🌴 Sync 2026-03-05 23:51:42
No files matched your search
@@ -0,0 +1,37 @@
|
||||
#=====================================================================================================
|
||||
# This file is licensed under the terms of the GNU General Public
|
||||
# License version 2. This program is licensed "as is" without any
|
||||
# warranty of any kind, whether express or implied.
|
||||
#
|
||||
# This file is a part of the luci-app-amlogic plugin
|
||||
# https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Description: Supports install/update/backup/restore/snapshot operations using OpenWrt on many boxes
|
||||
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Command: curl -fsSL git.io/luci-app-amlogic | bash
|
||||
#=====================================================================================================
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-amlogic
|
||||
PKG_VERSION:=3.1.286
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0 License
|
||||
PKG_MAINTAINER:=ophub <https://github.com/ophub/luci-app-amlogic>
|
||||
|
||||
LUCI_TITLE:=LuCI support for Amlogic, Allwinner and Rockchip related boxs
|
||||
LUCI_PKGARCH:=all
|
||||
LUCI_DEPENDS:= \
|
||||
@(aarch64||arm) +bash +blkid +block-mount +curl +dosfstools +e2fsprogs \
|
||||
+fdisk +jq +losetup +lsblk +parted +perl +pv +uuidgen
|
||||
|
||||
define Package/$(PKG_NAME)/conffiles
|
||||
/etc/config/amlogic
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="175" height="20" role="img" aria-label="OpenWrt: Compiler author"><title>OpenWrt: Compiler author</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="175" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="76" height="20" fill="#555"/><rect x="76" width="99" height="20" fill="#4c1"/><rect width="175" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="475" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="490">OpenWrt</text><text x="475" y="140" transform="scale(.1)" fill="#fff" textLength="490">OpenWrt</text><text aria-hidden="true" x="1245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="890">Compiler author</text><text x="1245" y="140" transform="scale(.1)" fill="#fff" textLength="890">Compiler author</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="187" height="20" role="img" aria-label="OpenWrt: flippy's homepage"><title>OpenWrt: flippy's homepage</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="187" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="76" height="20" fill="#555"/><rect x="76" width="111" height="20" fill="blueviolet"/><rect width="187" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="475" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="490">OpenWrt</text><text x="475" y="140" transform="scale(.1)" fill="#fff" textLength="490">OpenWrt</text><text aria-hidden="true" x="1305" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1010">flippy's homepage</text><text x="1305" y="140" transform="scale(.1)" fill="#fff" textLength="1010">flippy's homepage</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="161" height="20" role="img" aria-label="Plugin: luci-app-amlogic"><title>Plugin: luci-app-amlogic</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="161" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="60" height="20" fill="#555"/><rect x="60" width="101" height="20" fill="#007ec6"/><rect width="161" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="395" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">Plugin</text><text x="395" y="140" transform="scale(.1)" fill="#fff" textLength="330">Plugin</text><text aria-hidden="true" x="1095" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="910">luci-app-amlogic</text><text x="1095" y="140" transform="scale(.1)" fill="#fff" textLength="910">luci-app-amlogic</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,557 @@
|
||||
module("luci.controller.amlogic", package.seeall)
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local PKG_NAME = "luci-app-amlogic"
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/amlogic") then
|
||||
return
|
||||
end
|
||||
|
||||
local page = entry({ "admin", "system", "amlogic" }, alias("admin", "system", "amlogic", "info"), _("Amlogic Service"), 88)
|
||||
page.dependent = true
|
||||
page.acl_depends = { PKG_NAME }
|
||||
|
||||
local platfrom = luci.sys.exec("cat /etc/flippy-openwrt-release 2>/dev/null | grep PLATFORM | awk -F'=' '{print $2}' | grep -oE '(amlogic|rockchip|allwinner|qemu)' | xargs") or "Unknown"
|
||||
local install_menu = luci.sys.exec("cat /etc/flippy-openwrt-release 2>/dev/null | grep SHOW_INSTALL_MENU | awk -F'=' '{print $2}' | grep -oE '(yes|no)' | xargs") or "Unknown"
|
||||
|
||||
entry({ "admin", "system", "amlogic", "info" }, form("amlogic/amlogic_info"), _("Amlogic Service"), 1).leaf = true
|
||||
if (string.find(platfrom, "amlogic")) ~= nil or (string.find(install_menu, "yes")) ~= nil then
|
||||
entry({ "admin", "system", "amlogic", "install" }, form("amlogic/amlogic_install"), _("Install OpenWrt"), 2).leaf = true
|
||||
end
|
||||
entry({ "admin", "system", "amlogic", "upload" }, form("amlogic/amlogic_upload"), _("Manually Upload Update"), 3).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "check" }, form("amlogic/amlogic_check"), _("Online Download Update"), 4).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "backup" }, form("amlogic/amlogic_backup"), _("Backup Firmware Config"), 5).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "backuplist" }, form("amlogic/amlogic_backuplist")).leaf = true
|
||||
if (string.find(platfrom, "qemu")) == nil then
|
||||
entry({ "admin", "system", "amlogic", "armcpu" }, cbi("amlogic/amlogic_armcpu"), _("CPU Settings"), 6).leaf = true
|
||||
end
|
||||
entry({ "admin", "system", "amlogic", "config" }, cbi("amlogic/amlogic_config"), _("Plugin Settings"), 7).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "log" }, form("amlogic/amlogic_log"), _("Server Logs"), 8).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "poweroff" }, form("amlogic/amlogic_poweroff"), _("PowerOff"), 9).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "check_firmware" }, call("action_check_firmware"))
|
||||
entry({ "admin", "system", "amlogic", "check_plugin" }, call("action_check_plugin"))
|
||||
entry({ "admin", "system", "amlogic", "check_kernel" }, call("action_check_kernel"))
|
||||
entry({ "admin", "system", "amlogic", "refresh_log" }, call("action_refresh_log"))
|
||||
entry({ "admin", "system", "amlogic", "del_log" }, call("action_del_log"))
|
||||
entry({ "admin", "system", "amlogic", "start_model_database" }, call("action_check_model_database")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_check_install" }, call("action_start_check_install")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_check_firmware" }, call("action_start_check_firmware")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_check_plugin" }, call("action_start_check_plugin")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_check_kernel" }, call("action_start_check_kernel")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_check_rescue" }, call("action_start_check_rescue")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_check_upfiles" }, call("action_start_check_upfiles")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_amlogic_install" }, call("action_start_amlogic_install")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_amlogic_update" }, call("action_start_amlogic_update")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_amlogic_kernel" }, call("action_start_amlogic_kernel")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_amlogic_plugin" }, call("action_start_amlogic_plugin")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_amlogic_rescue" }, call("action_start_amlogic_rescue")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_snapshot_delete" }, call("action_start_snapshot_delete")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_snapshot_restore" }, call("action_start_snapshot_restore")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_snapshot_list" }, call("action_check_snapshot")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_openwrt_author" }, call("action_openwrt_author")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "state" }, call("action_state")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_poweroff" }, call("action_poweroff")).leaf = true
|
||||
entry({ "admin", "system", "amlogic", "start_switch" }, call("action_switch")).leaf = true
|
||||
end
|
||||
|
||||
--Remove the spaces in the string
|
||||
function trim(str)
|
||||
--return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
|
||||
return (string.gsub(str, "%s+", ""))
|
||||
end
|
||||
|
||||
--Create a temporary folder
|
||||
local tmp_upload_dir = luci.sys.exec("[ -d /tmp/upload ] || mkdir -p /tmp/upload >/dev/null")
|
||||
local tmp_amlogic_dir = luci.sys.exec("[ -d /tmp/amlogic ] || mkdir -p /tmp/amlogic >/dev/null")
|
||||
|
||||
--Whether to automatically restore the firmware config
|
||||
local amlogic_firmware_config = luci.sys.exec("uci get amlogic.config.amlogic_firmware_config 2>/dev/null") or "1"
|
||||
if tonumber(amlogic_firmware_config) == 0 then
|
||||
update_restore_config = "no-restore"
|
||||
else
|
||||
update_restore_config = "restore"
|
||||
end
|
||||
|
||||
--Whether to automatically write to the bootLoader
|
||||
local amlogic_write_bootloader = luci.sys.exec("uci get amlogic.config.amlogic_write_bootloader 2>/dev/null") or "1"
|
||||
if tonumber(amlogic_write_bootloader) == 0 then
|
||||
auto_write_bootloader = "no"
|
||||
else
|
||||
auto_write_bootloader = "yes"
|
||||
end
|
||||
|
||||
--Set the file system type of the shared partition
|
||||
local amlogic_shared_fstype = luci.sys.exec("uci get amlogic.config.amlogic_shared_fstype 2>/dev/null") or ""
|
||||
if trim(amlogic_shared_fstype) == "" then
|
||||
auto_shared_fstype = "ext4"
|
||||
else
|
||||
auto_shared_fstype = trim(amlogic_shared_fstype)
|
||||
end
|
||||
|
||||
--Device identification
|
||||
device_platfrom = luci.sys.exec("cat /etc/flippy-openwrt-release 2>/dev/null | grep PLATFORM | awk -F'=' '{print $2}' | grep -oE '(amlogic|rockchip|allwinner|qemu)' | xargs") or "Unknown"
|
||||
if (string.find(device_platfrom, "rockchip")) ~= nil then
|
||||
device_install_script = ""
|
||||
device_update_script = "openwrt-update-rockchip"
|
||||
device_kernel_script = "openwrt-kernel"
|
||||
elseif (string.find(device_platfrom, "allwinner")) ~= nil then
|
||||
device_install_script = "openwrt-install-allwinner"
|
||||
device_update_script = "openwrt-update-allwinner"
|
||||
device_kernel_script = "openwrt-kernel"
|
||||
elseif (string.find(device_platfrom, "qemu")) ~= nil then
|
||||
device_install_script = ""
|
||||
device_update_script = "openwrt-update-kvm"
|
||||
device_kernel_script = "openwrt-kernel"
|
||||
else
|
||||
device_install_script = "openwrt-install-amlogic"
|
||||
device_update_script = "openwrt-update-amlogic"
|
||||
device_kernel_script = "openwrt-kernel"
|
||||
end
|
||||
|
||||
--General array functions
|
||||
function string.split(input, delimiter)
|
||||
input = tostring(input)
|
||||
delimiter = tostring(delimiter)
|
||||
if (delimiter == '') then return false end
|
||||
local pos, arr = 0, {}
|
||||
-- for each divider found
|
||||
for st, sp in function() return string.find(input, delimiter, pos, true) end do
|
||||
table.insert(arr, string.sub(input, pos, st - 1))
|
||||
pos = sp + 1
|
||||
end
|
||||
table.insert(arr, string.sub(input, pos))
|
||||
return arr
|
||||
end
|
||||
|
||||
--Refresh the log
|
||||
function action_refresh_log()
|
||||
local logfile = "/tmp/amlogic/amlogic.log"
|
||||
if not nixio.fs.access(logfile) then
|
||||
luci.sys.exec("uname -a > /tmp/amlogic/amlogic.log && sync")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_install.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_upfiles.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_plugin.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_kernel.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_firmware.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_rescue.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_running_script.log && sync >/dev/null 2>&1")
|
||||
end
|
||||
luci.http.prepare_content("text/plain; charset=utf-8")
|
||||
local f = io.open(logfile, "r+")
|
||||
f:seek("set")
|
||||
local a = f:read(2048000) or ""
|
||||
f:close()
|
||||
luci.http.write(a)
|
||||
end
|
||||
|
||||
--Delete the logs
|
||||
function action_del_log()
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_check_install.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_check_upfiles.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_check_plugin.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_check_kernel.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_check_firmware.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_check_rescue.log")
|
||||
luci.sys.exec(": > /tmp/amlogic/amlogic_running_script.log")
|
||||
end
|
||||
|
||||
|
||||
--Upgrade luci-app-amlogic plugin
|
||||
function start_amlogic_plugin()
|
||||
local log_file = "/tmp/amlogic/amlogic_check_plugin.log"
|
||||
local running_lock = "/tmp/amlogic/amlogic_running_script.log"
|
||||
local config_file = "/etc/config/amlogic"
|
||||
local config_bak = "/etc/config/amlogic_bak"
|
||||
|
||||
-- 1. Create a running lock and clear previous log
|
||||
luci.sys.call("echo '1@Plugin update in progress, try again later!' > " .. running_lock .. " && > " .. log_file)
|
||||
|
||||
-- 2. Backup config file
|
||||
luci.sys.call(string.format("[ -f %s ] && cp -vf %s %s >> %s 2>&1", config_file, config_file, config_bak, log_file))
|
||||
|
||||
-- 3. Detect and install
|
||||
local install_status = 1
|
||||
if luci.sys.call("command -v opkg >/dev/null") == 0 then
|
||||
luci.sys.call("echo 'System uses opkg. Attempting to install .ipk package...' >> " .. log_file)
|
||||
local install_cmd = string.format("opkg --force-reinstall install /tmp/amlogic/*.ipk >> %s 2>&1", log_file)
|
||||
install_status = luci.sys.call(install_cmd)
|
||||
elseif luci.sys.call("command -v apk >/dev/null") == 0 then
|
||||
luci.sys.call("echo 'System uses apk. Attempting to install .apk package...' >> " .. log_file)
|
||||
local install_cmd = string.format("apk add --force-overwrite --allow-untrusted /tmp/amlogic/*.apk >> %s 2>&1", log_file)
|
||||
install_status = luci.sys.call(install_cmd)
|
||||
else
|
||||
luci.sys.call("echo 'Error: Neither opkg nor apk found. Aborting.' >> " .. log_file)
|
||||
end
|
||||
|
||||
-- 4. Check result and finalize
|
||||
if install_status == 0 then
|
||||
-- SUCCESS
|
||||
luci.sys.call("echo 'Installation successful. Finalizing...' >> " .. log_file)
|
||||
luci.sys.call(string.format("[ -f %s ] && cp -vf %s %s >> %s 2>&1", config_bak, config_bak, config_file, log_file))
|
||||
luci.sys.call("rm -rf /tmp/luci-indexcache /tmp/luci-modulecache/* " .. config_bak)
|
||||
luci.sys.call("echo '' > " .. running_lock)
|
||||
luci.sys.call("echo 'Successful Update' > " .. log_file)
|
||||
return 0
|
||||
else
|
||||
-- FAILURE
|
||||
luci.sys.call("echo '--- INSTALLATION FAILED! ---' >> " .. log_file)
|
||||
luci.sys.call("echo 'Restoring configuration and aborting.' >> " .. log_file)
|
||||
luci.sys.call(string.format("[ -f %s ] && cp -vf %s %s >> %s 2>&1", config_bak, config_bak, config_file, log_file))
|
||||
luci.sys.call("rm -f " .. config_bak)
|
||||
luci.sys.call("echo '' > " .. running_lock)
|
||||
return install_status
|
||||
end
|
||||
end
|
||||
|
||||
--Upgrade the kernel
|
||||
function start_amlogic_kernel()
|
||||
luci.sys.call("echo '2@Kernel update in progress, try again later!' > /tmp/amlogic/amlogic_running_script.log && sync >/dev/null 2>&1")
|
||||
luci.sys.call("chmod +x /usr/sbin/" .. device_kernel_script .. " >/dev/null 2>&1")
|
||||
local state = luci.sys.call("/usr/sbin/" .. device_kernel_script .. " " .. auto_write_bootloader .. " > /tmp/amlogic/amlogic_check_kernel.log && sync >/dev/null 2>&1")
|
||||
return state
|
||||
end
|
||||
|
||||
--Upgrade amlogic openwrt firmware
|
||||
function start_amlogic_update()
|
||||
luci.sys.call("echo '3@OpenWrt update in progress, try again later!' > /tmp/amlogic/amlogic_running_script.log && sync >/dev/null 2>&1")
|
||||
luci.sys.call("chmod +x /usr/sbin/" .. device_update_script .. " >/dev/null 2>&1")
|
||||
local amlogic_update_sel = luci.http.formvalue("amlogic_update_sel")
|
||||
local res = string.split(amlogic_update_sel, "@")
|
||||
local update_firmware_name = res[1] or "auto"
|
||||
local update_firmware_updated = res[2] or "updated"
|
||||
local update_write_path = res[3] or "/tmp"
|
||||
luci.sys.call("echo " .. update_firmware_updated .. " > " .. update_write_path .. "/.luci-app-amlogic/op_release_code 2>/dev/null && sync")
|
||||
local state = luci.sys.call("/usr/sbin/" .. device_update_script .. " " .. update_firmware_name .. " " .. auto_write_bootloader .. " " .. update_restore_config .. " > /tmp/amlogic/amlogic_check_firmware.log && sync 2>/dev/null")
|
||||
return state
|
||||
end
|
||||
|
||||
--Read rescue kernel log
|
||||
local function start_amlogic_rescue()
|
||||
luci.sys.call("echo '4@Kernel rescue in progress, try again later!' > /tmp/amlogic/amlogic_running_script.log && sync >/dev/null 2>&1")
|
||||
luci.sys.call("chmod +x /usr/sbin/" .. device_kernel_script .. " >/dev/null 2>&1")
|
||||
local state = luci.sys.call("/usr/sbin/" .. device_kernel_script .. " -s > /tmp/amlogic/amlogic_check_rescue.log && sync >/dev/null 2>&1")
|
||||
luci.sys.call("echo '' > /tmp/amlogic/amlogic_running_script.log && sync >/dev/null 2>&1")
|
||||
return state
|
||||
end
|
||||
|
||||
--Install amlogic openwrt firmware
|
||||
function start_amlogic_install()
|
||||
luci.sys.exec("chmod +x /usr/sbin/" .. device_install_script .. " >/dev/null 2>&1")
|
||||
local amlogic_install_sel = luci.http.formvalue("amlogic_install_sel")
|
||||
local res = string.split(amlogic_install_sel, "@")
|
||||
soc_id = res[1] or "99"
|
||||
if tonumber(res[1]) == 99 then
|
||||
dtb_filename = res[2] or "auto_dtb"
|
||||
else
|
||||
dtb_filename = "auto_dtb"
|
||||
end
|
||||
local state = luci.sys.call("/usr/sbin/" .. device_install_script .. " " .. auto_write_bootloader .. " " .. soc_id .. " " .. dtb_filename .. " " .. auto_shared_fstype .. " > /tmp/amlogic/amlogic_check_install.log && sync 2>/dev/null")
|
||||
return state
|
||||
end
|
||||
|
||||
--Delets the snapshot
|
||||
function start_snapshot_delete()
|
||||
local snapshot_delete_sel = luci.http.formvalue("snapshot_delete_sel")
|
||||
local state = luci.sys.exec("btrfs subvolume delete -c /.snapshots/" .. snapshot_delete_sel .. " 2>/dev/null && sync")
|
||||
return state
|
||||
end
|
||||
|
||||
--Restore to this snapshot
|
||||
function start_snapshot_restore()
|
||||
local snapshot_restore_sel = luci.http.formvalue("snapshot_restore_sel")
|
||||
local state = luci.sys.exec("btrfs subvolume snapshot /.snapshots/etc-" .. snapshot_restore_sel .. " /etc 2>/dev/null && sync")
|
||||
local state_nowreboot = luci.sys.exec("echo 'b' > /proc/sysrq-trigger 2>/dev/null")
|
||||
return state
|
||||
end
|
||||
|
||||
--Check the plugin
|
||||
function action_check_plugin()
|
||||
luci.sys.exec("chmod +x /usr/share/amlogic/amlogic_check_plugin.sh >/dev/null 2>&1")
|
||||
return luci.sys.call("/usr/share/amlogic/amlogic_check_plugin.sh >/dev/null 2>&1")
|
||||
end
|
||||
|
||||
--Check and download the kernel
|
||||
function check_kernel()
|
||||
luci.sys.exec("chmod +x /usr/share/amlogic/amlogic_check_kernel.sh >/dev/null 2>&1")
|
||||
local kernel_options = luci.http.formvalue("kernel_options")
|
||||
if kernel_options == "check" then
|
||||
local state = luci.sys.call("/usr/share/amlogic/amlogic_check_kernel.sh -check >/dev/null 2>&1")
|
||||
else
|
||||
local state = luci.sys.call("/usr/share/amlogic/amlogic_check_kernel.sh -download " .. kernel_options .. " >/dev/null 2>&1")
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
--Check the kernel
|
||||
function action_check_kernel()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
check_kernel_status = check_kernel();
|
||||
})
|
||||
end
|
||||
|
||||
--Check the firmware
|
||||
function check_firmware()
|
||||
luci.sys.exec("chmod +x /usr/share/amlogic/amlogic_check_firmware.sh >/dev/null 2>&1")
|
||||
local firmware_options = luci.http.formvalue("firmware_options")
|
||||
if firmware_options == "check" then
|
||||
local state = luci.sys.call("/usr/share/amlogic/amlogic_check_firmware.sh -check >/dev/null 2>&1")
|
||||
else
|
||||
local state = luci.sys.call("/usr/share/amlogic/amlogic_check_firmware.sh -download " .. firmware_options .. " >/dev/null 2>&1")
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
--Check the openwrt firmware version online
|
||||
function action_check_firmware()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
check_firmware_status = check_firmware();
|
||||
})
|
||||
end
|
||||
|
||||
--Read upload files log
|
||||
local function start_check_upfiles()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/amlogic/amlogic_check_upfiles.log 2>/dev/null")
|
||||
end
|
||||
|
||||
--Read plug-in check log
|
||||
local function start_check_plugin()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/amlogic/amlogic_check_plugin.log 2>/dev/null")
|
||||
end
|
||||
|
||||
--Read kernel check log
|
||||
local function start_check_kernel()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/amlogic/amlogic_check_kernel.log 2>/dev/null")
|
||||
end
|
||||
|
||||
--Read openwrt firmware check log
|
||||
local function start_check_firmware()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/amlogic/amlogic_check_firmware.log 2>/dev/null")
|
||||
end
|
||||
|
||||
--Read rescue kernel log
|
||||
local function start_check_rescue()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/amlogic/amlogic_check_rescue.log 2>/dev/null")
|
||||
end
|
||||
|
||||
--Read openwrt install log
|
||||
local function start_check_install()
|
||||
return luci.sys.exec("sed -n '$p' /tmp/amlogic/amlogic_check_install.log 2>/dev/null")
|
||||
end
|
||||
|
||||
--Return online check plugin result
|
||||
function action_start_check_plugin()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_check_plugin = start_check_plugin();
|
||||
})
|
||||
end
|
||||
|
||||
--Return online check kernel result
|
||||
function action_start_check_kernel()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_check_kernel = start_check_kernel();
|
||||
})
|
||||
end
|
||||
|
||||
--Return online check openwrt firmware result
|
||||
function action_start_check_firmware()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_check_firmware = start_check_firmware();
|
||||
})
|
||||
end
|
||||
|
||||
--Return online check rescue kernel result
|
||||
function action_start_check_rescue()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_check_rescue = start_check_rescue();
|
||||
})
|
||||
end
|
||||
|
||||
--Return online install openwrt result
|
||||
function action_start_check_install()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_check_install = start_check_install();
|
||||
})
|
||||
end
|
||||
|
||||
--Return online install openwrt result for amlogic
|
||||
function action_start_amlogic_install()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
rule_install_status = start_amlogic_install();
|
||||
})
|
||||
end
|
||||
|
||||
--Return snapshot delete result
|
||||
function action_start_snapshot_delete()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
rule_delete_status = start_snapshot_delete();
|
||||
})
|
||||
end
|
||||
|
||||
--Return snapshot restore result
|
||||
function action_start_snapshot_restore()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
rule_restore_status = start_snapshot_restore();
|
||||
})
|
||||
end
|
||||
|
||||
--Return openwrt update result for amlogic
|
||||
function action_start_amlogic_update()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
rule_update_status = start_amlogic_update();
|
||||
})
|
||||
end
|
||||
|
||||
--Return kernel update result
|
||||
function action_start_amlogic_kernel()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
rule_kernel_status = start_amlogic_kernel();
|
||||
})
|
||||
end
|
||||
|
||||
--Return plugin update result
|
||||
function action_start_amlogic_plugin()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
rule_plugin_status = start_amlogic_plugin();
|
||||
})
|
||||
end
|
||||
|
||||
--Return rescue kernel result
|
||||
function action_start_amlogic_rescue()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_amlogic_rescue = start_amlogic_rescue();
|
||||
})
|
||||
end
|
||||
|
||||
--Return files upload result
|
||||
function action_start_check_upfiles()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
start_check_upfiles = start_check_upfiles();
|
||||
})
|
||||
end
|
||||
|
||||
--Return the current openwrt firmware version
|
||||
local function current_firmware_version()
|
||||
return luci.sys.exec("uname -r 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+'") or "Invalid value."
|
||||
end
|
||||
|
||||
--Return the current plugin version
|
||||
local function current_plugin_version()
|
||||
local version_str = ""
|
||||
|
||||
-- Check if opkg command exists
|
||||
if sys.call("command -v opkg >/dev/null") == 0 then
|
||||
local opkg_cmd = string.format("opkg list-installed | grep '^%s' | awk '{print $3}' | cut -d'-' -f1", PKG_NAME)
|
||||
version_str = trim(sys.exec(opkg_cmd))
|
||||
end
|
||||
|
||||
-- If opkg failed or not found, check if apk command exists
|
||||
if version_str == "" and sys.call("command -v apk >/dev/null") == 0 then
|
||||
local apk_cmd = string.format("apk list --installed 2>/dev/null | grep '^%s' | awk '{print $1}' | cut -d'-' -f4", PKG_NAME)
|
||||
version_str = trim(sys.exec(apk_cmd))
|
||||
end
|
||||
|
||||
if version_str ~= "" then
|
||||
return version_str
|
||||
else
|
||||
return "Invalid value."
|
||||
end
|
||||
end
|
||||
|
||||
--Return the current kernel version
|
||||
local function current_kernel_version()
|
||||
return luci.sys.exec("uname -r 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+'") or "Invalid value."
|
||||
end
|
||||
|
||||
--Return the current kernel branch
|
||||
local function current_kernel_branch()
|
||||
local default_kernel_branch = luci.sys.exec("uname -r 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}'")
|
||||
local amlogic_kernel_branch = luci.sys.exec("uci get amlogic.config.amlogic_kernel_branch 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}'") or ""
|
||||
if trim(amlogic_kernel_branch) == "" then
|
||||
return default_kernel_branch
|
||||
else
|
||||
return amlogic_kernel_branch
|
||||
end
|
||||
end
|
||||
|
||||
--Return current version information
|
||||
function action_state()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
current_firmware_version = current_firmware_version(),
|
||||
current_plugin_version = current_plugin_version(),
|
||||
current_kernel_version = current_kernel_version(),
|
||||
current_kernel_branch = current_kernel_branch();
|
||||
})
|
||||
end
|
||||
|
||||
--Read external model database
|
||||
local function my_model_database()
|
||||
if (string.find(device_platfrom, "allwinner")) ~= nil then
|
||||
return luci.sys.exec("cat /etc/model_database.txt 2>/dev/null | grep -E '^w[0-9]{1,9}.*:' | awk -F ':' '{print $1,$2}' OFS='###' ORS='@@@' | tr ' ' '~' 2>&1")
|
||||
else
|
||||
return luci.sys.exec("cat /etc/model_database.txt 2>/dev/null | grep -E '^[0-9]{1,9}.*:' | awk -F ':' '{print $1,$2}' OFS='###' ORS='@@@' | tr ' ' '~' 2>&1")
|
||||
end
|
||||
end
|
||||
|
||||
--Return external model database
|
||||
function action_check_model_database()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
my_model_database = my_model_database();
|
||||
})
|
||||
end
|
||||
|
||||
--Return the current snapshot list
|
||||
local function current_snapshot()
|
||||
return luci.sys.exec("btrfs subvolume list -rt / | awk '{print $4}' | grep .snapshots") or "Invalid value."
|
||||
end
|
||||
|
||||
--Return current snapshot information
|
||||
function action_check_snapshot()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
current_snapshot = current_snapshot();
|
||||
})
|
||||
end
|
||||
|
||||
--Return the openwrt compile author
|
||||
local function openwrt_author()
|
||||
return luci.sys.exec("uci get amlogic.config.amlogic_firmware_repo 2>/dev/null") or "Invalid value."
|
||||
end
|
||||
|
||||
--Return current snapshot information
|
||||
function action_openwrt_author()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
openwrt_author = openwrt_author();
|
||||
})
|
||||
end
|
||||
|
||||
--Shut down the router
|
||||
function action_poweroff()
|
||||
luci.sys.exec("/sbin/poweroff")
|
||||
end
|
||||
|
||||
--Switching dual partition
|
||||
function action_switch()
|
||||
luci.sys.exec("[ -f /boot/efi/EFI/BOOT/grub.cfg.prev ] && (cd /boot/efi/EFI/BOOT/ && mv -f grub.cfg grub.cfg.bak && mv -f grub.cfg.prev grub.cfg && mv -f grub.cfg.bak grub.cfg.prev)")
|
||||
luci.sys.exec("sync && reboot")
|
||||
end
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
--Copyright: https://github.com/coolsnowwolf/luci/tree/master/applications/luci-app-cpufreq
|
||||
--Planner: https://github.com/unifreq/openwrt_packit
|
||||
--Extended support: https://github.com/ophub/luci-app-amlogic
|
||||
--Function: Support multi-core
|
||||
|
||||
local mp
|
||||
|
||||
--Remove the spaces in the string
|
||||
function trim(str)
|
||||
--return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
|
||||
return (string.gsub(str, "%s+", ""))
|
||||
end
|
||||
|
||||
--split
|
||||
function string.split(e, t)
|
||||
e = tostring(e)
|
||||
t = tostring(t)
|
||||
if (t == '') then return false end
|
||||
local a, o = 0, {}
|
||||
for i, t in function() return string.find(e, t, a, true) end do
|
||||
table.insert(o, string.sub(e, a, i - 1))
|
||||
a = t + 1
|
||||
end
|
||||
table.insert(o, string.sub(e, a))
|
||||
return o
|
||||
end
|
||||
|
||||
--Auto-complete node
|
||||
local check_config_settings = luci.sys.exec("uci get amlogic.@settings[0].governor0 2>/dev/null") or ""
|
||||
if (trim(check_config_settings) == "") then
|
||||
luci.sys.exec("uci delete amlogic.@settings[0] 2>/dev/null")
|
||||
luci.sys.exec("uci set amlogic.armcpu='settings' 2>/dev/null")
|
||||
luci.sys.exec("uci commit amlogic 2>/dev/null")
|
||||
end
|
||||
|
||||
mp = Map("amlogic")
|
||||
mp.title = translate("CPU Freq Settings")
|
||||
mp.description = translate("Set CPU Scaling Governor to Max Performance or Balance Mode")
|
||||
|
||||
s = mp:section(NamedSection, "armcpu", "settings")
|
||||
s.anonymouse = true
|
||||
|
||||
local cpu_policys = luci.sys.exec("ls /sys/devices/system/cpu/cpufreq | grep -E 'policy[0-9]{1,3}' | xargs") or "policy0"
|
||||
policy_array = string.split(cpu_policys, " ")
|
||||
|
||||
for tt, policy_name in ipairs(policy_array) do
|
||||
|
||||
--Dynamic tab, automatically changes according to the number of cores, begin ------
|
||||
policy_name = tostring(trim(policy_name))
|
||||
policy_id = tostring(trim(string.gsub(policy_name, "policy", "")))
|
||||
|
||||
tab_name = policy_name
|
||||
tab_id = tostring(trim("tab" .. policy_id))
|
||||
|
||||
cpu_freqs = nixio.fs.readfile(trim("/sys/devices/system/cpu/cpufreq/" .. policy_name .. "/scaling_available_frequencies")) or "100000"
|
||||
cpu_freqs = string.sub(cpu_freqs, 1, -3)
|
||||
cpu_governors = nixio.fs.readfile(trim("/sys/devices/system/cpu/cpufreq/" .. policy_name .. "/scaling_available_governors")) or "performance"
|
||||
cpu_governors = string.sub(cpu_governors, 1, -3)
|
||||
freq_array = string.split(cpu_freqs, " ")
|
||||
governor_array = string.split(cpu_governors, " ")
|
||||
|
||||
s:tab(tab_id, tab_name)
|
||||
|
||||
tab_core_type = s:taboption(tab_id, DummyValue, trim("core_type" .. policy_id), translate("Microarchitectures:"))
|
||||
tab_core_type.default = luci.sys.exec("cat /sys/devices/system/cpu/cpu" .. policy_id .. "/uevent | grep -E '^OF_COMPATIBLE_0.*' | tr -d 'OF_COMPATIBLE_0=' | xargs") or "Unknown"
|
||||
tab_core_type.rmempty = false
|
||||
|
||||
governor = s:taboption(tab_id, ListValue, trim("governor" .. policy_id), translate("CPU Scaling Governor:"))
|
||||
for t, e in ipairs(governor_array) do
|
||||
if e ~= "" then governor:value(e, translate(e, string.upper(e))) end
|
||||
end
|
||||
governor.default = "schedutil"
|
||||
governor.rmempty = false
|
||||
|
||||
minfreq = s:taboption(tab_id, ListValue, trim("minfreq" .. policy_id), translate("Min Freq:"))
|
||||
for t, e in ipairs(freq_array) do
|
||||
if e ~= "" then minfreq:value(e) end
|
||||
end
|
||||
minfreq.default = "500000"
|
||||
minfreq.rmempty = false
|
||||
|
||||
maxfreq = s:taboption(tab_id, ListValue, trim("maxfreq" .. policy_id), translate("Max Freq:"))
|
||||
for t, e in ipairs(freq_array) do
|
||||
if e ~= "" then maxfreq:value(e) end
|
||||
end
|
||||
maxfreq.default = "1512000"
|
||||
maxfreq.rmempty = false
|
||||
|
||||
--Dynamic tab, automatically changes according to the number of cores, end ------
|
||||
|
||||
end
|
||||
|
||||
-- Apply the settings to the system
|
||||
function mp.on_after_commit(self)
|
||||
luci.sys.exec("(sleep 2 && /etc/init.d/amlogic start) >/dev/null 2>&1 &")
|
||||
end
|
||||
|
||||
return mp
|
||||
@@ -0,0 +1,151 @@
|
||||
--Copyright: https://github.com/coolsnowwolf/luci/tree/master/applications/luci-app-filetransfer
|
||||
--Extended support: https://github.com/ophub/luci-app-amlogic
|
||||
--Function: Download files
|
||||
|
||||
local io = require "io"
|
||||
local os = require "os"
|
||||
local fs = require "nixio.fs"
|
||||
local b, c, x
|
||||
|
||||
-- Checks wheather the given path exists and points to a directory.
|
||||
function isdirectory(dirname)
|
||||
return fs.stat(dirname, "type") == "dir"
|
||||
end
|
||||
|
||||
-- Check if a file or directory exists
|
||||
function file_exists(path)
|
||||
local file = io.open(path, "rb")
|
||||
if file then file:close() end
|
||||
return file ~= nil
|
||||
end
|
||||
|
||||
--SimpleForm for Backup Config
|
||||
b = SimpleForm("backup", nil)
|
||||
b.title = translate("Backup Firmware Config")
|
||||
b.description = translate("Backup OpenWrt config (openwrt_config.tar.gz). Use this file to restore the config in [Manually Upload Update].")
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
s = b:section(SimpleSection, "", "")
|
||||
|
||||
-- Button for customize backup list
|
||||
my = s:option(Button, "customize", translate("Edit List:"))
|
||||
my.template = "amlogic/other_button"
|
||||
|
||||
my.render = function(self, section, scope)
|
||||
self.section = true
|
||||
scope.display = ""
|
||||
self.inputtitle = translate("Open List")
|
||||
self.inputstyle = "save"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
my.write = function(self, section, scope)
|
||||
local handle = io.popen("[[ -s /etc/amlogic_backup_list.conf ]] || sed -n \"/BACKUP_LIST='/,/.*'$/p\" /usr/sbin/openwrt-backup | sed -e \"s/BACKUP_LIST=\\(.*\\)/\\1/; s/'//g; s/\\\\\\\\//g; s/ //g\" > /etc/amlogic_backup_list.conf 2>/dev/null")
|
||||
handle:close()
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "system", "amlogic", "backuplist"))
|
||||
end
|
||||
|
||||
-- Button for download backup config
|
||||
o = s:option(Button, "download", translate("Backup Config:"))
|
||||
o.template = "amlogic/other_button"
|
||||
|
||||
um = s:option(DummyValue, "", nil)
|
||||
um.template = "amlogic/other_dvalue"
|
||||
|
||||
o.render = function(self, section, scope)
|
||||
self.section = true
|
||||
scope.display = ""
|
||||
self.inputtitle = translate("Download Backup")
|
||||
self.inputstyle = "save"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
o.write = function(self, section, scope)
|
||||
local x = luci.sys.exec("chmod +x /usr/sbin/openwrt-backup 2>/dev/null")
|
||||
local r = luci.sys.exec("/usr/sbin/openwrt-backup -b > /tmp/amlogic/amlogic.log && sync 2>/dev/null")
|
||||
|
||||
local sPath, sFile, fd, block
|
||||
sPath = "/.reserved/openwrt_config.tar.gz"
|
||||
sFile = fs.basename(sPath)
|
||||
if isdirectory(sPath) then
|
||||
fd = io.popen('tar -C "%s" -cz .' % { sPath }, "r")
|
||||
sFile = sFile .. ".tar.gz"
|
||||
else
|
||||
fd = nixio.open(sPath, "r")
|
||||
end
|
||||
if not fd then
|
||||
um.value = translate("Couldn't open file:") .. sPath
|
||||
return
|
||||
else
|
||||
um.value = translate("The file Will download automatically.") .. sPath
|
||||
end
|
||||
|
||||
luci.http.header('Content-Disposition', 'attachment; filename="%s"' % { sFile })
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
while true do
|
||||
block = fd:read(nixio.const.buffersize)
|
||||
if (not block) or (#block == 0) then
|
||||
break
|
||||
else
|
||||
luci.http.write(block)
|
||||
end
|
||||
end
|
||||
fd:close()
|
||||
luci.http.close()
|
||||
end
|
||||
|
||||
-- Button for restore backup list
|
||||
r = s:option(Button, "restore", translate("Restore Backup:"))
|
||||
r.template = "amlogic/other_button"
|
||||
|
||||
r.render = function(self, section, scope)
|
||||
self.section = true
|
||||
scope.display = ""
|
||||
self.inputtitle = translate("Upload Backup")
|
||||
self.inputstyle = "save"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
r.write = function(self, section, scope)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "system", "amlogic", "upload"))
|
||||
end
|
||||
|
||||
-- SimpleForm for Create Snapshot
|
||||
c = SimpleForm("snapshot", nil)
|
||||
c.title = translate("Snapshot Management")
|
||||
c.description = translate("Create a snapshot of the current system configuration, or restore to a snapshot.")
|
||||
c.reset = false
|
||||
c.submit = false
|
||||
|
||||
d = c:section(SimpleSection, "", nil)
|
||||
|
||||
w = d:option(Button, "create_snapshot", "")
|
||||
w.template = "amlogic/other_button"
|
||||
w.render = function(self, section, scope)
|
||||
self.section = true
|
||||
scope.display = ""
|
||||
self.inputtitle = translate("Create Snapshot")
|
||||
self.inputstyle = "save"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
w.write = function(self, section, scope)
|
||||
local x = luci.sys.exec("btrfs subvolume snapshot -r /etc /.snapshots/etc-" .. os.date("%m.%d.%H%M%S") .. " 2>/dev/null && sync")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "system", "amlogic", "backup"))
|
||||
end
|
||||
w = d:option(TextValue, "snapshot_list", nil)
|
||||
w.template = "amlogic/other_snapshot"
|
||||
|
||||
--KVM virtual machine switching dual partition
|
||||
if file_exists("/boot/efi/EFI/BOOT/grub.cfg.prev") then
|
||||
x = SimpleForm("kvm", nil)
|
||||
x.title = translate("KVM dual system switching")
|
||||
x.description = translate("You can freely switch between KVM dual partitions, using OpenWrt systems in different partitions.")
|
||||
x.reset = false
|
||||
x.submit = false
|
||||
|
||||
x:section(SimpleSection).template = "amlogic/other_kvm"
|
||||
end
|
||||
|
||||
return b, c, x
|
||||
@@ -0,0 +1,51 @@
|
||||
local fs = require "nixio.fs"
|
||||
local backup_list_conf = "/etc/amlogic_backup_list.conf"
|
||||
|
||||
-- Delete all spaces and tabs at the beginning of the line, and the unified line break is \n
|
||||
function remove_spaces(value)
|
||||
local lines = {}
|
||||
for line in value:gmatch("[^\r\n]+") do
|
||||
line = line:gsub("^%s*", "")
|
||||
if line ~= "" then
|
||||
table.insert(lines, line)
|
||||
end
|
||||
end
|
||||
value = table.concat(lines, "\n")
|
||||
value = value:gsub("[\r\n]+", "\n")
|
||||
return value
|
||||
end
|
||||
|
||||
-- Remove backslash at the end of each line
|
||||
function remove_backslash_at_end(value)
|
||||
local lines = {}
|
||||
for line in value:gmatch("[^\r\n]+") do
|
||||
line = line:gsub("%s*\\%s*$", "")
|
||||
table.insert(lines, line)
|
||||
end
|
||||
return table.concat(lines, "\n")
|
||||
end
|
||||
|
||||
local f = SimpleForm("customize",
|
||||
translate("Backup Configuration - Custom List"),
|
||||
translate("Write one configuration item per line, and directories should end with a /."))
|
||||
|
||||
local o = f:field(Value, "_custom")
|
||||
|
||||
o.template = "cbi/tvalue"
|
||||
o.rows = 30
|
||||
|
||||
function o.cfgvalue(self, section)
|
||||
local readconf = fs.readfile(backup_list_conf)
|
||||
local value = remove_spaces(readconf)
|
||||
local value = remove_backslash_at_end(value)
|
||||
return value
|
||||
end
|
||||
|
||||
function o.write(self, section, value)
|
||||
local value = remove_spaces(value)
|
||||
local value = remove_backslash_at_end(value)
|
||||
fs.writefile(backup_list_conf, value)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin", "system", "amlogic", "backup"))
|
||||
end
|
||||
|
||||
return f
|
||||
@@ -0,0 +1,22 @@
|
||||
local b, c
|
||||
|
||||
--SimpleForm for Check
|
||||
b = SimpleForm("amlogic", nil)
|
||||
b.title = translate("Check Update")
|
||||
b.description = translate("Provide OpenWrt Firmware, Kernel and Plugin online check, download and update service.")
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
b:section(SimpleSection).template = "amlogic/other_check"
|
||||
|
||||
|
||||
--SimpleForm for Rescue Kernel
|
||||
c = SimpleForm("rescue", nil)
|
||||
c.title = translate("Rescue Kernel")
|
||||
c.description = translate("When a kernel update fails and causes the OpenWrt system to be unbootable, the kernel can be restored by mutual recovery from eMMC/NVMe/sdX.")
|
||||
c.reset = false
|
||||
c.submit = false
|
||||
|
||||
c:section(SimpleSection).template = "amlogic/other_rescue"
|
||||
|
||||
return b, c
|
||||
@@ -0,0 +1,156 @@
|
||||
--Remove the spaces in the string
|
||||
function trim(str)
|
||||
--return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
|
||||
return (string.gsub(str, "%s+", ""))
|
||||
end
|
||||
|
||||
--Auto-complete node
|
||||
local check_config_amlogic = luci.sys.exec("uci get amlogic.@amlogic[0].amlogic_firmware_repo 2>/dev/null") or ""
|
||||
if (trim(check_config_amlogic) == "") then
|
||||
luci.sys.exec("uci delete amlogic.@amlogic[0] 2>/dev/null")
|
||||
luci.sys.exec("uci set amlogic.config='amlogic' 2>/dev/null")
|
||||
luci.sys.exec("uci commit amlogic 2>/dev/null")
|
||||
end
|
||||
|
||||
b = Map("amlogic")
|
||||
b.title = translate("Plugin Settings")
|
||||
local des_content = translate("You can customize the github.com download repository of OpenWrt files and kernels in [Online Download Update].")
|
||||
local des_content = des_content .. "<br />" .. translate("Tip: The same files as the current OpenWrt system's BOARD (such as rock5b) and kernel (such as 5.10) will be downloaded.")
|
||||
b.description = des_content
|
||||
|
||||
o = b:section(NamedSection, "config", "amlogic")
|
||||
o.anonymouse = true
|
||||
|
||||
--1.Set OpenWrt Firmware Repository
|
||||
mydevice = o:option(DummyValue, "mydevice", translate("Current Device:"))
|
||||
mydevice.description = translate("Display the PLATFORM classification of the device.")
|
||||
mydevice_platfrom = trim(luci.sys.exec("cat /etc/flippy-openwrt-release 2>/dev/null | grep PLATFORM | awk -F'=' '{print $2}' | grep -oE '(amlogic|rockchip|allwinner|qemu)'")) or "Unknown"
|
||||
mydevice.default = "PLATFORM: " .. mydevice_platfrom
|
||||
mydevice.rmempty = false
|
||||
|
||||
--2.Set OpenWrt Firmware Repository
|
||||
firmware_repo = o:option(Value, "amlogic_firmware_repo", translate("OpenWrt download repository:"))
|
||||
firmware_repo.description = translate("Set the OpenWrt files download repository on github.com in [Online Download Update].")
|
||||
firmware_repo.default = "https://github.com/breakingbadboy/OpenWrt"
|
||||
firmware_repo.rmempty = false
|
||||
|
||||
--3.Set OpenWrt Releases's Tag Keywords
|
||||
firmware_tag = o:option(Value, "amlogic_firmware_tag", translate("OpenWrt download tags keyword:"))
|
||||
firmware_tag.description = translate("Set the OpenWrt files download tags keyword for github.com in [Online Download Update].")
|
||||
firmware_tag.default = "ARMv8"
|
||||
firmware_tag.rmempty = false
|
||||
|
||||
--4.Set OpenWrt Firmware Suffix
|
||||
firmware_suffix = o:option(Value, "amlogic_firmware_suffix", translate("OpenWrt files suffix:"))
|
||||
firmware_suffix.description = translate("Set the OpenWrt files download suffix for github.com in [Online Download Update].")
|
||||
firmware_suffix:value(".7z", translate(".7z"))
|
||||
firmware_suffix:value(".zip", translate(".zip"))
|
||||
firmware_suffix:value(".img.gz", translate(".img.gz"))
|
||||
firmware_suffix:value(".img.xz", translate(".img.xz"))
|
||||
firmware_suffix.default = ".img.gz"
|
||||
firmware_suffix.rmempty = false
|
||||
|
||||
--5.Set OpenWrt Kernel DownLoad Path
|
||||
kernel_path = o:option(Value, "amlogic_kernel_path", translate("Kernel download repository:"))
|
||||
kernel_path.description = translate("Set the kernel files download repository on github.com in [Online Download Update].")
|
||||
kernel_path:value("https://github.com/breakingbadboy/OpenWrt")
|
||||
kernel_path:value("https://github.com/ophub/kernel")
|
||||
kernel_path.default = "https://github.com/breakingbadboy/OpenWrt"
|
||||
kernel_path.rmempty = false
|
||||
|
||||
--6. Set OpenWrt Kernel Tags
|
||||
-- Read the currently SAVED value of the kernel path.
|
||||
local current_kernel_path = trim(luci.sys.exec("uci get amlogic.@amlogic[0].amlogic_kernel_path 2>/dev/null") or "")
|
||||
-- If it's not set yet, use its default value for the logic below.
|
||||
if current_kernel_path == "" then
|
||||
current_kernel_path = kernel_path.default
|
||||
end
|
||||
-- Define the tag lists.
|
||||
-- The base list, available for all repositories.
|
||||
local known_tags = {
|
||||
kernel_rk3588 = "kernel_rk3588 [Rockchip RK3588 Kernel]",
|
||||
kernel_rk35xx = "kernel_rk35xx [Rockchip RK35xx Kernel]",
|
||||
kernel_stable = "kernel_stable [Mainline Stable Kernel]",
|
||||
}
|
||||
-- Additional tags only available for the 'ophub/kernel' repository.
|
||||
local ophub_extra_tags = {
|
||||
kernel_flippy = "kernel_flippy [Mainline Stable Kernel by Flippy]",
|
||||
kernel_h6 = "kernel_h6 [Allwinner H6 Kernel]",
|
||||
kernel_beta = "kernel_beta [Beta Kernel]",
|
||||
}
|
||||
-- Conditionally add the extra tags to the list.
|
||||
if (string.find(current_kernel_path, "ophub/kernel")) then
|
||||
for value, display_name in pairs(ophub_extra_tags) do
|
||||
known_tags[value] = display_name
|
||||
end
|
||||
end
|
||||
-- Determine the default kernel tag based on existing config or system info.
|
||||
local kernel_tagsname
|
||||
local existing_tag = trim(luci.sys.exec("uci get amlogic.@amlogic[0].amlogic_kernel_tags 2>/dev/null") or "")
|
||||
if existing_tag ~= "" then
|
||||
kernel_tagsname = existing_tag
|
||||
else
|
||||
local kernel_release_info = trim(luci.sys.exec("uname -r 2>/dev/null")) or ""
|
||||
|
||||
if (string.find(kernel_release_info, "-rk3588")) then
|
||||
kernel_tagsname = "kernel_rk3588"
|
||||
elseif (string.find(kernel_release_info, "-rk35xx")) then
|
||||
kernel_tagsname = "kernel_rk35xx"
|
||||
elseif (string.find(kernel_release_info, "-h6") or string.find(kernel_release_info, "-zicai")) then
|
||||
kernel_tagsname = "kernel_h6"
|
||||
else
|
||||
kernel_tagsname = "kernel_stable"
|
||||
end
|
||||
end
|
||||
-- Create the kernel tags option.
|
||||
kernel_tags = o:option(Value, "amlogic_kernel_tags", translate("Kernel download tags:"))
|
||||
kernel_tags.description = translate("Set the kernel files download tags on github.com in [Online Download Update].")
|
||||
-- Populate the dropdown with the known tags.
|
||||
for value, display_name in pairs(known_tags) do
|
||||
kernel_tags:value(value, translate(display_name))
|
||||
end
|
||||
-- Ensure the default tag is included in the options.
|
||||
if not known_tags[kernel_tagsname] then
|
||||
kernel_tags:value(kernel_tagsname, kernel_tagsname)
|
||||
end
|
||||
-- Set the default and other properties.
|
||||
kernel_tags.default = kernel_tagsname
|
||||
kernel_tags.rmempty = false
|
||||
|
||||
--7.Set kernel version branch
|
||||
kernel_branch = o:option(Value, "amlogic_kernel_branch", translate("Set version branch:"))
|
||||
kernel_branch.description = translate("Set the version branch of the OpenWrt files and kernel selected in [Online Download Update].")
|
||||
kernel_branch:value("5.4", translate("5.4"))
|
||||
kernel_branch:value("5.10", translate("5.10"))
|
||||
kernel_branch:value("5.15", translate("5.15"))
|
||||
kernel_branch:value("6.1", translate("6.1"))
|
||||
kernel_branch:value("6.6", translate("6.6"))
|
||||
kernel_branch:value("6.12", translate("6.12"))
|
||||
kernel_branch:value("6.18", translate("6.18"))
|
||||
local default_kernel_branch = luci.sys.exec("uname -r | grep -oE '^[1-9].[0-9]{1,3}'")
|
||||
kernel_branch.default = trim(default_kernel_branch)
|
||||
kernel_branch.rmempty = false
|
||||
|
||||
--8.Restore configuration
|
||||
firmware_config = o:option(Flag, "amlogic_firmware_config", translate("Keep config update:"))
|
||||
firmware_config.description = translate("Set whether to keep the current config during [Online Download Update] and [Manually Upload Update].")
|
||||
firmware_config.default = "1"
|
||||
firmware_config.rmempty = false
|
||||
|
||||
--9.Write bootloader
|
||||
write_bootloader = o:option(Flag, "amlogic_write_bootloader", translate("Auto write bootloader:"))
|
||||
write_bootloader.description = translate("[Recommended choice] Set whether to auto write bootloader during install and update OpenWrt.")
|
||||
write_bootloader.default = "0"
|
||||
write_bootloader.rmempty = false
|
||||
|
||||
--10.Set the file system type of the shared partition
|
||||
shared_fstype = o:option(ListValue, "amlogic_shared_fstype", translate("Set the file system type:"))
|
||||
shared_fstype.description = translate("[Default ext4] Set the file system type of the shared partition (/mnt/mmcblk*p4) when install OpenWrt.")
|
||||
shared_fstype:value("ext4", translate("ext4"))
|
||||
shared_fstype:value("f2fs", translate("f2fs"))
|
||||
shared_fstype:value("btrfs", translate("btrfs"))
|
||||
shared_fstype:value("xfs", translate("xfs"))
|
||||
shared_fstype.default = "ext4"
|
||||
shared_fstype.rmempty = false
|
||||
|
||||
return b
|
||||
@@ -0,0 +1,12 @@
|
||||
local b
|
||||
|
||||
--SimpleForm for Info
|
||||
b = SimpleForm("amlogic", nil)
|
||||
b.title = translate("Amlogic Service")
|
||||
b.description = translate("Supports management of Amlogic s9xxx, Allwinner (V-Plus Cloud), and Rockchip (BeikeYun, Chainedbox L1 Pro) boxes.")
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
b:section(SimpleSection).template = "amlogic/other_info"
|
||||
|
||||
return b
|
||||
@@ -0,0 +1,12 @@
|
||||
local b
|
||||
|
||||
--SimpleForm for Install OpenWrt to Amlogic EMMC
|
||||
b = SimpleForm("amlogic_install", nil)
|
||||
b.title = translate("Install OpenWrt")
|
||||
b.description = translate("Install OpenWrt to EMMC, Please select the device model, Or enter the dtb file name.")
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
b:section(SimpleSection).template = "amlogic/other_install"
|
||||
|
||||
return b
|
||||
@@ -0,0 +1,15 @@
|
||||
local b
|
||||
|
||||
--SimpleForm for Server Logs
|
||||
b = SimpleForm("amlogic_log", nil)
|
||||
b.title = translate("Server Logs")
|
||||
b.description = translate("Display the execution log of the current operation.")
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
s = b:section(SimpleSection, "", nil)
|
||||
|
||||
o = s:option(TextValue, "")
|
||||
o.template = "amlogic/other_log"
|
||||
|
||||
return b
|
||||
@@ -0,0 +1,12 @@
|
||||
local b
|
||||
|
||||
--SimpleForm for PowerOff
|
||||
b = SimpleForm("poweroff", nil)
|
||||
b.title = translate("PowerOff")
|
||||
b.description = translate("Shut down your router device.")
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
b:section(SimpleSection).template = "amlogic/other_poweroff"
|
||||
|
||||
return b
|
||||
@@ -0,0 +1,300 @@
|
||||
--Copyright: https://github.com/coolsnowwolf/luci/tree/master/applications/luci-app-filetransfer
|
||||
--Extended support: https://github.com/ophub/luci-app-amlogic
|
||||
--Function: Upload files
|
||||
|
||||
local os = require "os"
|
||||
local fs = require "nixio.fs"
|
||||
local nutil = require "nixio.util"
|
||||
local type = type
|
||||
local b, form
|
||||
|
||||
--Remove the spaces in the string
|
||||
function trim(str)
|
||||
--return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
|
||||
return (string.gsub(str, "%s+", ""))
|
||||
end
|
||||
|
||||
-- Evaluate given shell glob pattern and return a table containing all matching
|
||||
function glob(...)
|
||||
local iter, code, msg = fs.glob(...)
|
||||
if iter then
|
||||
return nutil.consume(iter)
|
||||
else
|
||||
return nil, code, msg
|
||||
end
|
||||
end
|
||||
|
||||
-- Checks wheather the given path exists and points to a regular file.
|
||||
function isfile(filename)
|
||||
return fs.stat(filename, "type") == "reg"
|
||||
end
|
||||
|
||||
-- Get the last modification time of given file path in Unix epoch format.
|
||||
function mtime(path)
|
||||
return fs.stat(path, "mtime")
|
||||
end
|
||||
|
||||
local stat_tr = {
|
||||
reg = "regular",
|
||||
dir = "directory",
|
||||
lnk = "link",
|
||||
chr = "character device",
|
||||
blk = "block device",
|
||||
fifo = "fifo",
|
||||
sock = "socket"
|
||||
}
|
||||
-- Get information about given file or directory.
|
||||
function stat(path, key)
|
||||
local data, code, msg = fs.stat(path)
|
||||
if data then
|
||||
data.mode = data.modestr
|
||||
data.type = stat_tr[data.type] or "?"
|
||||
end
|
||||
return key and data and data[key] or data, code, msg
|
||||
end
|
||||
|
||||
--Set default upload path
|
||||
local ROOT_PTNAME = trim(luci.sys.exec("df / | tail -n1 | awk '{print $1}' | awk -F '/' '{print $3}'"))
|
||||
if ROOT_PTNAME then
|
||||
if (string.find(ROOT_PTNAME, "mmcblk[0-4]p[1-4]")) then
|
||||
local EMMC_NAME = trim(luci.sys.exec("echo " .. ROOT_PTNAME .. " | awk '{print substr($1, 1, length($1)-2)}'"))
|
||||
upload_path = trim("/mnt/" .. EMMC_NAME .. "p4/")
|
||||
elseif (string.find(ROOT_PTNAME, "[hsv]d[a-z]")) then
|
||||
local EMMC_NAME = trim(luci.sys.exec("echo " .. ROOT_PTNAME .. " | awk '{print substr($1, 1, length($1)-1)}'"))
|
||||
upload_path = trim("/mnt/" .. EMMC_NAME .. "4/")
|
||||
else
|
||||
upload_path = "/tmp/upload/"
|
||||
end
|
||||
else
|
||||
upload_path = "/tmp/upload/"
|
||||
end
|
||||
|
||||
--Clear the version check log
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_plugin.log && sync >/dev/null 2>&1")
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_kernel.log && sync >/dev/null 2>&1")
|
||||
|
||||
--SimpleForm for Update OpenWrt firmware/kernel
|
||||
b = SimpleForm("upload", nil)
|
||||
b.title = translate("Upload")
|
||||
local des_content = translate("Update plugins first, then update the kernel or firmware.")
|
||||
local des_content = des_content .. "<br />" .. translate("After uploading [Firmware], [Kernel], [IPK] or [Backup Config], the operation buttons will be displayed.")
|
||||
b.description = des_content
|
||||
b.reset = false
|
||||
b.submit = false
|
||||
|
||||
s = b:section(SimpleSection, "", "")
|
||||
|
||||
o = s:option(FileUpload, "")
|
||||
o.template = "amlogic/other_upload"
|
||||
|
||||
um = s:option(DummyValue, "", nil)
|
||||
um.template = "amlogic/other_dvalue"
|
||||
|
||||
local dir, fd
|
||||
dir = upload_path
|
||||
fs.mkdir(dir)
|
||||
luci.http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not fd then
|
||||
if not meta then return end
|
||||
if meta and chunk then fd = nixio.open(dir .. meta.file, "w") end
|
||||
if not fd then
|
||||
um.value = translate("Create upload file error.") .. " Error Info: " .. trim(upload_path .. meta.file)
|
||||
return
|
||||
end
|
||||
end
|
||||
if chunk and fd then
|
||||
fd:write(chunk)
|
||||
end
|
||||
if eof and fd then
|
||||
fd:close()
|
||||
fd = nil
|
||||
um.value = translate("File saved to") .. trim(upload_path .. meta.file)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if luci.http.formvalue("upload") then
|
||||
local f = luci.http.formvalue("ulfile")
|
||||
if #f <= 0 then
|
||||
um.value = translate("No specify upload file.")
|
||||
end
|
||||
end
|
||||
|
||||
local function getSizeStr(size)
|
||||
local i = 0
|
||||
local byteUnits = { ' kB', ' MB', ' GB', ' TB' }
|
||||
repeat
|
||||
size = size / 1024
|
||||
i = i + 1
|
||||
until (size <= 1024)
|
||||
return string.format("%.1f", size) .. byteUnits[i]
|
||||
end
|
||||
|
||||
local inits, attr = {}
|
||||
for i, f in ipairs(glob(trim(upload_path .. "*"))) do
|
||||
attr = stat(f)
|
||||
itisfile = isfile(f)
|
||||
if attr and itisfile then
|
||||
inits[i] = {}
|
||||
inits[i].name = fs.basename(f)
|
||||
inits[i].mtime = os.date("%Y-%m-%d %H:%M:%S", attr.mtime)
|
||||
inits[i].modestr = attr.modestr
|
||||
inits[i].size = getSizeStr(attr.size)
|
||||
inits[i].remove = 0
|
||||
inits[i].ipk = false
|
||||
|
||||
--Check whether the openwrt firmware file
|
||||
-- openwrt_s905d_v5.10.16_2021.05.31.1958.img.gz
|
||||
if (string.lower(string.sub(fs.basename(f), -7, -1)) == ".img.gz") then
|
||||
openwrt_firmware_file = true
|
||||
end
|
||||
-- openwrt_s905d_n1_R21.7.15_k5.4.134-flippy-62+o.img.xz
|
||||
if (string.lower(string.sub(fs.basename(f), -7, -1)) == ".img.xz") then
|
||||
openwrt_firmware_file = true
|
||||
end
|
||||
-- openwrt_s905d_n1_R21.7.15_k5.13.2-flippy-62+.7z
|
||||
if (string.lower(string.sub(fs.basename(f), -3, -1)) == ".7z") then
|
||||
openwrt_firmware_file = true
|
||||
end
|
||||
-- openwrt_s905d_n1_R21.7.15_k5.13.2-flippy-62+.img
|
||||
if (string.lower(string.sub(fs.basename(f), -4, -1)) == ".img") then
|
||||
openwrt_firmware_file = true
|
||||
end
|
||||
|
||||
--Check whether the three kernel files
|
||||
-- boot-5.10.16-flippy-53+.tar.gz
|
||||
if (string.lower(string.sub(fs.basename(f), 1, 5)) == "boot-") then
|
||||
boot_file = true
|
||||
end
|
||||
-- dtb-amlogic-5.10.16-flippy-53+.tar.gz
|
||||
if (string.lower(string.sub(fs.basename(f), 1, 4)) == "dtb-") then
|
||||
dtb_file = true
|
||||
end
|
||||
-- modules-5.10.16-flippy-53+.tar.gz
|
||||
if (string.lower(string.sub(fs.basename(f), 1, 8)) == "modules-") then
|
||||
modules_file = true
|
||||
end
|
||||
|
||||
--Check whether the backup file
|
||||
-- openwrt_config.tar.gz
|
||||
if (string.lower(string.sub(fs.basename(f), 1, -1)) == "openwrt_config.tar.gz") then
|
||||
backup_config_file = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--SimpleForm for Upload file list
|
||||
form = SimpleForm("filelist", translate("Upload file list"), nil)
|
||||
form.reset = false
|
||||
form.submit = false
|
||||
|
||||
description_info = ""
|
||||
luci.sys.exec("echo '' > /tmp/amlogic/amlogic_check_upfiles.log && sync >/dev/null 2>&1")
|
||||
|
||||
if backup_config_file then
|
||||
description_info = description_info .. translate("There are config file in the upload directory, and you can restore the config. ")
|
||||
end
|
||||
|
||||
if boot_file and dtb_file and modules_file then
|
||||
description_info = description_info .. translate("There are kernel files in the upload directory, and you can replace the kernel.")
|
||||
luci.sys.exec("echo 'kernel' > /tmp/amlogic/amlogic_check_upfiles.log && sync >/dev/null 2>&1")
|
||||
end
|
||||
|
||||
if openwrt_firmware_file then
|
||||
description_info = description_info .. translate("There are openwrt firmware file in the upload directory, and you can update the openwrt.")
|
||||
luci.sys.exec("echo 'firmware' > /tmp/amlogic/amlogic_check_upfiles.log && sync >/dev/null 2>&1")
|
||||
end
|
||||
|
||||
if description_info ~= "" then
|
||||
form.description = ' <span style="color: green"><b> Tip: ' .. description_info .. ' </b></span> '
|
||||
end
|
||||
|
||||
tb = form:section(Table, inits)
|
||||
nm = tb:option(DummyValue, "name", translate("File name"))
|
||||
mt = tb:option(DummyValue, "mtime", translate("Modify time"))
|
||||
ms = tb:option(DummyValue, "modestr", translate("Attributes"))
|
||||
sz = tb:option(DummyValue, "size", translate("Size"))
|
||||
btnrm = tb:option(Button, "remove", translate("Remove"))
|
||||
btnrm.render = function(self, section, scope)
|
||||
self.inputstyle = "remove"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btnrm.write = function(self, section)
|
||||
local v = fs.unlink(trim(upload_path .. fs.basename(inits[section].name)))
|
||||
if v then table.remove(inits, section) end
|
||||
return v
|
||||
end
|
||||
|
||||
function IsConfigFile(name)
|
||||
name = name or ""
|
||||
local config_file = string.lower(string.sub(name, 1, -1))
|
||||
return config_file == "openwrt_config.tar.gz"
|
||||
end
|
||||
|
||||
-- Check if the file is a known package type (.ipk or .apk)
|
||||
function IsPackageFile(name)
|
||||
name = name or ""
|
||||
local lname = string.lower(name)
|
||||
return string.sub(lname, -4) == ".ipk" or string.sub(lname, -4) == ".apk"
|
||||
end
|
||||
|
||||
--Add Button for *.ipk
|
||||
btnis = tb:option(Button, "ipk", translate("Install"))
|
||||
btnis.template = "amlogic/other_button"
|
||||
btnis.render = function(self, section, scope)
|
||||
if not inits[section] then return false end
|
||||
if IsPackageFile(inits[section].name) then
|
||||
scope.display = ""
|
||||
self.inputtitle = translate("Install")
|
||||
elseif IsConfigFile(inits[section].name) then
|
||||
scope.display = ""
|
||||
self.inputtitle = translate("Restore")
|
||||
else
|
||||
scope.display = "none"
|
||||
end
|
||||
|
||||
self.inputstyle = "apply"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btnis.write = function(self, section)
|
||||
local file_to_install = inits[section].name
|
||||
local full_path = upload_path .. file_to_install
|
||||
|
||||
if IsPackageFile(file_to_install) then
|
||||
local r = ""
|
||||
local install_cmd = ""
|
||||
|
||||
-- Check for opkg first
|
||||
if luci.sys.call("command -v opkg >/dev/null") == 0 then
|
||||
install_cmd = string.format('opkg --force-reinstall install %s', full_path)
|
||||
r = luci.sys.exec(install_cmd)
|
||||
-- If opkg is not found, check for apk
|
||||
elseif luci.sys.call("command -v apk >/dev/null") == 0 then
|
||||
-- NOTE: --allow-untrusted is required for local packages
|
||||
install_cmd = string.format('apk add --force-overwrite --allow-untrusted %s', full_path)
|
||||
r = luci.sys.exec(install_cmd)
|
||||
-- If neither is found
|
||||
else
|
||||
r = "Error: Neither 'opkg' nor 'apk' package manager found on the system."
|
||||
end
|
||||
|
||||
-- Clean LuCI cache after installation
|
||||
luci.sys.exec("rm -rf /tmp/luci-indexcache /tmp/luci-modulecache/* >/dev/null 2>&1")
|
||||
|
||||
-- Display the result message
|
||||
-- We add a message to prompt the user to refresh the page to see changes.
|
||||
local result_msg = r .. "<br/><b>" .. translate("Please refresh the page to see the changes.") .. "</b>"
|
||||
form.description = string.format('<span style="color: red">%s</span>', result_msg)
|
||||
|
||||
elseif IsConfigFile(inits[section].name) then
|
||||
form.description = ' <span style="color: green"><b> ' .. translate("Tip: The config is being restored, and it will automatically restart after completion.") .. ' </b></span> '
|
||||
luci.sys.exec("chmod +x /usr/sbin/openwrt-backup 2>/dev/null")
|
||||
luci.sys.exec("/usr/sbin/openwrt-backup -r > /tmp/amlogic/amlogic.log && sync 2>/dev/null")
|
||||
end
|
||||
end
|
||||
|
||||
--SimpleForm for Check upload files
|
||||
form:section(SimpleSection).template = "amlogic/other_upfiles"
|
||||
|
||||
return b, form
|
||||
@@ -0,0 +1,7 @@
|
||||
<%+cbi/valueheader%>
|
||||
<% if self:cfgvalue(section) ~= false then %>
|
||||
<input class="cbi-button cbi-button-<%=self.inputstyle or "button" %>" style="display: <%= display %>" type="submit" <%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> />
|
||||
<% else %>
|
||||
-
|
||||
<% end %>
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -0,0 +1,222 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height: 20px; }
|
||||
</style>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td width="100%" colspan="2">
|
||||
<p align="center">
|
||||
<%:Update plugins first, then update the kernel or firmware. More options can be configured in [Plugin Settings].%> <span id="_openwrt_mainline_version"></span>
|
||||
</p>
|
||||
</td></tr>
|
||||
<tr><td width="35%" align="right"><input type="button" class="cbi-button cbi-button-reload" value="<%:Only update Amlogic Service%>" onclick="return b_check_plugin(this)"/></td><td width="65%" align="left"><span id="_current_plugin_version"><%:Collecting data...%></span> <span id="_check_plugin"></span></td></tr>
|
||||
<tr><td width="35%" align="right"><input type="button" class="cbi-button cbi-button-reload" value="<%:Update system kernel only%>" onclick="return b_check_kernel(this, 'check')"/></td><td width="65%" align="left"><span id="_current_kernel_version"><%:Collecting data...%></span> <span id="_check_kernel"></span></td></tr>
|
||||
<tr><td width="35%" align="right"><input type="button" class="cbi-button cbi-button-reload" value="<%:Complete system update%>" onclick="return b_check_firmware(this, 'check')"/></td><td width="65%" align="left"><span id="_current_firmware_version"><%:Collecting data...%></span> <span id="_check_firmware"></span></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function amlogic_update(btn,amlogic_update_sel)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Updating...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_update")%>',
|
||||
{
|
||||
amlogic_update_sel: amlogic_update_sel
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_update_status!="0")
|
||||
{
|
||||
btn.value = '<%:Update Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successful Update%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Update%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function amlogic_kernel(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Updating...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_kernel")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_kernel_status!="0")
|
||||
{
|
||||
btn.value = '<%:Update Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successful Update%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Update%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function amlogic_plugin(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Updating...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_plugin")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_plugin_status!="0")
|
||||
{
|
||||
btn.value = '<%:Update Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successful Update%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Update%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function b_check_firmware(btn,firmware_options)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Checking...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "check_firmware")%>',
|
||||
{
|
||||
firmware_options: firmware_options
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.check_firmware_status!="0")
|
||||
{
|
||||
btn.value = '<%:Complete system update%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Complete system update%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Complete system update%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function b_check_plugin(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Checking...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "check_plugin")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Only update Amlogic Service%>';
|
||||
}
|
||||
else {
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Only update Amlogic Service%>';
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function b_check_kernel(btn,kernel_options)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Checking...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "check_kernel")%>',
|
||||
{
|
||||
kernel_options: kernel_options
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.check_kernel_status!="0")
|
||||
{
|
||||
btn.value = '<%:Update system kernel only%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Update system kernel only%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Update system kernel only%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
var _check_firmware = document.getElementById('_check_firmware');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_firmware")%>', status.start_check_firmware, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_firmware != "\n" && status.start_check_firmware != "" ) {
|
||||
_check_firmware.innerHTML = '<font color="blue"> '+status.start_check_firmware+'</font>';
|
||||
}
|
||||
if ( status.start_check_firmware == "\n" || status.start_check_firmware == "" ) {
|
||||
_check_firmware.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _check_plugin = document.getElementById('_check_plugin');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_plugin")%>', status.start_check_plugin, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_plugin != "\n" && status.start_check_plugin != "" ) {
|
||||
_check_plugin.innerHTML = '<font color="blue"> '+status.start_check_plugin+'</font>';
|
||||
}
|
||||
if ( status.start_check_plugin == "\n" || status.start_check_plugin == "" ) {
|
||||
_check_plugin.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _check_kernel = document.getElementById('_check_kernel');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_kernel")%>', status.start_check_kernel, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_kernel != "\n" && status.start_check_kernel != "" ) {
|
||||
_check_kernel.innerHTML = '<font color="blue"> '+status.start_check_kernel+'</font>';
|
||||
}
|
||||
if ( status.start_check_kernel == "\n" || status.start_check_kernel == "" ) {
|
||||
_check_kernel.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _current_firmware_version = document.getElementById('_current_firmware_version');
|
||||
var _current_plugin_version = document.getElementById('_current_plugin_version');
|
||||
var _current_kernel_version = document.getElementById('_current_kernel_version');
|
||||
var _openwrt_mainline_version = document.getElementById('_openwrt_mainline_version');
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "state")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
_current_firmware_version.innerHTML = status.current_firmware_version ? "<font color=green><%:Current Version%> [ "+status.current_firmware_version+" ] </font>" : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
_current_plugin_version.innerHTML = status.current_plugin_version ? "<font color=green><%:Current Version%> [ "+status.current_plugin_version+" ] </font>" : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
_current_kernel_version.innerHTML = status.current_kernel_version ? "<font color=green><%:Current Version%> [ "+status.current_kernel_version+" ] </font>" : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
_openwrt_mainline_version.innerHTML = status.current_kernel_branch ? " [ "+status.current_kernel_branch+".y ] " : "[ "+"<%:Invalid value.%>"+" ]";
|
||||
}
|
||||
});
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,8 @@
|
||||
<%+cbi/valueheader%>
|
||||
<span style="color: red">
|
||||
<%
|
||||
local val = self:cfgvalue(section) or self.default or ""
|
||||
write(pcdata(val))
|
||||
%>
|
||||
</span>
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -0,0 +1,70 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height:20px; }
|
||||
</style>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td colspan="2" width="100%" align="center">
|
||||
<img id="logo_amlogic" src="<%=resource%>/amlogic/logo.png" alt="Logo" width="135" />
|
||||
</td></tr>
|
||||
<tr><td colspan="2" width="100%" align="center">
|
||||
<img id="Packit" src="<%=resource%>/amlogic/packit.svg" alt="Packit" width="168px" height="20px" onclick="return homepage('packit')" />
|
||||
|
||||
<img id="Author" src="<%=resource%>/amlogic/author.svg" alt="Author" width="168px" height="20px" onclick="return author_homepage('author')" />
|
||||
|
||||
<img id="Plugin" src="<%=resource%>/amlogic/plugin.svg" alt="luci-app-amlogic" width="160px" height="20px" onclick="return homepage('plugin')" />
|
||||
</td></tr>
|
||||
<tr><td width="20%" align="right"><%:Supported functions:%></td><td width="80%" align="left" id="_clash">
|
||||
<%:Provide services such as install to EMMC, Update Firmware and Kernel, Backup and Recovery Config, Snapshot management, etc.%>
|
||||
</td></tr>
|
||||
<tr><td width="20%" align="right"><%:Supported Boxes:%></td><td width="80%" align="left" id="_clash">
|
||||
<%:Amlogic s922x --- [ Beelink, Beelink-Pro, Ugoos-AM6-Plus, ODROID-N2, Khadas-VIM3, Ali-CT2000 ]%><br>
|
||||
<%:Amlogic s905x3 -- [ X96-Max+, HK1-Box, H96-Max-X3, Ugoos-X3, TX3, X96-Air, A95XF3-Air ]%><br>
|
||||
<%:Amlogic s905x2 -- [ X96Max-4G, X96Max-2G, MECOOL-KM3-4G, Tanix-Tx5-Max, A95X-F2 ]%><br>
|
||||
<%:Amlogic s912 ---- [ H96-Pro-Plus, Octopus-Planet, A1, A2, Z6-Plus, TX92, X92, TX8-MAX, TX9-Pro ]%><br>
|
||||
<%:Amlogic s905x --- [ HG680P, B860H, TBee, T95, TX9, XiaoMI-3S, X96 ]%><br>
|
||||
<%:Amlogic s905w --- [ X96-Mini, TX3-Mini, W95, X96W/FunTV, MXQ-Pro-4K ]%><br>
|
||||
<%:Amlogic s905d --- [ Phicomm-N1, MECOOL-KI-Pro, SML-5442TW ]%><br>
|
||||
<%:Amlogic s905l --- [ UNT402A, M201-S ]%><br>
|
||||
<%:Amlogic s905l2 -- [ MGV2000, MGV3000, Wojia-TV-IPBS9505, M301A, E900v21E ]%><br>
|
||||
<%:Amlogic s905l3 -- [ CM211-1, CM311-1, HG680-LC, M401A, UNT400G1, UNT402A, ZXV10-BV310 ]%><br>
|
||||
<%:Amlogic s905l3a - [ E900V22C/D, CM311-1a-YST, M401A, M411A, UNT403A, UNT413A, IP112H ]%><br>
|
||||
<%:Amlogic s905l3b - [ CM211-1, CM311-1, E900V22D, E900V21E, E900V22E, M302A/M304A ]%><br>
|
||||
<%:Amlogic s905 ---- [ Beelink-Mini-MX-2G, Sunvell-T95M, MXQ-Pro+4K, SumaVision-Q5 ]%><br>
|
||||
<%:Allwinner H6 ---- [ V-Plus Cloud ]%><br>
|
||||
<%:Rockchip -------- [ BeikeYun, L1-Pro, FastRhino R66S/R68S, Radxa 5B/E25 ]%><br>
|
||||
<%:Used in KVM ----- [ Can be used in KVM virtual machine of Armbian system. ]%>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function winOpen(url)
|
||||
{
|
||||
var winOpen = window.open(url);
|
||||
if( winOpen == null || typeof(winOpen) == 'undefined' ){ window.location.href=url; }
|
||||
}
|
||||
|
||||
function homepage(website)
|
||||
{
|
||||
var url = "";
|
||||
if( website == 'packit' ) { url = 'https://github.com/unifreq/openwrt_packit'; }
|
||||
if( website == 'plugin' ) { url = 'https://github.com/ophub/luci-app-amlogic'; }
|
||||
if ( url != "" ) { winOpen(url); }
|
||||
}
|
||||
|
||||
function author_homepage(website)
|
||||
{
|
||||
var openwrt_author_repo = "";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_openwrt_author")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
let openwrt_author_repo = status.openwrt_author;
|
||||
let trimstr_au = openwrt_author_repo.replace(/(^\s*)|(\s*$)/g, "");
|
||||
if (trimstr_au.indexOf("https") == -1) {
|
||||
trimstr_au = 'https://github.com/' + trimstr_au;
|
||||
}
|
||||
if ( trimstr_au != "" ) { winOpen(trimstr_au); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,128 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height:20px; }
|
||||
</style>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td width="35%" align="right"><%:Select the device model:%></td>
|
||||
<td width="65%" align="left">
|
||||
<select name="amlogic_soc" id="amlogic_soc" style="width:auto" onchange="sel_dtb_input(this.options[this.selectedIndex].value)">
|
||||
<option value="0"><%:Select List%></option>
|
||||
<option value="99"><%:Enter the dtb file name%></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="tr_sel_dtb" style="display:none;"><td width="30%" align="right"><%:Enter the dtb file name:%></td><td width="70%" align="left"><input class="cbi-input-file" style="width: 235px" type="text" id="amlogic_dtb" name="amlogic_dtb" /></td></tr>
|
||||
<tr id="tr_sel_soc" style="display:none;"><td width="30%" align="right"><%:Enter the soc name:%></td><td width="70%" align="left"><input class="cbi-input-file" style="width: 235px" type="text" id="amlogic_socname" name="amlogic_socname" /></td></tr>
|
||||
<tr id="tr_sel_uboot" style="display:none;"><td width="30%" align="right"><%:Enter the uboot_overload name:%></td><td width="70%" align="left"><input class="cbi-input-file" style="width: 235px" type="text" id="amlogic_uboot" name="amlogic_uboot" /></td></tr>
|
||||
<tr>
|
||||
<td width="30%" align="right"><%:Install OpenWrt:%></td>
|
||||
<td width="70%" align="left">
|
||||
<input type="button" class="cbi-button cbi-button-reload" value="<%:Install%>" onclick="return amlogic_install(this, '<%=self:cfgvalue(section)%>')"/> <span id="_check_install"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
// Show custom dtb input box
|
||||
function sel_dtb_input(soc_value){
|
||||
if ( soc_value == "99" )
|
||||
{
|
||||
document.getElementById('tr_sel_dtb').style = '';
|
||||
document.getElementById('tr_sel_soc').style = '';
|
||||
document.getElementById('tr_sel_uboot').style = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById('tr_sel_dtb').style = 'display:none;';
|
||||
document.getElementById('tr_sel_soc').style = 'display:none;';
|
||||
document.getElementById('tr_sel_uboot').style = 'display:none;';
|
||||
}
|
||||
}
|
||||
|
||||
// Show the status of the install button
|
||||
function amlogic_install(btn,amlogic_install_sel)
|
||||
{
|
||||
var amlogic_soc_id = document.getElementById('amlogic_soc');
|
||||
var amlogic_soc_index = amlogic_soc_id.selectedIndex;
|
||||
var amlogic_soc_value = amlogic_soc_id.options[amlogic_soc_index].value;
|
||||
var amlogic_soc_text = amlogic_soc_id.options[amlogic_soc_index].text;
|
||||
|
||||
var amlogic_dtb_id = document.getElementById('amlogic_dtb');
|
||||
var amlogic_dtb_value = amlogic_dtb_id.value;
|
||||
|
||||
var amlogic_soc_name = document.getElementById('amlogic_socname');
|
||||
var amlogic_socname_value = amlogic_socname.value;
|
||||
|
||||
var amlogic_ubootname = document.getElementById('amlogic_uboot');
|
||||
var amlogic_ubootname_value = amlogic_ubootname.value;
|
||||
|
||||
var amlogic_confirm_info = amlogic_soc_text;
|
||||
if (confirm('<%:You have chosen:%>' + amlogic_confirm_info + ', <%:Start install?%>') != true) { return false; }
|
||||
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Installing...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_install")%>',
|
||||
{
|
||||
amlogic_install_sel: amlogic_soc_value + '@' + amlogic_dtb_value + ':' + amlogic_socname_value + ':' + amlogic_ubootname_value
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_install_status!="0")
|
||||
{
|
||||
btn.value = '<%:Install Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successful Install%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Install%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read openwrt install log
|
||||
var start_check_install = document.getElementById('_check_install');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_install")%>', status.start_check_install, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_install != "\n" && status.start_check_install != "" ) {
|
||||
start_check_install.innerHTML = '<font color="blue"> '+status.start_check_install+'</font>';
|
||||
}
|
||||
if ( status.start_check_install == "\n" || status.start_check_install == "" ) {
|
||||
start_check_install.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Show external modal database: /etc/model_database.txt
|
||||
var mymodel_arrlen = 0;
|
||||
var _option_codes = '<option value="0"><%:Select List%></option>';
|
||||
var _check_my_amlogic_soc = document.getElementById('amlogic_soc');
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_model_database")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.my_model_database != "" ) {
|
||||
let userModelList = status.my_model_database;
|
||||
var user_arry = userModelList.split('@@@');
|
||||
var mymodel_arrlen = user_arry.length - 1;
|
||||
for ( j = 0; j < mymodel_arrlen; j++ ) {
|
||||
my_box_mode = user_arry[j].split('###');
|
||||
my_box_mode_id = my_box_mode[0];
|
||||
my_box_mode_name = my_box_mode[1];
|
||||
if ( my_box_mode_id != "" && my_box_mode_name != "" ) {
|
||||
_option_codes = _option_codes + '<option value="' + my_box_mode_id + '">[ ' + my_box_mode_id + ' ] ' + my_box_mode_name.replace(/~/g, " ") + '</option>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_option_codes = _option_codes + '<option value="99"><%:Enter the dtb file name%></option>';
|
||||
_check_my_amlogic_soc.innerHTML = _option_codes;
|
||||
});
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,48 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height:32px; }
|
||||
.imgLeft{ float:left; margin-right:10px; vertical-align:middle; }
|
||||
.contentRight{ align-items: center; }
|
||||
</style>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td width="100%" align="left">
|
||||
<input class="cbi-button cbi-button-save" type="button" value="<%:Switch System%>" onclick="switchopenwrt(this)" />
|
||||
<p style="display:none">
|
||||
<img id="img_loading" style="display:block" src="<%=resource%>/amlogic/loading.gif" alt="<%:Loading%>" class="imgLeft" />
|
||||
<img id="img_switch" style="display:none" src="<%=resource%>/amlogic/switch.png" alt="<%:PowerOff%>" class="imgLeft" />
|
||||
<span id="msg_switch" class="contentRight"><%:System is switching...%></span>
|
||||
</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function status_check() {
|
||||
var time = 5;
|
||||
var img_loading = document.getElementById("img_loading");
|
||||
var img_switch = document.getElementById("img_switch");
|
||||
var msg = document.getElementById("msg_switch");
|
||||
var set = setInterval(function() {
|
||||
time--;
|
||||
msg.innerHTML = "<%:Waiting for system switching...%>";
|
||||
if(time === 0) {
|
||||
img_loading.style.display = 'none';
|
||||
img_switch.style.display = 'block';
|
||||
msg.innerHTML = "<%:System switchover succeeded, restarting...%>";
|
||||
clearInterval(set);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function switchopenwrt(btn) {
|
||||
if (confirm('<%:Are you sure you want to switch systems?%>') != true) { return false; }
|
||||
|
||||
btn.style.display = 'none';
|
||||
document.getElementById('msg_switch').parentNode.style.display = 'block';
|
||||
|
||||
(new XHR()).post('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_switch")%>', { token: '<%=token%>' }, status_check);
|
||||
}
|
||||
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,117 @@
|
||||
<%+cbi/valueheader%>
|
||||
<textarea id="amlogic.ophub.clog" class="cbi-input-textarea" style="width: 100%;display:inline" data-update="change" rows="8" cols="60" readonly="readonly" > </textarea>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="25%" align="center"><input type="button" class="cbi-button cbi-button-apply" id="stop_refresh_button" value="<%:Stop Refresh Log%>" onclick=" return stop_refresh() "/></td>
|
||||
<td width="25%" align="center"><input type="button" class="cbi-button cbi-button-apply" id="start_refresh_button" value="<%:Start Refresh Log%>" onclick=" return start_refresh() "/></td>
|
||||
<td width="25%" align="center"><input type="button" class="cbi-button cbi-button-apply" id="del_log_button" value="<%:Clean Log%>" style=" display:inline;" onclick=" return del_log() " /></td>
|
||||
<td width="25%" align="center"><input type="button" class="cbi-button cbi-button-apply" id="down_log_button" value="<%:Download Log%>" style=" display:inline;" onclick=" return download_log() " /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var r
|
||||
|
||||
function stop_refresh() {
|
||||
clearTimeout(r);
|
||||
return
|
||||
}
|
||||
|
||||
function start_refresh() {
|
||||
clearTimeout(r);
|
||||
r=setTimeout("poll_log()",1000*2);
|
||||
return
|
||||
}
|
||||
|
||||
function createAndDownloadFile(fileName, content) {
|
||||
var aTag = document.createElement('a');
|
||||
var blob = new Blob([content]);
|
||||
aTag.download = fileName;
|
||||
aTag.href = URL.createObjectURL(blob);
|
||||
aTag.click();
|
||||
URL.revokeObjectURL(blob);
|
||||
}
|
||||
|
||||
function download_log(){
|
||||
var lv = document.getElementById('amlogic.ophub.clog');
|
||||
var dt = new Date();
|
||||
var timestamp = dt.getFullYear()+"-"+(dt.getMonth()+1)+"-"+dt.getDate()+"-"+dt.getHours()+"-"+dt.getMinutes()+"-"+dt.getSeconds();
|
||||
createAndDownloadFile("Amlogic-"+timestamp+".log",lv.innerHTML)
|
||||
return
|
||||
}
|
||||
|
||||
function del_log() {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "del_log")%>',null,function(x, data){
|
||||
var lv = document.getElementById('amlogic.ophub.clog');
|
||||
lv.innerHTML="";
|
||||
}
|
||||
);
|
||||
return
|
||||
}
|
||||
|
||||
function p(s) {
|
||||
return s < 10 ? '0' + s: s;
|
||||
}
|
||||
|
||||
function line_tolocal(str){
|
||||
var strt=new Array();
|
||||
str.trim().split('\n').forEach(function(v, i) {
|
||||
var dt = new Date(v.substring(6,26));
|
||||
if (dt != "Invalid Date"){
|
||||
strt[i]=dt.getFullYear()+"-"+p(dt.getMonth()+1)+"-"+p(dt.getDate())+" "+p(dt.getHours())+":"+p(dt.getMinutes())+":"+p(dt.getSeconds())+v.substring(27);
|
||||
}else{
|
||||
strt[i]=v;}})
|
||||
var old_log_line = sessionStorage.log_line;
|
||||
if ( old_log_line != null && strt.length != null ) {
|
||||
if (old_log_line - strt.length < 0) {
|
||||
sessionStorage.log_line = strt.length;
|
||||
return strt.slice('-'+(strt.length-old_log_line))
|
||||
}
|
||||
else if (old_log_line == strt.length) {
|
||||
sessionStorage.log_line = strt.length;
|
||||
return
|
||||
}
|
||||
else if (old_log_line - strt.length > 0) {
|
||||
sessionStorage.log_line = strt.length;
|
||||
var lv = document.getElementById('amlogic.ophub.clog');
|
||||
lv.innerHTML = "";
|
||||
return strt
|
||||
}
|
||||
}
|
||||
else if ( strt.length != null ) {
|
||||
sessionStorage.log_line = strt.length;
|
||||
return strt
|
||||
}
|
||||
else {
|
||||
sessionStorage.log_line = "0";
|
||||
return strt
|
||||
}
|
||||
}
|
||||
|
||||
function poll_log(){
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "refresh_log")%>', null,
|
||||
function(x, data) {
|
||||
if ( x && x.status == 200 ) {
|
||||
var lv = document.getElementById('amlogic.ophub.clog');
|
||||
if (x.responseText && lv) {
|
||||
var lines=line_tolocal(x.responseText);
|
||||
if (lines != null) {
|
||||
lv.innerHTML = lines.reverse().join('\n')+'\n'+lv.innerHTML;
|
||||
//lv.innerHTML = x.responseText.split('\n').reverse().join('\n')+lv.innerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
r=setTimeout("poll_log()",1000*2);
|
||||
}
|
||||
|
||||
sessionStorage.removeItem("log_line");
|
||||
poll_log();
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -0,0 +1,48 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height:32px; }
|
||||
.imgLeft{ float:left; margin-right:10px; vertical-align:middle; }
|
||||
.contentRight{ align-items: center; }
|
||||
</style>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td width="100%" align="left">
|
||||
<input class="cbi-button cbi-button-remove" type="button" value="<%:Perform PowerOff%>" onclick="poweroff(this)" />
|
||||
<p style="display:none">
|
||||
<img id="img_loading" style="display:block" src="<%=resource%>/amlogic/loading.gif" alt="<%:Loading%>" class="imgLeft" />
|
||||
<img id="img_poweroff" style="display:none" src="<%=resource%>/amlogic/poweroff.png" alt="<%:PowerOff%>" class="imgLeft" />
|
||||
<span id="msg_poweroff" class="contentRight"><%:Device is shutting down...%></span>
|
||||
</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function status_check() {
|
||||
var time = 5;
|
||||
var img_loading = document.getElementById("img_loading");
|
||||
var img_poweroff = document.getElementById("img_poweroff");
|
||||
var msg = document.getElementById("msg_poweroff");
|
||||
var set = setInterval(function() {
|
||||
time--;
|
||||
msg.innerHTML = "<%:Waiting for the device to shut down...%>";
|
||||
if(time === 0) {
|
||||
img_loading.style.display = 'none';
|
||||
img_poweroff.style.display = 'block';
|
||||
msg.innerHTML = "<%:The device has been turned off%>";
|
||||
clearInterval(set);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function poweroff(btn) {
|
||||
if (confirm('<%:Are you sure you want to shut down?%>') != true) { return false; }
|
||||
|
||||
btn.style.display = 'none';
|
||||
document.getElementById('msg_poweroff').parentNode.style.display = 'block';
|
||||
|
||||
(new XHR()).post('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_poweroff")%>', { token: '<%=token%>' }, status_check);
|
||||
}
|
||||
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,46 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height: 20px; }
|
||||
</style>
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td width="35%" align="right"><input type="button" class="cbi-button cbi-button-reload" value="<%:Rescue the original system kernel%>" onclick="return b_rescue_kernel(this)"/></td><td width="65%" align="left"><span id="_current_rescue_version"><%:Collecting data...%></span> <span id="_check_rescue"></span></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function b_rescue_kernel(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Rescuing...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_rescue")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Rescue the original system kernel%>';
|
||||
}
|
||||
else {
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Rescue the original system kernel%>';
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
var _check_rescue = document.getElementById('_check_rescue');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_rescue")%>', status.start_check_rescue, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_rescue != "\n" && status.start_check_rescue != "" ) {
|
||||
_check_rescue.innerHTML = '<font color="blue"> '+status.start_check_rescue+'</font>';
|
||||
}
|
||||
if ( status.start_check_rescue == "\n" || status.start_check_rescue == "" ) {
|
||||
_check_rescue.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _current_rescue_version = document.getElementById('_current_rescue_version');
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "state")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
_current_rescue_version.innerHTML = status.current_kernel_version ? "<font color=green><%:Current Version%> [ "+status.current_kernel_version+" ] </font>" : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
}
|
||||
});
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,152 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height:20px; }
|
||||
.SnapshotsTitHeight{ line-height:40px; text-align: center; }
|
||||
.list{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #FFF;
|
||||
}
|
||||
.item{
|
||||
border: 1px solid #CACACA;
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
width: 150px;
|
||||
height: 130px;
|
||||
margin:8px;
|
||||
text-align: center;
|
||||
align-items:center;
|
||||
}
|
||||
.item:hover{background:#e5f3f6;}
|
||||
.item:not(:nth-child(3n)){
|
||||
content: "";
|
||||
width: 150px;
|
||||
}
|
||||
.list:after {
|
||||
content: "";
|
||||
width: 150px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="list" id="_check_snapshot">
|
||||
<%:Collecting data...%>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
// Delete snapshot function
|
||||
function delete_snapshot(btn,snapshot_delete_sel)
|
||||
{
|
||||
|
||||
if (confirm('<%:You selected a snapshot:%> [ ' + snapshot_delete_sel + ' ] , <%:Confirm delete?%>') != true) { return false; }
|
||||
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Deleting...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_snapshot_delete")%>',
|
||||
{
|
||||
snapshot_delete_sel: snapshot_delete_sel
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_delete_status!="0")
|
||||
{
|
||||
btn.value = '<%:Delete Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successfully Deleted%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Delete Snapshot%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
var sdiv = 'snapshots_div_' + snapshot_delete_sel;
|
||||
document.getElementById(sdiv).style.display = 'none';
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Restore snapshot function
|
||||
function restore_snapshot(btn,snapshot_restore_sel)
|
||||
{
|
||||
|
||||
if (confirm('<%:You selected a snapshot:%> [ ' + snapshot_restore_sel + ' ] , <%:Confirm recovery and restart OpenWrt?%>') != true) { return false; }
|
||||
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Restoring...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_snapshot_restore")%>',
|
||||
{
|
||||
snapshot_restore_sel: snapshot_restore_sel
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_restore_status!="0")
|
||||
{
|
||||
btn.value = '<%:Restore Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successfully Restored%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Restore Snapshot%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Show current snapshot list
|
||||
mycars_arrlen = 0;
|
||||
_no_snapshots = "<%:Currently OpenWrt does not support the snapshot function.%>";
|
||||
_no_snapshots = _no_snapshots + "<%:Please use this plugin to reinstall or upgrade OpenWrt to enable the snapshot function.%>";
|
||||
var _check_snapshot = document.getElementById('_check_snapshot');
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_snapshot_list")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
|
||||
let userArer = status.current_snapshot;
|
||||
let user_arer_clear = userArer.replace(/\.snapshots\//g, "");
|
||||
let trimstr = user_arer_clear.replace(/(^\s*)|(\s*$)/g, "");
|
||||
let user_arer = trimstr.replace(/\s+/g, ",");
|
||||
var mycars = user_arer.split(',');
|
||||
var mycars_arrlen = mycars.length;
|
||||
|
||||
_div_codes = ""
|
||||
_snapshots_tit = ""
|
||||
for ( j = 0; j < mycars_arrlen; j++ ) {
|
||||
|
||||
if ( mycars[j] == "etc-000" ) {
|
||||
_snapshots_tit = "<%:Initialize Snapshot%>";
|
||||
} else if ( mycars[j] == "etc-001" ) {
|
||||
_snapshots_tit = "<%:Update Snapshot%>";
|
||||
} else {
|
||||
_snapshots_tit = mycars[j];
|
||||
}
|
||||
|
||||
_div_codes = _div_codes + '<div class="item" id="snapshots_div_' + mycars[j] + '">';
|
||||
_div_codes = _div_codes + '<div class="SnapshotsTitHeight">' + _snapshots_tit + '</div>'
|
||||
_div_codes = _div_codes + '<div class="SnapshotsTitHeight"><input type="button" class="cbi-button cbi-button-apply" value="<%:Restore Snap%>" onclick="return restore_snapshot(this, \'' + mycars[j] + '\')"/></div>'
|
||||
if ( mycars[j] != "etc-000" && mycars[j] != "etc-001" ) { _div_codes = _div_codes + '<div class="SnapshotsTitHeight"><input type="button" class="cbi-button cbi-button-remove" value="<%:Delete Snap%>" onclick="return delete_snapshot(this, \'' + mycars[j] + '\')"/></div>' }
|
||||
_div_codes = _div_codes + '</div>';
|
||||
|
||||
}
|
||||
_check_snapshot.innerHTML = _div_codes ? _div_codes : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
} else {
|
||||
_check_snapshot.innerHTML = "<font color=red>"+ _no_snapshots +"</font>";
|
||||
}
|
||||
});
|
||||
|
||||
//]]></script>
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
<style>
|
||||
.NewsTdHeight{ line-height:20px; }
|
||||
</style>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<table width="100%" class="NewsTdHeight">
|
||||
<tr><td width="100%" colspan="2">
|
||||
<p align="center">
|
||||
<%:After uploading firmware (.img/.img.gz/.img.xz/.7z suffix) or kernel files (3 kernel files), the update button will be displayed.%>
|
||||
</p>
|
||||
</td></tr>
|
||||
<tr><td width="30%" align="right">
|
||||
<input id="_have_firmware" type="button" class="cbi-button cbi-button-reload" value="<%:Update OpenWrt firmware%>" onclick="return amlogic_update(this, 'auto@updated@/tmp')"/>
|
||||
<input id="_have_kernel" type="button" class="cbi-button cbi-button-reload" value="<%:Replace OpenWrt Kernel%>" onclick="return amlogic_kernel(this)"/>
|
||||
</td><td width="70%" align="left">
|
||||
<span id="_current_firmware_version"><%:Collecting data...%></span>
|
||||
<span id="_check_log_firmware"></span><span id="_check_log_kernel"></span>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function amlogic_update(btn,amlogic_update_sel)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Updating...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_update")%>',
|
||||
{
|
||||
amlogic_update_sel: amlogic_update_sel
|
||||
},
|
||||
function(x,status)
|
||||
{
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_update_status!="0")
|
||||
{
|
||||
btn.value = '<%:Update Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successful Update%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Update OpenWrt firmware%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function amlogic_kernel(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Updating...%> ';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_amlogic_kernel")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if(status.rule_kernel_status!="0")
|
||||
{
|
||||
btn.value = '<%:Update Failed%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.value = '<%:Successful Update%>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
btn.value = '<%:Replace OpenWrt Kernel%>';
|
||||
}
|
||||
}
|
||||
);
|
||||
btn.disabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
var _have_firmware = document.getElementById('_have_firmware');
|
||||
var _have_kernel = document.getElementById('_have_kernel');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_upfiles")%>', status.start_check_upfiles, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_upfiles == "firmware\n" || status.start_check_upfiles == "firmware" ) {
|
||||
_have_firmware.style.display = 'block';
|
||||
} else {
|
||||
_have_firmware.style.display = 'none';
|
||||
}
|
||||
|
||||
if ( status.start_check_upfiles == "kernel\n" || status.start_check_upfiles == "kernel" ) {
|
||||
_have_kernel.style.display = 'block';
|
||||
} else {
|
||||
_have_kernel.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _check_log_firmware = document.getElementById('_check_log_firmware');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_firmware")%>', status.start_check_firmware, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_firmware != "\n" && status.start_check_firmware != "" ) {
|
||||
_check_log_firmware.innerHTML = '<font color="blue"> '+status.start_check_firmware+'</font>';
|
||||
}
|
||||
if ( status.start_check_firmware == "\n" || status.start_check_firmware == "" ) {
|
||||
_check_log_firmware.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _check_log_kernel = document.getElementById('_check_log_kernel');
|
||||
XHR.poll(1, '<%=luci.dispatcher.build_url("admin", "system", "amlogic", "start_check_kernel")%>', status.start_check_kernel, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
if ( status.start_check_kernel != "\n" && status.start_check_kernel != "" ) {
|
||||
_check_log_kernel.innerHTML = '<font color="blue"> '+status.start_check_kernel+'</font>';
|
||||
}
|
||||
if ( status.start_check_kernel == "\n" || status.start_check_kernel == "" ) {
|
||||
_check_log_kernel.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var _current_firmware_version = document.getElementById('_current_firmware_version');
|
||||
//var _current_kernel_version = document.getElementById('_current_kernel_version');
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "amlogic", "state")%>', null, function(x, status) {
|
||||
if ( x && x.status == 200 ) {
|
||||
_current_firmware_version.innerHTML = status.current_firmware_version ? "<font color=green><%:Current Version%> [ "+status.current_firmware_version+" ] </font>" : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
//_current_kernel_version.innerHTML = status.current_kernel_version ? "<font color=green><%:Current Version%> [ "+status.current_kernel_version+" ] </font>" : "<font color=red>"+"<%:Invalid value.%>"+"</font>";
|
||||
}
|
||||
});
|
||||
|
||||
//]]></script>
|
||||
@@ -0,0 +1,5 @@
|
||||
<%+cbi/valueheader%>
|
||||
<label class="cbi-value" style="display:inline-block; width: 150px" for="ulfile"><%:Choose local file:%></label>
|
||||
<input class="cbi-input-file" style="width: 400px" type="file" id="ulfile" name="ulfile" />
|
||||
<input type="submit" class="cbi-button cbi-input-apply" name="upload" value="<%:Upload%>" />
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -0,0 +1,588 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: https://github.com/ophub/luci-app-amlogic\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ru_RU\n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
|
||||
msgid "Choose local file:"
|
||||
msgstr "Выберите локальный файл:"
|
||||
|
||||
msgid "Couldn't open file:"
|
||||
msgstr "Не удалось открыть файл:"
|
||||
|
||||
msgid "The file Will download automatically."
|
||||
msgstr "Файл будет загружен автоматически."
|
||||
|
||||
msgid "Create upload file error."
|
||||
msgstr "Ошибка создания загружаемого файла."
|
||||
|
||||
msgid "Download"
|
||||
msgstr "Скачать"
|
||||
|
||||
msgid "Download file"
|
||||
msgstr "Скачать файл"
|
||||
|
||||
msgid "File name"
|
||||
msgstr "Имя файла"
|
||||
|
||||
msgid "File saved to"
|
||||
msgstr "Файл сохранён в"
|
||||
|
||||
msgid "FileTransfer"
|
||||
msgstr "Передача файлов"
|
||||
|
||||
msgid "Install"
|
||||
msgstr "Установить"
|
||||
|
||||
msgid "Attributes"
|
||||
msgstr "Атрибуты"
|
||||
|
||||
msgid "Modify time"
|
||||
msgstr "Время изменения"
|
||||
|
||||
msgid "No specify upload file."
|
||||
msgstr "Не указан файл для загрузки."
|
||||
|
||||
msgid "Path on Route:"
|
||||
msgstr "Путь на маршрутизаторе:"
|
||||
|
||||
msgid "Remove"
|
||||
msgstr "Удалить"
|
||||
|
||||
msgid "Size"
|
||||
msgstr "Размер"
|
||||
|
||||
msgid "Upload"
|
||||
msgstr "Загрузить"
|
||||
|
||||
msgid "Upload file list"
|
||||
msgstr "Список загруженных файлов"
|
||||
|
||||
msgid "There are config file in the upload directory, and you can restore the config. "
|
||||
msgstr "В каталоге загрузки есть файл конфигурации — вы можете восстановить настройки."
|
||||
|
||||
msgid "There are kernel files in the upload directory, and you can replace the kernel."
|
||||
msgstr "В каталоге загрузки находятся файлы ядра — вы можете заменить ядро."
|
||||
|
||||
msgid "There are openwrt firmware file in the upload directory, and you can update the openwrt."
|
||||
msgstr "В каталоге загрузки есть файл прошивки OpenWrt — вы можете обновить OpenWrt."
|
||||
|
||||
msgid "Update plugins first, then update the kernel or firmware."
|
||||
msgstr "Сначала обновите плагины, затем ядро или прошивку."
|
||||
|
||||
msgid "After uploading [Firmware], [Kernel], [IPK] or [Backup Config], the operation buttons will be displayed."
|
||||
msgstr "После загрузки [прошивки], [ядра], [IPK-пакета] или [резервной конфигурации] появятся соответствующие кнопки управления."
|
||||
|
||||
msgid "After uploading firmware (.img/.img.gz/.img.xz/.7z suffix) or kernel files (3 kernel files), the update button will be displayed."
|
||||
msgstr "После загрузки файлов прошивки (с расширениями .img/.img.gz/.img.xz/.7z) или файлов ядра (3 файла), появится кнопка обновления."
|
||||
|
||||
msgid "Amlogic Service"
|
||||
msgstr "Сервис Amlogic"
|
||||
|
||||
msgid "Restore Config / Replace OpenWrt Kernel"
|
||||
msgstr "Восстановить конфигурацию / Заменить ядро OpenWrt"
|
||||
|
||||
msgid "Manually Upload Update"
|
||||
msgstr "Обновление вручную"
|
||||
|
||||
msgid "Install OpenWrt"
|
||||
msgstr "Установить OpenWrt"
|
||||
|
||||
msgid "Select the device model:"
|
||||
msgstr "Выберите модель устройства:"
|
||||
|
||||
msgid "Select List"
|
||||
msgstr "Выбрать из списка"
|
||||
|
||||
msgid "Enter the dtb file name"
|
||||
msgstr "Введите имя файла DTB"
|
||||
|
||||
msgid "Enter the soc name:"
|
||||
msgstr "Введите имя SoC:"
|
||||
|
||||
msgid "Enter the uboot_overload name:"
|
||||
msgstr "Введите имя uboot_overload:"
|
||||
|
||||
msgid "Invalid value."
|
||||
msgstr "Недопустимое значение."
|
||||
|
||||
msgid "Install OpenWrt:"
|
||||
msgstr "Установка OpenWrt:"
|
||||
|
||||
msgid "Install OpenWrt to EMMC, Please select the device model, Or enter the dtb file name."
|
||||
msgstr "Установка OpenWrt на eMMC. Пожалуйста, выберите модель устройства или введите имя файла DTB."
|
||||
|
||||
msgid "Tip: Writing is in progress, and it will automatically restart after completion."
|
||||
msgstr "Подсказка: идёт запись — после завершения устройство автоматически перезагрузится."
|
||||
|
||||
msgid "You have chosen:"
|
||||
msgstr "Вы выбрали:"
|
||||
|
||||
msgid "Start install?"
|
||||
msgstr "Начать установку?"
|
||||
|
||||
msgid "Installing..."
|
||||
msgstr "Установка..."
|
||||
|
||||
msgid "Install Failed"
|
||||
msgstr "Установка не удалась"
|
||||
|
||||
msgid "Successful Install"
|
||||
msgstr "Установка завершена успешно"
|
||||
|
||||
msgid "Update"
|
||||
msgstr "Обновить"
|
||||
|
||||
msgid "Updating..."
|
||||
msgstr "Обновление..."
|
||||
|
||||
msgid "Update Failed"
|
||||
msgstr "Обновление не удалось"
|
||||
|
||||
msgid "Successful Update"
|
||||
msgstr "Обновление завершено успешно"
|
||||
|
||||
msgid "Update OpenWrt firmware"
|
||||
msgstr "Обновить прошивку OpenWrt"
|
||||
|
||||
msgid "kernel"
|
||||
msgstr "ядро"
|
||||
|
||||
msgid "Replace OpenWrt Kernel"
|
||||
msgstr "Заменить ядро OpenWrt"
|
||||
|
||||
msgid "Tip: The kernel is being replaced, and it will automatically restart after completion."
|
||||
msgstr "Подсказка: идёт замена ядра — после завершения устройство автоматически перезагрузится."
|
||||
|
||||
msgid "Supports management of Amlogic s9xxx, Allwinner (V-Plus Cloud), and Rockchip (BeikeYun, Chainedbox L1 Pro) boxes."
|
||||
msgstr "Поддерживает управление устройствами на базе Amlogic s9xxx, Allwinner (V-Plus Cloud) и Rockchip (BeikeYun, Chainedbox L1 Pro)."
|
||||
|
||||
msgid "Supported functions:"
|
||||
msgstr "Поддерживаемые функции:"
|
||||
|
||||
msgid "Provide services such as install to EMMC, Update Firmware and Kernel, Backup and Recovery Config, Snapshot management, etc."
|
||||
msgstr "Позволяет устанавливать OpenWrt на eMMC, обновлять прошивку и ядро, выполнять резервное копирование и восстановление конфигурации, а также управлять снапшотами (мгновенными снимками системы)."
|
||||
|
||||
msgid "Supported Boxes:"
|
||||
msgstr "Поддерживаемые устройства:"
|
||||
|
||||
msgid "Amlogic s922x --- [ Beelink, Beelink-Pro, Ugoos-AM6-Plus, ODROID-N2, Khadas-VIM3, Ali-CT2000 ]"
|
||||
msgstr "Amlogic s922x — [Beelink, Beelink-Pro, Ugoos-AM6-Plus, ODROID-N2, Khadas-VIM3, Ali-CT2000]"
|
||||
|
||||
msgid "Amlogic s905x3 -- [ X96-Max+, HK1-Box, H96-Max-X3, Ugoos-X3, TX3, X96-Air, A95XF3-Air ]"
|
||||
msgstr "Amlogic s905x3 — [X96-Max+, HK1-Box, H96-Max-X3, Ugoos-X3, TX3, X96-Air, A95XF3-Air]"
|
||||
|
||||
msgid "Amlogic s905x2 -- [ X96Max-4G, X96Max-2G, MECOOL-KM3-4G, Tanix-Tx5-Max, A95X-F2 ]"
|
||||
msgstr "Amlogic s905x2 — [X96Max-4G, X96Max-2G, MECOOL-KM3-4G, Tanix-Tx5-Max, A95X-F2]"
|
||||
|
||||
msgid "Amlogic s912 ---- [ H96-Pro-Plus, Octopus-Planet, A1, A2, Z6-Plus, TX92, X92, TX8-MAX, TX9-Pro ]"
|
||||
msgstr "Amlogic s912 — [H96-Pro-Plus, Octopus-Planet, A1, A2, Z6-Plus, TX92, X92, TX8-MAX, TX9-Pro]"
|
||||
|
||||
msgid "Amlogic s905x --- [ HG680P, B860H, TBee, T95, TX9, XiaoMI-3S, X96 ]"
|
||||
msgstr "Amlogic s905x — [HG680P, B860H, TBee, T95, TX9, XiaoMI-3S, X96]"
|
||||
|
||||
msgid "Amlogic s905w --- [ X96-Mini, TX3-Mini, W95, X96W/FunTV, MXQ-Pro-4K ]"
|
||||
msgstr "Amlogic s905w — [X96-Mini, TX3-Mini, W95, X96W/FunTV, MXQ-Pro-4K]"
|
||||
|
||||
msgid "Amlogic s905d --- [ Phicomm-N1, MECOOL-KI-Pro, SML-5442TW ]"
|
||||
msgstr "Amlogic s905d — [Phicomm-N1, MECOOL-KI-Pro, SML-5442TW]"
|
||||
|
||||
msgid "Amlogic s905l --- [ UNT402A, M201-S ]"
|
||||
msgstr "Amlogic s905l — [UNT402A, M201-S]"
|
||||
|
||||
msgid "Amlogic s905l2 -- [ MGV2000, MGV3000, Wojia-TV-IPBS9505, M301A, E900v21E ]"
|
||||
msgstr "Amlogic s905l2 — [MGV2000, MGV3000, Wojia-TV-IPBS9505, M301A, E900v21E]"
|
||||
|
||||
msgid "Amlogic s905l3 -- [ CM211-1, CM311-1, HG680-LC, M401A, UNT400G1, UNT402A, ZXV10-BV310 ]"
|
||||
msgstr "Amlogic s905l3 — [CM211-1, CM311-1, HG680-LC, M401A, UNT400G1, UNT402A, ZXV10-BV310]"
|
||||
|
||||
msgid "Amlogic s905l3a - [ E900V22C/D, CM311-1a-YST, M401A, M411A, UNT403A, UNT413A, IP112H ]"
|
||||
msgstr "Amlogic s905l3a — [E900V22C/D, CM311-1a-YST, M401A, M411A, UNT403A, UNT413A, IP112H]"
|
||||
|
||||
msgid "Amlogic s905l3b - [ CM211-1, CM311-1, E900V22D, E900V21E, E900V22E, M302A/M304A ]"
|
||||
msgstr "Amlogic s905l3b — [CM211-1, CM311-1, E900V22D, E900V21E, E900V22E, M302A/M304A]"
|
||||
|
||||
msgid "Amlogic s905 ---- [ Beelink-Mini-MX-2G, Sunvell-T95M, MXQ-Pro+4K, SumaVision-Q5 ]"
|
||||
msgstr "Amlogic s905 — [Beelink-Mini-MX-2G, Sunvell-T95M, MXQ-Pro+4K, SumaVision-Q5]"
|
||||
|
||||
msgid "Allwinner H6 ---- [ V-Plus Cloud ]"
|
||||
msgstr "Allwinner H6 — [V-Plus Cloud]"
|
||||
|
||||
msgid "Rockchip -------- [ BeikeYun, L1-Pro, FastRhino R66S/R68S, Radxa 5B/E25 ]"
|
||||
msgstr "Rockchip — [BeikeYun, L1-Pro, FastRhino R66S/R68S, Radxa 5B/E25]"
|
||||
|
||||
msgid "Used in KVM ----- [ Can be used in KVM virtual machine of Armbian system. ]"
|
||||
msgstr "Используется в KVM — [можно использовать в виртуальной машине KVM на базе Armbian]."
|
||||
|
||||
msgid "KVM dual system switching"
|
||||
msgstr "Переключение между двумя системами в KVM"
|
||||
|
||||
msgid "You can freely switch between KVM dual partitions, using OpenWrt systems in different partitions."
|
||||
msgstr "Вы можете свободно переключаться между двумя разделами KVM, используя OpenWrt из разных разделов."
|
||||
|
||||
msgid "Switch System"
|
||||
msgstr "Переключить систему"
|
||||
|
||||
msgid "System is switching..."
|
||||
msgstr "Переключение системы..."
|
||||
|
||||
msgid "Waiting for system switching..."
|
||||
msgstr "Ожидание завершения переключения..."
|
||||
|
||||
msgid "System switchover succeeded, restarting..."
|
||||
msgstr "Переключение успешно, перезагрузка..."
|
||||
|
||||
msgid "Are you sure you want to switch systems?"
|
||||
msgstr "Вы уверены, что хотите переключить систему?"
|
||||
|
||||
msgid "Install Ipk"
|
||||
msgstr "Установить IPK"
|
||||
|
||||
msgid "Plugin Settings"
|
||||
msgstr "Настройки плагина"
|
||||
|
||||
msgid "Backup Firmware Config"
|
||||
msgstr "Резервное копирование конфигурации"
|
||||
|
||||
msgid "Backup Config:"
|
||||
msgstr "Резервная копия конфигурации:"
|
||||
|
||||
msgid "Download Backup"
|
||||
msgstr "Скачать резервную копию"
|
||||
|
||||
msgid "Backup OpenWrt config (openwrt_config.tar.gz). Use this file to restore the config in [Manually Upload Update]."
|
||||
msgstr "Создать резервную копию конфигурации OpenWrt (openwrt_config.tar.gz). Используйте этот файл для восстановления в разделе [Обновление вручную]."
|
||||
|
||||
msgid "Edit List:"
|
||||
msgstr "Редактировать список:"
|
||||
|
||||
msgid "Open List"
|
||||
msgstr "Открыть список"
|
||||
|
||||
msgid "Backup Configuration - Custom List"
|
||||
msgstr "Резервная копия — пользовательский список"
|
||||
|
||||
msgid "Write one configuration item per line, and directories should end with a /."
|
||||
msgstr "По одному элементу на строку. Имена каталогов должны оканчиваться на «/»."
|
||||
|
||||
msgid "Restore Backup:"
|
||||
msgstr "Восстановить из резервной копии:"
|
||||
|
||||
msgid "Upload Backup"
|
||||
msgstr "Загрузить резервную копию"
|
||||
|
||||
msgid "Restore"
|
||||
msgstr "Восстановить"
|
||||
|
||||
msgid "Restore Config"
|
||||
msgstr "Восстановить конфигурацию"
|
||||
|
||||
msgid "Restore configuration"
|
||||
msgstr "Восстановление конфигурации"
|
||||
|
||||
msgid "Config File"
|
||||
msgstr "Файл конфигурации"
|
||||
|
||||
msgid "Tip: The config is being restored, and it will automatically restart after completion."
|
||||
msgstr "Подсказка: идёт восстановление конфигурации — после завершения устройство автоматически перезагрузится."
|
||||
|
||||
msgid "Snapshot Management"
|
||||
msgstr "Управление снапшотами"
|
||||
|
||||
msgid "Create Snapshot"
|
||||
msgstr "Создать снапшот"
|
||||
|
||||
msgid "Creating..."
|
||||
msgstr "Создание..."
|
||||
|
||||
msgid "Created successfully"
|
||||
msgstr "Создано успешно"
|
||||
|
||||
msgid "Creation failed"
|
||||
msgstr "Ошибка создания"
|
||||
|
||||
msgid "Initialize Snapshot"
|
||||
msgstr "Инициализировать снапшот"
|
||||
|
||||
msgid "Update Snapshot"
|
||||
msgstr "Обновить снапшот"
|
||||
|
||||
msgid "Restore Snap"
|
||||
msgstr "Восстановить снапшот"
|
||||
|
||||
msgid "Restoring..."
|
||||
msgstr "Восстановление..."
|
||||
|
||||
msgid "Restore Failed"
|
||||
msgstr "Восстановление не удалось"
|
||||
|
||||
msgid "Successfully Restored"
|
||||
msgstr "Восстановлено успешно"
|
||||
|
||||
msgid "Delete Snap"
|
||||
msgstr "Удалить снапшот"
|
||||
|
||||
msgid "You selected a snapshot:"
|
||||
msgstr "Вы выбрали снапшот:"
|
||||
|
||||
msgid "Confirm delete?"
|
||||
msgstr "Подтвердить удаление?"
|
||||
|
||||
msgid "Confirm recovery and restart OpenWrt?"
|
||||
msgstr "Подтвердить восстановление и перезагрузку OpenWrt?"
|
||||
|
||||
msgid "Delete Failed"
|
||||
msgstr "Удаление не удалось"
|
||||
|
||||
msgid "Successfully Deleted"
|
||||
msgstr "Удалено успешно"
|
||||
|
||||
msgid "Create a snapshot of the current system configuration, or restore to a snapshot."
|
||||
msgstr "Создать снапшот текущей конфигурации системы или восстановиться из снапшота."
|
||||
|
||||
msgid "Currently OpenWrt does not support the snapshot function."
|
||||
msgstr "В текущей версии OpenWrt функция снапшотов не поддерживается."
|
||||
|
||||
msgid "Please use this plugin to reinstall or upgrade OpenWrt to enable the snapshot function."
|
||||
msgstr "Пожалуйста, используйте этот плагин для переустановки или обновления OpenWrt, чтобы включить поддержку снапшотов."
|
||||
|
||||
msgid "Deleting..."
|
||||
msgstr "Удаление..."
|
||||
|
||||
msgid "Online Download Update"
|
||||
msgstr "Обновление через интернет"
|
||||
|
||||
msgid "Config Source"
|
||||
msgstr "Источник конфигурации"
|
||||
|
||||
msgid "You can customize the github.com download repository of OpenWrt files and kernels in [Online Download Update]."
|
||||
msgstr "Вы можете настроить репозиторий на github.com для загрузки файлов OpenWrt и ядер в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "Tip: The same files as the current OpenWrt system's BOARD (such as rock5b) and kernel (such as 5.10) will be downloaded."
|
||||
msgstr "Подсказка: будут загружены файлы, соответствующие текущей платформе (например, rock5b) и версии ядра (например, 5.10)."
|
||||
|
||||
msgid "OpenWrt download repository:"
|
||||
msgstr "Репозиторий OpenWrt:"
|
||||
|
||||
msgid "Set the OpenWrt files download repository on github.com in [Online Download Update]."
|
||||
msgstr "Укажите репозиторий на github.com для загрузки файлов OpenWrt в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "OpenWrt download tags keyword:"
|
||||
msgstr "Ключевое слово тега OpenWrt:"
|
||||
|
||||
msgid "Set the OpenWrt files download tags keyword for github.com in [Online Download Update]."
|
||||
msgstr "Укажите ключевое слово тега для загрузки файлов OpenWrt на github.com в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "OpenWrt files suffix:"
|
||||
msgstr "Расширение файлов OpenWrt:"
|
||||
|
||||
msgid "Set the OpenWrt files download suffix for github.com in [Online Download Update]."
|
||||
msgstr "Укажите расширение файлов OpenWrt, загружаемых с github.com, в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "Kernel download repository:"
|
||||
msgstr "Репозиторий ядра:"
|
||||
|
||||
msgid "Set the kernel files download repository on github.com in [Online Download Update]."
|
||||
msgstr "Укажите репозиторий на github.com для загрузки файлов ядра в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "Kernel download tags:"
|
||||
msgstr "Теги ядра:"
|
||||
|
||||
msgid "Set the kernel files download tags on github.com in [Online Download Update]."
|
||||
msgstr "Укажите теги для загрузки файлов ядра на github.com в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "kernel_rk3588 [Rockchip RK3588 Kernel]"
|
||||
msgstr "kernel_rk3588 [Ядро для Rockchip RK3588]"
|
||||
|
||||
msgid "kernel_rk35xx [Rockchip RK35xx Kernel]"
|
||||
msgstr "kernel_rk35xx [Ядро для Rockchip RK35xx]"
|
||||
|
||||
msgid "kernel_stable [Mainline Stable Kernel]"
|
||||
msgstr "kernel_stable [Стабильное ядро из mainline]"
|
||||
|
||||
msgid "kernel_flippy [Mainline Stable Kernel by Flippy]"
|
||||
msgstr "kernel_flippy [Стабильное ядро от Flippy]"
|
||||
|
||||
msgid "kernel_h6 [Allwinner H6 Kernel]"
|
||||
msgstr "kernel_h6 [Ядро для Allwinner H6]"
|
||||
|
||||
msgid "kernel_beta [Beta Kernel]"
|
||||
msgstr "kernel_beta [Бета-версия ядра]"
|
||||
|
||||
msgid "Set version branch:"
|
||||
msgstr "Ветка версии:"
|
||||
|
||||
msgid "Set the version branch of the OpenWrt files and kernel selected in [Online Download Update]."
|
||||
msgstr "Укажите ветку версии для файлов OpenWrt и ядра в разделе [Обновление через интернет]."
|
||||
|
||||
msgid "Keep config update:"
|
||||
msgstr "Сохранять конфигурацию при обновлении:"
|
||||
|
||||
msgid "Set whether to keep the current config during [Online Download Update] and [Manually Upload Update]."
|
||||
msgstr "Выберите, сохранять ли текущую конфигурацию при обновлении через интернет или вручную."
|
||||
|
||||
msgid "Auto write bootloader:"
|
||||
msgstr "Автоматически записывать bootloader:"
|
||||
|
||||
msgid "[Recommended choice] Set whether to auto write bootloader during install and update OpenWrt."
|
||||
msgstr "[Рекомендуется] Указывает, записывать ли автоматически bootloader при установке или обновлении OpenWrt."
|
||||
|
||||
msgid "Set the file system type:"
|
||||
msgstr "Тип файловой системы:"
|
||||
|
||||
msgid "[Default ext4] Set the file system type of the shared partition (/mnt/mmcblk*p4) when install OpenWrt."
|
||||
msgstr "[По умолчанию ext4] Укажите тип файловой системы для общего раздела (/mnt/mmcblk*p4) при установке OpenWrt."
|
||||
|
||||
msgid "Save Config:"
|
||||
msgstr "Сохранить конфигурацию:"
|
||||
|
||||
msgid "Save"
|
||||
msgstr "Сохранить"
|
||||
|
||||
msgid "Check All Components Update"
|
||||
msgstr "Проверка обновлений"
|
||||
|
||||
msgid "Provide OpenWrt Firmware, Kernel and Plugin online check, download and update service."
|
||||
msgstr "Предоставляет онлайн-проверку, загрузку и обновление прошивки OpenWrt, ядра и плагинов."
|
||||
|
||||
msgid "Only update Amlogic Service"
|
||||
msgstr "Обновить только сервис Amlogic"
|
||||
|
||||
msgid "Update system kernel only"
|
||||
msgstr "Обновить только ядро системы"
|
||||
|
||||
msgid "Complete system update"
|
||||
msgstr "Полное обновление системы"
|
||||
|
||||
msgid "Check Update"
|
||||
msgstr "Проверить обновления"
|
||||
|
||||
msgid "Checking..."
|
||||
msgstr "Проверка..."
|
||||
|
||||
msgid "Current Version"
|
||||
msgstr "Текущая версия"
|
||||
|
||||
msgid "Latest Version"
|
||||
msgstr "Последняя версия"
|
||||
|
||||
msgid "Rescue Kernel"
|
||||
msgstr "Аварийное восстановление ядра"
|
||||
|
||||
msgid "When a kernel update fails and causes the OpenWrt system to be unbootable, the kernel can be restored by mutual recovery from eMMC/NVMe/sdX."
|
||||
msgstr "Если обновление ядра привело к невозможности загрузки OpenWrt, его можно восстановить с другого носителя (eMMC/NVMe/sdX)."
|
||||
|
||||
msgid "Rescue the original system kernel"
|
||||
msgstr "Восстановить исходное ядро системы"
|
||||
|
||||
msgid "Rescuing..."
|
||||
msgstr "Восстановление..."
|
||||
|
||||
msgid "Current Device:"
|
||||
msgstr "Текущее устройство:"
|
||||
|
||||
msgid "Display the PLATFORM classification of the device."
|
||||
msgstr "Отображает класс PLATFORM устройства."
|
||||
|
||||
msgid "Update plugins first, then update the kernel or firmware. More options can be configured in [Plugin Settings]."
|
||||
msgstr "Сначала обновите плагины, затем ядро или прошивку. Дополнительные настройки доступны в [Настройках плагина]."
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "Сбор данных..."
|
||||
|
||||
msgid "Server Logs"
|
||||
msgstr "Журнал операций"
|
||||
|
||||
msgid "Display the execution log of the current operation."
|
||||
msgstr "Отображает журнал выполнения текущей операции."
|
||||
|
||||
msgid "Stop Refresh Log"
|
||||
msgstr "Остановить обновление журнала"
|
||||
|
||||
msgid "Start Refresh Log"
|
||||
msgstr "Начать обновление журнала"
|
||||
|
||||
msgid "Clean Log"
|
||||
msgstr "Очистить журнал"
|
||||
|
||||
msgid "Download Log"
|
||||
msgstr "Скачать журнал"
|
||||
|
||||
msgid "CPU Settings"
|
||||
msgstr "Настройки CPU"
|
||||
|
||||
msgid "CPU Freq"
|
||||
msgstr "Частота CPU"
|
||||
|
||||
msgid "CPU Freq Settings"
|
||||
msgstr "Настройки частоты CPU"
|
||||
|
||||
msgid "Set CPU Scaling Governor to Max Performance or Balance Mode"
|
||||
msgstr "Выберите режим управления частотой CPU: максимальная производительность или баланс."
|
||||
|
||||
msgid "CPU Scaling Governor:"
|
||||
msgstr "Режим управления частотой:"
|
||||
|
||||
msgid "ondemand"
|
||||
msgstr "Ondemand — автоматический баланс"
|
||||
|
||||
msgid "performance"
|
||||
msgstr "Performance — максимальная производительность"
|
||||
|
||||
msgid "schedutil"
|
||||
msgstr "Schedutil — умный планировщик"
|
||||
|
||||
msgid "CPU Freq from 48000 to 716000 (Khz)"
|
||||
msgstr "Диапазон частоты CPU: от 48000 до 716000 КГц"
|
||||
|
||||
msgid "Min Freq:"
|
||||
msgstr "Мин. частота:"
|
||||
|
||||
msgid "Max Freq:"
|
||||
msgstr "Макс. частота:"
|
||||
|
||||
msgid "CPU Switching Threshold:"
|
||||
msgstr "Порог переключения частоты CPU:"
|
||||
|
||||
msgid "Kernel make a decision on whether it should increase the frequency (%)"
|
||||
msgstr "При загрузке CPU выше указанного процента (%), ядро увеличит частоту."
|
||||
|
||||
msgid "CPU Switching Sampling rate:"
|
||||
msgstr "Период проверки частоты CPU:"
|
||||
|
||||
msgid "The sampling rate determines how frequently the governor checks to tune the CPU (ms)"
|
||||
msgstr "Частота проверки загрузки CPU (мс). Примечание: слишком частое переключение может вызвать дрожание задержек в сети."
|
||||
|
||||
msgid "Microarchitectures:"
|
||||
msgstr "Микроархитектура:"
|
||||
|
||||
msgid "Loading"
|
||||
msgstr "Загрузка"
|
||||
|
||||
msgid "PowerOff"
|
||||
msgstr "Выключить"
|
||||
|
||||
msgid "Shut down your router device."
|
||||
msgstr "Выключить устройство маршрутизатора."
|
||||
|
||||
msgid "Perform PowerOff"
|
||||
msgstr "Выполнить выключение"
|
||||
|
||||
msgid "Are you sure you want to shut down?"
|
||||
msgstr "Вы уверены, что хотите выключить устройство?"
|
||||
|
||||
msgid "Device is shutting down..."
|
||||
msgstr "Устройство выключается..."
|
||||
|
||||
msgid "Waiting for the device to shut down..."
|
||||
msgstr "Ожидание завершения выключения..."
|
||||
|
||||
msgid "The device has been turned off"
|
||||
msgstr "Устройство выключено"
|
||||
@@ -0,0 +1,593 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: https://github.com/ophub/luci-app-amlogic \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: zh_CN\n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
|
||||
msgid "Choose local file:"
|
||||
msgstr "选择本地文件:"
|
||||
|
||||
msgid "Couldn't open file:"
|
||||
msgstr "无法打开文件:"
|
||||
|
||||
msgid "The file Will download automatically."
|
||||
msgstr "文件将自动下载"
|
||||
|
||||
msgid "Create upload file error."
|
||||
msgstr "创建上传文件失败。"
|
||||
|
||||
msgid "Download"
|
||||
msgstr "下载"
|
||||
|
||||
msgid "Download file"
|
||||
msgstr "下载文件"
|
||||
|
||||
msgid "File name"
|
||||
msgstr "文件名"
|
||||
|
||||
msgid "File saved to"
|
||||
msgstr "文件保存到"
|
||||
|
||||
msgid "FileTransfer"
|
||||
msgstr "文件传输"
|
||||
|
||||
msgid "Install"
|
||||
msgstr "安装"
|
||||
|
||||
msgid "Attributes"
|
||||
msgstr "属性"
|
||||
|
||||
msgid "Modify time"
|
||||
msgstr "修改时间"
|
||||
|
||||
msgid "No specify upload file."
|
||||
msgstr "未指定上传文件。"
|
||||
|
||||
msgid "Path on Route:"
|
||||
msgstr "路由根目录:"
|
||||
|
||||
msgid "Remove"
|
||||
msgstr "移除"
|
||||
|
||||
msgid "Size"
|
||||
msgstr "大小"
|
||||
|
||||
msgid "Upload"
|
||||
msgstr "上传"
|
||||
|
||||
msgid "Upload file list"
|
||||
msgstr "上传文件列表"
|
||||
|
||||
msgid "There are config file in the upload directory, and you can restore the config. "
|
||||
msgstr "上传文件列表中有配置文件,你可以恢复配置。"
|
||||
|
||||
msgid "There are kernel files in the upload directory, and you can replace the kernel."
|
||||
msgstr "上传文件列表中有内核文件,你可以升级内核。"
|
||||
|
||||
msgid "There are openwrt firmware file in the upload directory, and you can update the openwrt."
|
||||
msgstr "上传文件列表中有 OpenWrt 固件文件,你可以升级 OpenWrt。"
|
||||
|
||||
msgid "Update plugins first, then update the kernel or firmware."
|
||||
msgstr "首先更新插件,再更新内核或固件。"
|
||||
|
||||
msgid "After uploading [Firmware], [Kernel], [IPK] or [Backup Config], the operation buttons will be displayed."
|
||||
msgstr "当上传 [固件文件],[内核文件],[IPK文件],[配置文件] 后,将自动显示相关操作按钮。"
|
||||
|
||||
msgid "After uploading firmware (.img/.img.gz/.img.xz/.7z suffix) or kernel files (3 kernel files), the update button will be displayed."
|
||||
msgstr "当上传文件列表中有 OpenWrt 固件(.img/.img.gz/.img.xz/.7z 后缀)或内核文件(3个内核文件)时,将自动显示相关操作按钮。"
|
||||
|
||||
msgid "Amlogic Service"
|
||||
msgstr "晶晨宝盒"
|
||||
|
||||
msgid "Restore Config / Replace OpenWrt Kernel"
|
||||
msgstr "恢复配置 / 升级 OpenWrt 内核"
|
||||
|
||||
msgid "Manually Upload Update"
|
||||
msgstr "手动上传更新"
|
||||
|
||||
msgid "Install OpenWrt"
|
||||
msgstr "安装 OpenWrt"
|
||||
|
||||
msgid "Select the device model:"
|
||||
msgstr "选择设备型号:"
|
||||
|
||||
msgid "Select List"
|
||||
msgstr "选择列表"
|
||||
|
||||
msgid "Enter the dtb file name"
|
||||
msgstr "输入自定义 dtb 文件名"
|
||||
|
||||
msgid "Enter the soc name:"
|
||||
msgstr "输入自定义 soc 名称:"
|
||||
|
||||
msgid "Enter the uboot_overload name:"
|
||||
msgstr "输入自定义 uboot_overload 名称:"
|
||||
|
||||
msgid "Invalid value."
|
||||
msgstr "无效值"
|
||||
|
||||
msgid "Install OpenWrt:"
|
||||
msgstr "安装 OpenWrt:"
|
||||
|
||||
msgid "Install OpenWrt to EMMC, Please select the device model, Or enter the dtb file name."
|
||||
msgstr "将 OpenWrt 安装到 EMMC,请选择设备型号,或输入 dtb 文件名。"
|
||||
|
||||
msgid "Tip: Writing is in progress, and it will automatically restart after completion."
|
||||
msgstr "提示:正在写入,完成后将自动重启。"
|
||||
|
||||
msgid "You have chosen:"
|
||||
msgstr "你选择了:"
|
||||
|
||||
msgid "Start install?"
|
||||
msgstr "开始安装吗?"
|
||||
|
||||
msgid "Installing..."
|
||||
msgstr "正在安装..."
|
||||
|
||||
msgid "Install Failed"
|
||||
msgstr "安装失败"
|
||||
|
||||
msgid "Successful Install"
|
||||
msgstr "安装成功"
|
||||
|
||||
msgid "Update"
|
||||
msgstr "升级"
|
||||
|
||||
msgid "Updating..."
|
||||
msgstr "正在更新..."
|
||||
|
||||
msgid "Update Failed"
|
||||
msgstr "更新失败"
|
||||
|
||||
msgid "Successful Update"
|
||||
msgstr "更新成功"
|
||||
|
||||
msgid "Update OpenWrt firmware"
|
||||
msgstr "升级 OpenWrt 固件"
|
||||
|
||||
msgid "kernel"
|
||||
msgstr "内核"
|
||||
|
||||
msgid "Replace OpenWrt Kernel"
|
||||
msgstr "更换 OpenWrt 内核"
|
||||
|
||||
msgid "Tip: The kernel is being replaced, and it will automatically restart after completion."
|
||||
msgstr "提示:正在替换内核,完成后将自动重启。"
|
||||
|
||||
msgid "Supports management of Amlogic s9xxx, Allwinner (V-Plus Cloud), and Rockchip (BeikeYun, Chainedbox L1 Pro) boxes."
|
||||
msgstr "支持对晶晨 s9xxx 系列(斐讯N1、HK1等),全志(微加云),以及瑞芯微(贝壳云、我家云)的盒子进行在线管理。"
|
||||
|
||||
msgid "Supported functions:"
|
||||
msgstr "支持的功能:"
|
||||
|
||||
msgid "Provide services such as install to EMMC, Update Firmware and Kernel, Backup and Recovery Config, Snapshot management, etc."
|
||||
msgstr "支持将 OpenWrt 系统写入 EMMC、升级固件与内核,备份与恢复自定义配置,快照管理等功能。"
|
||||
|
||||
msgid "Supported Boxes:"
|
||||
msgstr "支持的盒子:"
|
||||
|
||||
msgid "Amlogic s922x --- [ Beelink, Beelink-Pro, Ugoos-AM6-Plus, ODROID-N2, Khadas-VIM3, Ali-CT2000 ]"
|
||||
msgstr "晶晨 s922x --- [ Beelink, Beelink-Pro, Ugoos-AM6-Plus, ODROID-N2, Khadas-VIM3, Ali-CT2000 ]"
|
||||
|
||||
msgid "Amlogic s905x3 -- [ X96-Max+, HK1-Box, H96-Max-X3, Ugoos-X3, TX3, X96-Air, A95XF3-Air ]"
|
||||
msgstr "晶晨 s905x3 -- [ X96-Max+, HK1-Box, H96-Max-X3, Ugoos-X3, TX3, X96-Air, A95XF3-Air ]"
|
||||
|
||||
msgid "Amlogic s905x2 -- [ X96Max-4G, X96Max-2G, MECOOL-KM3-4G, Tanix-Tx5-Max, A95X-F2 ]"
|
||||
msgstr "晶晨 s905x2 -- [ X96Max-4G, X96Max-2G, MECOOL-KM3-4G, Tanix-Tx5-Max, A95X-F2 ]"
|
||||
|
||||
msgid "Amlogic s912 ---- [ H96-Pro-Plus, Octopus-Planet, A1, A2, Z6-Plus, TX92, X92, TX8-MAX, TX9-Pro ]"
|
||||
msgstr "晶晨 s912 ---- [ H96-Pro-Plus, 章鱼星球, A1, A2, Z6-Plus, TX92, X92, TX8-MAX, TX9-Pro ]"
|
||||
|
||||
msgid "Amlogic s905x --- [ HG680P, B860H, TBee, T95, TX9, XiaoMI-3S, X96 ]"
|
||||
msgstr "晶晨 s905x --- [ 烽火HG680, 中兴B860H, TBee, T95, TX9, XiaoMI-3S, X96 ]"
|
||||
|
||||
msgid "Amlogic s905w --- [ X96-Mini, TX3-Mini, W95, X96W/FunTV, MXQ-Pro-4K ]"
|
||||
msgstr "晶晨 s905w --- [ X96-Mini, TX3-Mini, W95, X96W/FunTV, MXQ-Pro-4K ]"
|
||||
|
||||
msgid "Amlogic s905d --- [ Phicomm-N1, MECOOL-KI-Pro, SML-5442TW ]"
|
||||
msgstr "晶晨 s905d --- [ 斐讯-N1, MECOOL-KI-Pro, SML-5442TW ]"
|
||||
|
||||
msgid "Amlogic s905l --- [ UNT402A, M201-S ]"
|
||||
msgstr "晶晨 s905l --- [ UNT402A, M201-S ]"
|
||||
|
||||
msgid "Amlogic s905l2 -- [ MGV2000, MGV3000, Wojia-TV-IPBS9505, M301A, E900v21E ]"
|
||||
msgstr "晶晨 s905l2 -- [ MGV2000, MGV3000, Wojia-TV-IPBS9505, M301A, E900v21E ]"
|
||||
|
||||
msgid "Amlogic s905l3 -- [ CM211-1, CM311-1, HG680-LC, M401A, UNT400G1, UNT402A, ZXV10-BV310 ]"
|
||||
msgstr "晶晨 s905l3 -- [ CM211-1, CM311-1, HG680-LC, M401A, UNT400G1, UNT402A, ZXV10-BV310 ]"
|
||||
|
||||
msgid "Amlogic s905l3a - [ E900V22C/D, CM311-1a-YST, M401A, M411A, UNT403A, UNT413A, IP112H ]"
|
||||
msgstr "晶晨 s905l3a - [ E900V22C/D, CM311-1a-YST, M401A, M411A, UNT403A, UNT413A, IP112H ]"
|
||||
|
||||
msgid "Amlogic s905l3b - [ CM211-1, CM311-1, E900V22D, E900V21E, E900V22E, M302A/M304A ]"
|
||||
msgstr "晶晨 s905l3b - [ CM211-1, CM311-1, E900V22D, E900V21E, E900V22E, M302A/M304A ]"
|
||||
|
||||
msgid "Amlogic s905 ---- [ Beelink-Mini-MX-2G, Sunvell-T95M, MXQ-Pro+4K, SumaVision-Q5 ]"
|
||||
msgstr "晶晨 s905 ---- [ Beelink-Mini-MX-2G, Sunvell-T95M, MXQ-Pro+4K, SumaVision-Q5 ]"
|
||||
|
||||
msgid "Allwinner H6 ---- [ V-Plus Cloud ]"
|
||||
msgstr "全志 H6 ------ [ 微加云 ]"
|
||||
|
||||
msgid "Rockchip -------- [ BeikeYun, L1-Pro, FastRhino R66S/R68S, Radxa 5B/E25 ]"
|
||||
msgstr "瑞芯微 ------- [ 贝壳云, 我家云, 电犀牛R66S/R68S, 瑞莎5B/E25 ]"
|
||||
|
||||
msgid "Used in KVM ----- [ Can be used in KVM virtual machine of Armbian system. ]"
|
||||
msgstr "KVM 中使用 --- [ 可以在 Armbian 系统的 KVM 虚拟机中使用。 ]"
|
||||
|
||||
msgid "KVM dual system switching"
|
||||
msgstr "KVM 双系统切换"
|
||||
|
||||
msgid "You can freely switch between KVM dual partitions, using OpenWrt systems in different partitions."
|
||||
msgstr "您可以在 KVM 双分区之间自由切换,使用不同分区中的 OpenWrt 系统。"
|
||||
|
||||
msgid "Switch System"
|
||||
msgstr "切换系统"
|
||||
|
||||
msgid "System is switching..."
|
||||
msgstr "系统切换中..."
|
||||
|
||||
msgid "Waiting for system switching..."
|
||||
msgstr "等待系统完成切换..."
|
||||
|
||||
msgid "System switchover succeeded, restarting..."
|
||||
msgstr "系统切换成功,正在重启..."
|
||||
|
||||
msgid "Are you sure you want to switch systems?"
|
||||
msgstr "你确定要切换系统吗?"
|
||||
|
||||
msgid "Install Ipk"
|
||||
msgstr "安装Ipk"
|
||||
|
||||
msgid "Plugin Settings"
|
||||
msgstr "插件设置"
|
||||
|
||||
msgid "Backup Firmware Config"
|
||||
msgstr "备份固件配置"
|
||||
|
||||
msgid "Backup Config:"
|
||||
msgstr "备份配置:"
|
||||
|
||||
msgid "Download Backup"
|
||||
msgstr "下载备份"
|
||||
|
||||
msgid "Backup OpenWrt config (openwrt_config.tar.gz). Use this file to restore the config in [Manually Upload Update]."
|
||||
msgstr "备份当前 OpenWrt 的相关配置信息(openwrt_config.tar.gz)。使用此文件可在 [手动上传更新] 中恢复配置。"
|
||||
|
||||
msgid "Edit List:"
|
||||
msgstr "编辑列表:"
|
||||
|
||||
msgid "Open List"
|
||||
msgstr "打开列表"
|
||||
|
||||
msgid "Backup Configuration - Custom List"
|
||||
msgstr "备份配置 - 自定义列表"
|
||||
|
||||
msgid "Write one configuration item per line, and directories should end with a /."
|
||||
msgstr "每行写一个配置项,目录需要以/结尾。"
|
||||
|
||||
msgid "Restore Backup:"
|
||||
msgstr "恢复备份:"
|
||||
|
||||
msgid "Upload Backup"
|
||||
msgstr "上传备份"
|
||||
|
||||
msgid "Restore"
|
||||
msgstr "恢复"
|
||||
|
||||
msgid "Restore Config"
|
||||
msgstr "恢复配置"
|
||||
|
||||
msgid "Restore configuration"
|
||||
msgstr "还原配置"
|
||||
|
||||
msgid "Config File"
|
||||
msgstr "配置文件"
|
||||
|
||||
msgid "Tip: The config is being restored, and it will automatically restart after completion."
|
||||
msgstr "提示:正在还原配置,完成后将自动重启。"
|
||||
|
||||
msgid "Snapshot Management"
|
||||
msgstr "快照管理"
|
||||
|
||||
msgid "Create Snapshot"
|
||||
msgstr "创建快照"
|
||||
|
||||
msgid "Creating..."
|
||||
msgstr "正在创建"
|
||||
|
||||
msgid "Created successfully"
|
||||
msgstr "创建成功"
|
||||
|
||||
msgid "Creation failed"
|
||||
msgstr "创建失败"
|
||||
|
||||
msgid "Initialize Snapshot"
|
||||
msgstr "初始化快照"
|
||||
|
||||
msgid "Update Snapshot"
|
||||
msgstr "更新点快照"
|
||||
|
||||
msgid "Restore Snap"
|
||||
msgstr "还原快照"
|
||||
|
||||
msgid "Restoring..."
|
||||
msgstr "正在还原"
|
||||
|
||||
msgid "Restore Failed"
|
||||
msgstr "还原失败"
|
||||
|
||||
msgid "Successfully Restored"
|
||||
msgstr "还原成功"
|
||||
|
||||
msgid "Delete Snap"
|
||||
msgstr "删除快照"
|
||||
|
||||
msgid "You selected a snapshot:"
|
||||
msgstr "你选择了快照:"
|
||||
|
||||
msgid "Confirm delete?"
|
||||
msgstr "确定删除吗?"
|
||||
|
||||
msgid "Confirm recovery and restart OpenWrt?"
|
||||
msgstr "确定恢复并重启 OpenWrt 吗?"
|
||||
|
||||
msgid "Delete Failed"
|
||||
msgstr "删除失败"
|
||||
|
||||
msgid "Successfully Deleted"
|
||||
msgstr "删除成功"
|
||||
|
||||
msgid "Create a snapshot of the current system configuration, or restore to a snapshot."
|
||||
msgstr "创建当前系统配置的快照,或还原到某个快照。"
|
||||
|
||||
msgid "Currently OpenWrt does not support the snapshot function."
|
||||
msgstr "当前 OpenWrt 不支持快照功能。"
|
||||
|
||||
msgid "Please use this plugin to reinstall or upgrade OpenWrt to enable the snapshot function."
|
||||
msgstr "请使用本插件重新安装或升级 OpenWrt 开启快照功能。"
|
||||
|
||||
msgid "Deleting..."
|
||||
msgstr "正在删除..."
|
||||
|
||||
msgid "Online Download Update"
|
||||
msgstr "在线下载更新"
|
||||
|
||||
msgid "Config Source"
|
||||
msgstr "配置来源"
|
||||
|
||||
msgid "You can customize the github.com download repository of OpenWrt files and kernels in [Online Download Update]."
|
||||
msgstr "您可以自定义 [在线下载和更新] 中 OpenWrt 固件和内核的 github.com 下载仓库。"
|
||||
|
||||
msgid "Tip: The same files as the current OpenWrt system's BOARD (such as rock5b) and kernel (such as 5.10) will be downloaded."
|
||||
msgstr "提示:将下载与当前 OpenWrt 系统的 BOARD(如:rock5b)和内核(如:5.10)相同的文件。"
|
||||
|
||||
msgid "OpenWrt download repository:"
|
||||
msgstr "OpenWrt 文件的下载仓库:"
|
||||
|
||||
msgid "Set the OpenWrt files download repository on github.com in [Online Download Update]."
|
||||
msgstr "设置 [在线下载更新] 中 github.com 的 OpenWrt 文件的下载仓库。"
|
||||
|
||||
msgid "OpenWrt download tags keyword:"
|
||||
msgstr "OpenWrt 下载标签关键字:"
|
||||
|
||||
msgid "Set the OpenWrt files download tags keyword for github.com in [Online Download Update]."
|
||||
msgstr "设置 [在线下载更新] 中 github.com 的 OpenWrt 文件下载标签关键字。"
|
||||
|
||||
msgid "OpenWrt files suffix:"
|
||||
msgstr "OpenWrt 文件的后缀:"
|
||||
|
||||
msgid "Set the OpenWrt files download suffix for github.com in [Online Download Update]."
|
||||
msgstr "设置 [在线下载更新] 中 github.com 的 OpenWrt 文件的后缀。"
|
||||
|
||||
msgid "Kernel download repository:"
|
||||
msgstr "内核的下载仓库:"
|
||||
|
||||
msgid "Set the kernel files download repository on github.com in [Online Download Update]."
|
||||
msgstr "设置 [在线下载更新] 中 github.com 的内核文件下载仓库。"
|
||||
|
||||
msgid "Kernel download tags:"
|
||||
msgstr "内核的下载标签:"
|
||||
|
||||
msgid "Set the kernel files download tags on github.com in [Online Download Update]."
|
||||
msgstr "设置 [在线下载更新] 中 github.com 的内核文件下载标签。"
|
||||
|
||||
msgid "kernel_rk3588 [Rockchip RK3588 Kernel]"
|
||||
msgstr "kernel_rk3588 [Rockchip RK3588 内核]"
|
||||
|
||||
msgid "kernel_rk35xx [Rockchip RK35xx Kernel]"
|
||||
msgstr "kernel_rk35xx [Rockchip RK35xx 内核]"
|
||||
|
||||
msgid "kernel_stable [Mainline Stable Kernel]"
|
||||
msgstr "kernel_stable [主线稳定内核]"
|
||||
|
||||
msgid "kernel_flippy [Mainline Stable Kernel by Flippy]"
|
||||
msgstr "kernel_flippy [Flippy 的主线稳定内核]"
|
||||
|
||||
msgid "kernel_h6 [Allwinner H6 Kernel]"
|
||||
msgstr "kernel_h6 [Allwinner H6 内核]"
|
||||
|
||||
msgid "kernel_beta [Beta Kernel]"
|
||||
msgstr "kernel_beta [测试版内核]"
|
||||
|
||||
msgid "Set version branch:"
|
||||
msgstr "设置版本分支:"
|
||||
|
||||
msgid "Set the version branch of the OpenWrt files and kernel selected in [Online Download Update]."
|
||||
msgstr "设置 [在线下载更新] 时 OpenWrt 文件与内核所选用的版本分支。"
|
||||
|
||||
msgid "Keep config update:"
|
||||
msgstr "保留配置更新:"
|
||||
|
||||
msgid "Set whether to keep the current config during [Online Download Update] and [Manually Upload Update]."
|
||||
msgstr "设置是否在 [在线下载更新] 和 [手动上传更新] 时保留当前的配置。"
|
||||
|
||||
msgid "Auto write bootloader:"
|
||||
msgstr "自动写入 bootloader:"
|
||||
|
||||
msgid "[Recommended choice] Set whether to auto write bootloader during install and update OpenWrt."
|
||||
msgstr "[推荐选择] 设置在安装和更新 OpenWrt 固件时是否自动写入 bootloader 文件。"
|
||||
|
||||
msgid "Set the file system type:"
|
||||
msgstr "设置文件系统类型:"
|
||||
|
||||
msgid "[Default ext4] Set the file system type of the shared partition (/mnt/mmcblk*p4) when install OpenWrt."
|
||||
msgstr "[默认 ext4] 设置安装 OpenWrt 时共享分区 (/mnt/mmcblk*p4) 的文件系统类型。"
|
||||
|
||||
msgid "Save Config:"
|
||||
msgstr "保存配置:"
|
||||
|
||||
msgid "Save"
|
||||
msgstr "保存"
|
||||
|
||||
msgid "Check All Components Update"
|
||||
msgstr "插件和内核检查更新"
|
||||
|
||||
msgid "Provide OpenWrt Firmware, Kernel and Plugin online check, download and update service."
|
||||
msgstr "提供 OpenWrt 固件,内核和插件在线检查,下载和更新服务。"
|
||||
|
||||
msgid "Only update Amlogic Service"
|
||||
msgstr "仅更新晶晨宝盒"
|
||||
|
||||
msgid "Update system kernel only"
|
||||
msgstr "仅更新系统内核"
|
||||
|
||||
msgid "Complete system update"
|
||||
msgstr "完整更新全系统"
|
||||
|
||||
msgid "Check Update"
|
||||
msgstr "检查更新"
|
||||
|
||||
msgid "Checking..."
|
||||
msgstr "正在检查更新..."
|
||||
|
||||
msgid "Current Version"
|
||||
msgstr "当前版本"
|
||||
|
||||
msgid "Latest Version"
|
||||
msgstr "最新版本"
|
||||
|
||||
msgid "Rescue Kernel"
|
||||
msgstr "救援内核"
|
||||
|
||||
msgid "When a kernel update fails and causes the OpenWrt system to be unbootable, the kernel can be restored by mutual recovery from eMMC/NVMe/sdX."
|
||||
msgstr "当内核更新失败造成 OpenWrt 系统无法启动时,可以从 eMMC/NVME/sdX 相互恢复内核。"
|
||||
|
||||
msgid "Rescue the original system kernel"
|
||||
msgstr "救援原系统内核"
|
||||
|
||||
msgid "Rescuing..."
|
||||
msgstr "正在救援..."
|
||||
|
||||
msgid "Current Device:"
|
||||
msgstr "当前设备:"
|
||||
|
||||
msgid "Display the PLATFORM classification of the device."
|
||||
msgstr "显示设备的 PLATFORM 分类。"
|
||||
|
||||
msgid "Update plugins first, then update the kernel or firmware. More options can be configured in [Plugin Settings]."
|
||||
msgstr "首先更新插件,再更新内核或固件。更多选项可以在插件设置中配置。"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在收集数据…"
|
||||
|
||||
msgid "Check All Components Update"
|
||||
msgstr "插件和内核检查更新"
|
||||
|
||||
msgid "Server Logs"
|
||||
msgstr "操作日志"
|
||||
|
||||
msgid "Display the execution log of the current operation."
|
||||
msgstr "显示当前操作的执行日志。"
|
||||
|
||||
msgid "Stop Refresh Log"
|
||||
msgstr "停止刷新"
|
||||
|
||||
msgid "Start Refresh Log"
|
||||
msgstr "开始刷新"
|
||||
|
||||
msgid "Clean Log"
|
||||
msgstr "清理日志"
|
||||
|
||||
msgid "Download Log"
|
||||
msgstr "下载日志"
|
||||
|
||||
msgid "CPU Settings"
|
||||
msgstr "CPU 设置"
|
||||
|
||||
msgid "CPU Freq"
|
||||
msgstr "CPU 性能优化调节"
|
||||
|
||||
msgid "CPU Freq Settings"
|
||||
msgstr "CPU 性能优化调节设置"
|
||||
|
||||
msgid "Set CPU Scaling Governor to Max Performance or Balance Mode"
|
||||
msgstr "设置路由器的 CPU 性能模式(高性能/均衡省电)"
|
||||
|
||||
msgid "CPU Scaling Governor:"
|
||||
msgstr "CPU 调速器:"
|
||||
|
||||
msgid "ondemand"
|
||||
msgstr "Ondemand 自动平衡模式"
|
||||
|
||||
msgid "performance"
|
||||
msgstr "Performance 高性能模式"
|
||||
|
||||
msgid "schedutil"
|
||||
msgstr "Schedutil 敏捷调度器模式"
|
||||
|
||||
msgid "CPU Freq from 48000 to 716000 (Khz)"
|
||||
msgstr "CPU 频率范围为 48000 到 716000 (Khz)"
|
||||
|
||||
msgid "Min Freq:"
|
||||
msgstr "最小频率:"
|
||||
|
||||
msgid "Max Freq:"
|
||||
msgstr "最大频率:"
|
||||
|
||||
msgid "CPU Switching Threshold:"
|
||||
msgstr "CPU 切换频率触发阈值:"
|
||||
|
||||
msgid "Kernel make a decision on whether it should increase the frequency (%)"
|
||||
msgstr "当 CPU 占用率超过 (%) 的情况下触发内核切换频率"
|
||||
|
||||
msgid "CPU Switching Sampling rate:"
|
||||
msgstr "CPU 切换周期:"
|
||||
|
||||
msgid "The sampling rate determines how frequently the governor checks to tune the CPU (ms)"
|
||||
msgstr "CPU 检查切换的周期 (ms) 。注意:过于频繁的切换频率会引起网络延迟抖动"
|
||||
|
||||
msgid "Microarchitectures:"
|
||||
msgstr "微架构:"
|
||||
|
||||
msgid "Loading"
|
||||
msgstr "载入中"
|
||||
|
||||
msgid "PowerOff"
|
||||
msgstr "关机"
|
||||
|
||||
msgid "Shut down your router device."
|
||||
msgstr "关闭你的路由器设备。"
|
||||
|
||||
msgid "Perform PowerOff"
|
||||
msgstr "执行关机"
|
||||
|
||||
msgid "Are you sure you want to shut down?"
|
||||
msgstr "你确定要关机吗?"
|
||||
|
||||
msgid "Device is shutting down..."
|
||||
msgstr "设备正在关机..."
|
||||
|
||||
msgid "Waiting for the device to shut down..."
|
||||
msgstr "等待设备关机..."
|
||||
|
||||
msgid "The device has been turned off"
|
||||
msgstr "设备已经关机"
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
zh-cn
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
config amlogic 'config'
|
||||
option enable '1'
|
||||
option amlogic_firmware_repo 'https://github.com/breakingbadboy/OpenWrt'
|
||||
option amlogic_firmware_tag 'ARMv8'
|
||||
option amlogic_firmware_suffix '.img.gz'
|
||||
option amlogic_kernel_path 'https://github.com/breakingbadboy/OpenWrt'
|
||||
option amlogic_kernel_tags ''
|
||||
option amlogic_kernel_branch ''
|
||||
option amlogic_firmware_config '1'
|
||||
option amlogic_write_bootloader '0'
|
||||
option amlogic_shared_fstype 'ext4'
|
||||
|
||||
config settings 'armcpu'
|
||||
option governor0 'schedutil'
|
||||
option minfreq0 '500000'
|
||||
option maxfreq0 '1512000'
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
START=60
|
||||
|
||||
NAME=amlogic
|
||||
|
||||
uci_get_by_type() {
|
||||
local ret=$(uci get $NAME.@$1[0].$2 2>/dev/null)
|
||||
echo ${ret:=$3}
|
||||
}
|
||||
|
||||
uci_set_by_type() {
|
||||
uci set $NAME.@$1[0].$2=$3 2>/dev/null
|
||||
uci commit $NAME
|
||||
}
|
||||
|
||||
start() {
|
||||
[ -x "/usr/sbin/fixcpufreq.pl" ] && /usr/sbin/fixcpufreq.pl && sync
|
||||
local cpu_policys=$(ls /sys/devices/system/cpu/cpufreq 2>/dev/null | grep -E 'policy[0-9]{1,3}' | xargs)
|
||||
if [ "${cpu_policys}" = "" ]; then
|
||||
cpu_policys="policy0"
|
||||
fi
|
||||
|
||||
config_load $NAME
|
||||
for policy_name in ${cpu_policys}; do
|
||||
local policy_id="${policy_name//policy/}"
|
||||
|
||||
# Get an optional value list for the current device
|
||||
local governor_list="$(cat /sys/devices/system/cpu/cpufreq/${policy_name}/scaling_available_frequencies 2>/dev/null | xargs)"
|
||||
local second_place_order="$(echo ${governor_list} | awk '{print $1}')"
|
||||
local second_place_reverse="$(echo ${governor_list} | awk '{print $NF}')"
|
||||
|
||||
# Get the default value in the Config file
|
||||
local governor=$(uci_get_by_type settings governor${policy_id} schedutil)
|
||||
local minfreq=$(uci_get_by_type settings minfreq${policy_id} ${second_place_order})
|
||||
local maxfreq=$(uci_get_by_type settings maxfreq${policy_id} ${second_place_reverse})
|
||||
|
||||
# Update result to the corresponding file
|
||||
echo $governor >/sys/devices/system/cpu/cpufreq/${policy_name}/scaling_governor
|
||||
echo $minfreq >/sys/devices/system/cpu/cpufreq/${policy_name}/scaling_min_freq
|
||||
echo $maxfreq >/sys/devices/system/cpu/cpufreq/${policy_name}/scaling_max_freq
|
||||
|
||||
# If the governor is ondemand, configure its specific parameters.
|
||||
if [ "$governor" = "ondemand" ]; then
|
||||
local ondemand_dir="/sys/devices/system/cpu/cpufreq/${policy_name}/ondemand"
|
||||
# Check if the per-policy ondemand directory exists.
|
||||
if [ -d "$ondemand_dir" ]; then
|
||||
# Read ondemand parameters from UCI, or use default values (e.g., 80 and 20) if not set.
|
||||
local up_threshold=$(uci_get_by_type settings up_threshold${policy_id} 80)
|
||||
local sampling_down_factor=$(uci_get_by_type settings sampling_down_factor${policy_id} 20)
|
||||
|
||||
# Write the values to the system files.
|
||||
echo $up_threshold > "${ondemand_dir}/up_threshold"
|
||||
echo $sampling_down_factor > "${ondemand_dir}/sampling_down_factor"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
reload() {
|
||||
start
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
[ ! -f "/usr/share/ucitrack/luci-app-amlogic.json" ] && {
|
||||
cat > /usr/share/ucitrack/luci-app-amlogic.json << EEOF
|
||||
{
|
||||
"config": "amlogic",
|
||||
"init": "amlogic"
|
||||
}
|
||||
EEOF
|
||||
}
|
||||
|
||||
sed -i 's/cbi.submit\"] = true/cbi.submit\"] = \"1\"/g' /usr/lib/lua/luci/dispatcher.lua
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@amlogic[-1]
|
||||
add ucitrack amlogic
|
||||
set ucitrack.@amlogic[-1].init=amlogic
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -rf /tmp/luci-*
|
||||
exit 0
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use File::Basename;
|
||||
|
||||
my $uci_config_name;
|
||||
if(-f "/etc/config/amlogic") {
|
||||
$uci_config_name="amlogic";
|
||||
} elsif(-f "/etc/config/cpufreq") {
|
||||
$uci_config_name="cpufreq";
|
||||
} else {
|
||||
print "Can not found amlogic or cpufreq config file!\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my @policy_ids;
|
||||
my @policy_homes = </sys/devices/system/cpu/cpufreq/policy?>;
|
||||
if(@policy_homes) {
|
||||
foreach my $policy_home (@policy_homes) {
|
||||
push @policy_ids, substr($policy_home, -1);
|
||||
}
|
||||
} else {
|
||||
print "Can not found any policy!\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
our $need_commit = 0;
|
||||
for(my $i=0; $i <= $#policy_ids; $i++) {
|
||||
&fix_invalid_value($uci_config_name, $policy_ids[$i], $policy_homes[$i]);
|
||||
|
||||
}
|
||||
|
||||
if($need_commit > 0) {
|
||||
&uci_commit($uci_config_name);
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
||||
################################# function ####################################
|
||||
sub fix_invalid_value {
|
||||
my($uci_config, $policy_id, $policy_home) = @_;
|
||||
|
||||
my %gove_hash = &get_gove_hash($policy_home);
|
||||
my @freqs = &get_freq_list($policy_home);
|
||||
my %freq_hash = &get_freq_hash(@freqs);
|
||||
my $min_freq = &get_min_freq(@freqs);
|
||||
my $max_freq = &get_max_freq(@freqs);
|
||||
|
||||
my $uci_section = "settings";
|
||||
my $uci_option;
|
||||
if($uci_config eq "cpufreq" ) {
|
||||
$uci_option = "governor";
|
||||
} else {
|
||||
$uci_option = "governor" . $policy_id;
|
||||
}
|
||||
# 如果未设置 governor, 或该 goveernor 不存在, 则修败默认值为 schedutil
|
||||
my $config_gove = &uci_get_by_type($uci_config, $uci_section, $uci_option, "NA");
|
||||
if( ($config_gove eq "NA") ||
|
||||
($gove_hash{$config_gove} != 1)) {
|
||||
&uci_set_by_type($uci_config, $uci_section, $uci_option, "schedutil");
|
||||
$need_commit++;
|
||||
}
|
||||
|
||||
# 如果出现不存在的 minfreq, 则修改为实际的 min_freq
|
||||
if($uci_config eq "cpufreq" ) {
|
||||
# "minifreq" is a spelling error that has always existed in the upstream source code
|
||||
$uci_option = "minifreq";
|
||||
} else {
|
||||
$uci_option = "minfreq" . $policy_id;
|
||||
}
|
||||
my $config_min_freq = &uci_get_by_type($uci_config, $uci_section, $uci_option, "0");
|
||||
if($freq_hash{$config_min_freq} != 1) {
|
||||
&uci_set_by_type($uci_config, $uci_section, $uci_option, $min_freq);
|
||||
$need_commit++;
|
||||
}
|
||||
|
||||
# 如果出现不存在的 maxfreq
|
||||
# 或 maxfreq < minfreq, 则修改为实际的 max_freq
|
||||
if($uci_config eq "cpufreq" ) {
|
||||
$uci_option = "maxfreq";
|
||||
} else {
|
||||
$uci_option = "maxfreq" . $policy_id;
|
||||
}
|
||||
my $config_max_freq = &uci_get_by_type($uci_config, $uci_section, $uci_option, "0");
|
||||
if( ( $freq_hash{$config_max_freq} != 1) ||
|
||||
( $config_max_freq < $config_min_freq)) {
|
||||
&uci_set_by_type($uci_config, $uci_section, $uci_option, $max_freq);
|
||||
$need_commit++;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_freq_list {
|
||||
my $policy_home = shift;
|
||||
my @ret_ary;
|
||||
open my $fh, "<", "${policy_home}/scaling_available_frequencies" or die;
|
||||
$_ = <$fh>;
|
||||
chomp;
|
||||
@ret_ary = split /\s+/;
|
||||
close($fh);
|
||||
return @ret_ary;
|
||||
}
|
||||
|
||||
sub get_freq_hash {
|
||||
my @freq_ary = @_;
|
||||
my %ret_hash;
|
||||
foreach my $freq (@freq_ary) {
|
||||
if($freq =~ m/\d+/) {
|
||||
$ret_hash{$freq} = 1;
|
||||
}
|
||||
}
|
||||
return %ret_hash;
|
||||
}
|
||||
|
||||
sub get_min_freq {
|
||||
my @freq_ary = @_;
|
||||
return (sort {$a<=>$b} @freq_ary)[0];
|
||||
}
|
||||
|
||||
sub get_max_freq {
|
||||
my @freq_ary = @_;
|
||||
return (sort {$a<=>$b} @freq_ary)[-1];
|
||||
}
|
||||
|
||||
sub get_gove_hash {
|
||||
my $policy_home = shift;
|
||||
my %ret_hash;
|
||||
open my $fh, "<", "${policy_home}/scaling_available_governors" or die;
|
||||
$_ = <$fh>;
|
||||
chomp;
|
||||
my @gov_ary = split /\s+/;
|
||||
foreach my $gov (@gov_ary) {
|
||||
#print "gov: $gov\n";
|
||||
if($gov =~ m/\w+/) {
|
||||
$ret_hash{$gov} = 1;
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
return %ret_hash;
|
||||
}
|
||||
|
||||
sub uci_get_by_type {
|
||||
my($config,$section,$option,$default) = @_;
|
||||
my $ret;
|
||||
$ret=`uci get ${config}.\@${section}\[0\].${option} 2>/dev/null`;
|
||||
# 消除回车换行
|
||||
$ret =~ s/[\n\r]//g;
|
||||
if($ret eq '') {
|
||||
return $default;
|
||||
} else {
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
sub uci_set_by_type {
|
||||
my($config,$section,$option,$value) = @_;
|
||||
my $ret;
|
||||
system("uci set ${config}.\@${section}\[0\].${option}=${value}");
|
||||
return;
|
||||
}
|
||||
|
||||
sub uci_commit {
|
||||
my $config = shift;
|
||||
system("uci commit ${config}");
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,598 @@
|
||||
#!/bin/bash
|
||||
#======================================================================
|
||||
# Function: Backup and restore config files in the /etc directory
|
||||
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
|
||||
#======================================================================
|
||||
|
||||
VERSION="v1.3"
|
||||
ZSTD_LEVEL=6
|
||||
SNAPSHOT_PRESTR=".snapshots/"
|
||||
BACKUP_DIR="/.reserved"
|
||||
BACKUP_NAME="openwrt_config.tar.gz"
|
||||
BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}"
|
||||
# Customize backup list
|
||||
backup_list_conf="/etc/amlogic_backup_list.conf"
|
||||
if [[ -s "${backup_list_conf}" ]]; then
|
||||
while IFS= read -r line; do
|
||||
BACKUP_LIST+="${line} "
|
||||
done <"${backup_list_conf}"
|
||||
else
|
||||
BACKUP_LIST='./etc/AdGuardHome.yaml \
|
||||
./etc/amlogic_backup_list.conf \
|
||||
./etc/adblocklist/ \
|
||||
./etc/amule/ \
|
||||
./etc/balance_irq \
|
||||
./etc/bluetooth/ \
|
||||
./etc/china_ssr.txt \
|
||||
./etc/cifs/cifsdpwd.db \
|
||||
./etc/smbd/smbdpwd.db \
|
||||
./etc/ksmbd/ksmbdpwd.db \
|
||||
./etc/config/ \
|
||||
./etc/crontabs/ \
|
||||
./etc/dae/ \
|
||||
./etc/daed/ \
|
||||
./usr/share/openclash/core/ \
|
||||
./etc/openclash/backup/ \
|
||||
./etc/openclash/config/ \
|
||||
./etc/openclash/custom/ \
|
||||
./etc/openclash/game_rules/ \
|
||||
./etc/openclash/rule_provider/ \
|
||||
./etc/openclash/proxy_provider/ \
|
||||
./etc/dnsforwarder/ \
|
||||
./etc/dnsmasq.conf \
|
||||
./etc/dnsmasq.d/ \
|
||||
./etc/dnsmasq.oversea/ \
|
||||
./etc/dnsmasq.ssr/ \
|
||||
./etc/docker/daemon.json \
|
||||
./etc/docker/key.json \
|
||||
./etc/dropbear/ \
|
||||
./etc/easy-rsa/ \
|
||||
./etc/environment \
|
||||
./etc/exports \
|
||||
./etc/firewall.user \
|
||||
./etc/gfwlist/ \
|
||||
./etc/haproxy.cfg \
|
||||
./etc/hosts \
|
||||
./etc/ipsec.conf \
|
||||
./etc/ipsec.d/ \
|
||||
./etc/ipsec.secrets \
|
||||
./etc/ipsec.user \
|
||||
./etc/ipset/ \
|
||||
./etc/mosdns/config.yaml \
|
||||
./etc/mwan3.user \
|
||||
./etc/nginx/nginx.conf \
|
||||
./etc/ocserv/ \
|
||||
./etc/openvpn/ \
|
||||
./etc/pptpd.conf \
|
||||
./etc/qBittorrent/ \
|
||||
./etc/rc.local \
|
||||
./etc/samba/smbpasswd \
|
||||
./etc/shadow \
|
||||
./etc/smartdns/ \
|
||||
./etc/sqm/ \
|
||||
./etc/ssh/*key* \
|
||||
./etc/ssl/private/ \
|
||||
./etc/ssrplus/ \
|
||||
./etc/sysupgrade.conf \
|
||||
./etc/tailscale/ \
|
||||
./etc/transmission/ \
|
||||
./etc/uhttpd.crt \
|
||||
./etc/uhttpd.key \
|
||||
./etc/urandom.seed \
|
||||
./etc/v2raya/ \
|
||||
./etc/verysync/ \
|
||||
./root/.ssh/'
|
||||
fi
|
||||
|
||||
error_msg() {
|
||||
echo -e " [ERROR] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if dmesg | grep 'meson' >/dev/null 2>&1; then
|
||||
PLATFORM="amlogic"
|
||||
elif dmesg | grep 'rockchip' >/dev/null 2>&1; then
|
||||
PLATFORM="rockchip"
|
||||
elif dmesg | grep 'sun50i-h6' >/dev/null 2>&1; then
|
||||
PLATFORM="allwinner"
|
||||
else
|
||||
source /etc/flippy-openwrt-release
|
||||
case ${PLATFORM} in
|
||||
amlogic | rockchip | allwinner | qemu-aarch64) : ;;
|
||||
*) error_msg "Unknown platform, only support amlogic or rockchip or allwinner h6 or qemu-aarch64!" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_name}" ]] && error_msg "Cannot find the root partition!"
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition message of the root file system
|
||||
get_root_partition_msg() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_msg=$(lsblk -l -o NAME,PATH,MOUNTPOINT,UUID,FSTYPE,LABEL | awk '$3 ~ "^" "'"${path}"'" "$" {print $0}')
|
||||
[[ -n "${partition_msg}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
|
||||
echo "${partition_msg}"
|
||||
}
|
||||
|
||||
backup() {
|
||||
cd /
|
||||
echo -n "Backup config files ... "
|
||||
[ -d "${BACKUP_DIR}" ] || mkdir -p "${BACKUP_DIR}"
|
||||
eval tar czf "${BACKUP_FILE}" "${BACKUP_LIST}" 2>/dev/null
|
||||
sync
|
||||
if [ -f "${BACKUP_FILE}" ]; then
|
||||
echo "Has been backed up to [ ${BACKUP_FILE} ], please download and save."
|
||||
exit 0
|
||||
else
|
||||
error_msg "Backup failed!"
|
||||
fi
|
||||
}
|
||||
|
||||
restore() {
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case ${ROOT_PTNAME} in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
|
||||
PARTITION_NAME="p"
|
||||
LB_PRE="EMMC_"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
|
||||
PARTITION_NAME=""
|
||||
LB_PRE=""
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -d "${BACKUP_DIR}" ] || mkdir -p "${BACKUP_DIR}"
|
||||
[ -f "/tmp/upload/${BACKUP_NAME}" ] && mv -f "/tmp/upload/${BACKUP_NAME}" ${BACKUP_FILE}
|
||||
[ -f "/mnt/${EMMC_NAME}${PARTITION_NAME}4/${BACKUP_NAME}" ] && mv -f "/mnt/${EMMC_NAME}${PARTITION_NAME}4/${BACKUP_NAME}" ${BACKUP_FILE}
|
||||
sync
|
||||
|
||||
if [ -f "${BACKUP_FILE}" ]; then
|
||||
echo -n "restore config files ... "
|
||||
cd /
|
||||
tar xzf "${BACKUP_FILE}" 2>/dev/null && sync
|
||||
|
||||
echo "Successful recovery. Will start automatically, please refresh later!"
|
||||
sleep 3
|
||||
reboot
|
||||
exit 0
|
||||
else
|
||||
error_msg "The backup file [ ${BACKUP_FILE} ] not found!"
|
||||
fi
|
||||
}
|
||||
|
||||
gen_fstab() {
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case ${ROOT_PTNAME} in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
|
||||
PARTITION_NAME=""
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
ROOT_MSG="$(get_root_partition_msg)"
|
||||
ROOT_NAME=$(echo $ROOT_MSG | awk '{print $1}')
|
||||
ROOT_DEV=$(echo $ROOT_MSG | awk '{print $2}')
|
||||
ROOT_UUID=$(echo $ROOT_MSG | awk '{print $4}')
|
||||
ROOT_FSTYPE=$(echo $ROOT_MSG | awk '{print $5}')
|
||||
ROOT_LABEL=$(echo $ROOT_MSG | awk '{print $6}')
|
||||
|
||||
BOOT_NAME="${EMMC_NAME}${PARTITION_NAME}1"
|
||||
BOOT_MSG=$(lsblk -l -o NAME,UUID,FSTYPE,LABEL | grep "${BOOT_NAME}")
|
||||
BOOT_DEV="/dev/${BOOT_NAME}"
|
||||
BOOT_UUID=$(echo $BOOT_MSG | awk '{print $2}')
|
||||
BOOT_FSTYPE=$(echo $BOOT_MSG | awk '{print $3}')
|
||||
BOOT_LABEL=$(echo $BOOT_MSG | awk '{print $4}')
|
||||
|
||||
cat >/etc/config/fstab <<EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '1'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '0'
|
||||
|
||||
config mount
|
||||
option target '/rom'
|
||||
option uuid '${ROOT_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype '${ROOT_FSTYPE}'
|
||||
EOF
|
||||
|
||||
if [ "${ROOT_FSTYPE}" == "btrfs" ]; then
|
||||
echo " option options 'compress=zstd:${ZSTD_LEVEL}'" >>/etc/config/fstab
|
||||
fi
|
||||
|
||||
cat >>/etc/config/fstab <<EOF
|
||||
|
||||
config mount
|
||||
option target '/boot'
|
||||
EOF
|
||||
|
||||
if [ "${BOOT_FSTYPE}" == "vfat" ]; then
|
||||
echo " option label '${BOOT_LABEL}'" >>/etc/config/fstab
|
||||
else
|
||||
echo " option uuid '${BOOT_UUID}'" >>/etc/config/fstab
|
||||
fi
|
||||
|
||||
cat >>/etc/config/fstab <<EOF
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype '${BOOT_FSTYPE}'
|
||||
|
||||
EOF
|
||||
echo "/etc/config/fstab generated."
|
||||
echo "Please reboot before continuing."
|
||||
exit 0
|
||||
}
|
||||
|
||||
print_list() {
|
||||
echo "${BACKUP_LIST}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
list_snapshot() {
|
||||
echo "----------------------------------------------------------------"
|
||||
btrfs subvolume list -rt /
|
||||
echo "----------------------------------------------------------------"
|
||||
read -p "Press [ enter ] to return." q
|
||||
}
|
||||
|
||||
create_snapshot() {
|
||||
default_snap_name="etc-$(date +"%m.%d.%H%M%S")"
|
||||
echo "The default snapshot name is: ${default_snap_name}"
|
||||
echo "If you want to modify the snapshot name, please enter it below. Cannot contain spaces."
|
||||
echo "If you do not want to modify it, just press [ Enter ]. Or press the [ q ] key to go back directly."
|
||||
while :; do
|
||||
read -p "[${default_snap_name}] : " nname
|
||||
if [ "${nname}" == "" ]; then
|
||||
snap_name="${default_snap_name}"
|
||||
break
|
||||
elif echo "${nname}" | grep -E "\s+" >/dev/null; then
|
||||
echo "The name [${nname}] contains spaces, please re-enter!"
|
||||
continue
|
||||
elif [ "${nname}" == "q" ] || [ "${nname}" == "Q" ]; then
|
||||
return
|
||||
else
|
||||
if btrfs subvolume list -rt / | awk '{print $4}' | grep "^\\${SNAPSHOT_PRESTR}${nname}$" >/dev/null; then
|
||||
echo "Name: [ ${nname} ] has been used, please re-enter!"
|
||||
continue
|
||||
else
|
||||
snap_name="${nname}"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
(
|
||||
cd /
|
||||
chattr -ia etc/config/fstab
|
||||
btrfs subvolume snapshot -r /etc "${SNAPSHOT_PRESTR}${snap_name}"
|
||||
if [[ "$?" -eq "0" ]]; then
|
||||
echo "The snapshot is created successfully: ${snap_name}"
|
||||
else
|
||||
echo "Snapshot creation failed!"
|
||||
fi
|
||||
)
|
||||
read -p "Press [ enter ] to return." q
|
||||
}
|
||||
|
||||
restore_snapshot() {
|
||||
echo "Below are the existing etc snapshots, please enter the name of one of them."
|
||||
echo "Tip: [ etc-000 ] This is the factory initial configuration."
|
||||
echo " [ etc-001 ] if it exists, it is the initial configuration after upgrading from the previous version."
|
||||
echo "----------------------------------------------------------------"
|
||||
btrfs subvolume list -rt /
|
||||
echo "----------------------------------------------------------------"
|
||||
read -p "Please enter the name of the snapshot to be restored (only the part after ${SNAPSHOT_PRESTR} needs to be entered): " snap_name
|
||||
if btrfs subvolume list -rt / | grep "${SNAPSHOT_PRESTR}${snap_name}" >/dev/null; then
|
||||
while :; do
|
||||
echo "Once the snapshot is restored, the current [ /etc ] will be overwritten!"
|
||||
read -p "Are you sure you want to restore the snapshot: [$snap_name]? y/n [n] " yn
|
||||
case $yn in
|
||||
y | Y)
|
||||
(
|
||||
cd /
|
||||
chattr -ia etc/config/fstab
|
||||
mv etc etc.backup
|
||||
btrfs subvolume snapshot "${SNAPSHOT_PRESTR}${snap_name}" etc
|
||||
if [[ "$?" -eq "0" ]]; then
|
||||
btrfs subvolume delete -c etc.backup
|
||||
echo "Successfully restored, please enter [ reboot ] to restart the openwrt."
|
||||
else
|
||||
rm -rf etc
|
||||
mv etc.backup etc
|
||||
echo "Recovery failed, [ etc ] has not changed!"
|
||||
fi
|
||||
)
|
||||
read -p "Press [ enter ] to return." q
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
read -p "The snapshot name is incorrect, please run the program again! Press [ Enter ] to go back." q
|
||||
fi
|
||||
}
|
||||
|
||||
delete_snapshot() {
|
||||
echo "Below are the existing [ etc ] snapshots, please enter the name of one of them."
|
||||
echo "Tip: [ etc-000 ] This is the factory initial configuration (cannot be deleted)"
|
||||
echo " [ etc-001 ] if it exists, it is the initial configuration after upgrading from the previous version (cannot be deleted)"
|
||||
echo "----------------------------------------------------------------"
|
||||
btrfs subvolume list -rt /
|
||||
echo "----------------------------------------------------------------"
|
||||
read -p "Please enter the name of the snapshot to be deleted (only the part after ${SNAPSHOT_PRESTR} needs to be entered): " snap_name
|
||||
if [ "${snap_name}" == "etc-000" ] || [ "${snap_name}" == "etc-001" ]; then
|
||||
read -p "The key snapshot cannot be deleted! Press [ enter ] to return." q
|
||||
elif [ "${snap_name}" == "" ]; then
|
||||
read -p "Name is empty! Press [ enter ] to return." q
|
||||
else
|
||||
if btrfs subvolume list -rt / | grep "${SNAPSHOT_PRESTR}${snap_name}" >/dev/null; then
|
||||
read -p "Are you sure you want to delete ${snap_name}? y/n [n] " yn
|
||||
case $yn in
|
||||
y | Y)
|
||||
(
|
||||
cd /
|
||||
btrfs subvolume delete -c "${SNAPSHOT_PRESTR}${snap_name}"
|
||||
if [[ "$?" -eq "0" ]]; then
|
||||
echo "Snapshot [ ${snap_name} ] has been deleted."
|
||||
else
|
||||
echo "Snapshot [ ${snap_name} ] failed to delete!"
|
||||
fi
|
||||
)
|
||||
read -p "Press [ Enter ] to return." q
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
else
|
||||
read -p "The name of the snapshot is incorrect, press [ Enter ] to return." q
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
migrate_snapshot() {
|
||||
cur_rootdev="$(get_root_partition_name)"
|
||||
|
||||
dev_pre=$(echo "${cur_rootdev}" | awk '{print substr($1, 1, length($1)-1);}')
|
||||
rootdev_idx=$(echo "${cur_rootdev}" | awk '{print substr($1, length($1),1);}')
|
||||
case $rootdev_idx in
|
||||
2)
|
||||
old_rootpath="/mnt/${dev_pre}3"
|
||||
;;
|
||||
3)
|
||||
old_rootpath="/mnt/${dev_pre}2"
|
||||
;;
|
||||
*)
|
||||
echo "Judge the old version of rootfs path failed!"
|
||||
read -p "Press [ enter ] to return." q
|
||||
return
|
||||
;;
|
||||
esac
|
||||
echo "The following are snapshots of etc found from the old version of rootfs, please enter the name of one of them."
|
||||
echo "Tip: Automatically exclude etc-000 and etc-001"
|
||||
echo "-----------------------------------------------------------------------------------"
|
||||
btrfs subvolume list -rt "${old_rootpath}" | grep -v "${SNAPSHOT_PRESTR}etc-000" | grep -v "${SNAPSHOT_PRESTR}etc-001"
|
||||
echo "-----------------------------------------------------------------------------------"
|
||||
read -p "Please enter the name of the snapshot to be migrated (only the part after $(SNAPSHOT_PRESTR) needs to be entered): " old_snap_name
|
||||
if [ "${old_snap_name}" == "" ]; then
|
||||
read -p "The name is empty, Press [ enter ] to return." q
|
||||
return
|
||||
elif ! btrfs subvolume list -rt "${old_rootpath}" | awk '{print $4}' | grep "^${SNAPSHOT_PRESTR}${old_snap_name}$" >/dev/null; then
|
||||
echo "The name was entered incorrectly, and the corresponding snapshot was not found!"
|
||||
read -p "Press [ enter ] to return." q
|
||||
return
|
||||
elif [ "${old_snap_name}" == "etc-000" ] || [ "${old_snap_name}" == "etc-001" ]; then
|
||||
echo "Critical snapshots are not allowed to migrate!"
|
||||
read -p "Press [ enter ] to return." q
|
||||
return
|
||||
fi
|
||||
|
||||
# Find out if there is a snapshot with the same name under the current rootfs
|
||||
if btrfs subvolume list -rt / | awk '{print $4}' | grep "^\\${SNAPSHOT_PRESTR}${old_snap_name}$" >/dev/null; then
|
||||
echo "A snapshot with the name [ ${old_snap_name} ] already exists and cannot be migrated! (But you can delete the existing snapshot with the same name and then migrate)"
|
||||
read -p "Press [ enter ] to return." q
|
||||
return
|
||||
fi
|
||||
|
||||
need_size=$(du -h -d0 ${old_rootpath}/${SNAPSHOT_PRESTR}${old_snap_name} | tail -n1 | awk '{print $1}')
|
||||
echo "----------------------------------------------------------------------------------------------"
|
||||
df -h
|
||||
echo "----------------------------------------------------------------------------------------------"
|
||||
echo -e "Note: To migrate the snapshot [ ${old_snap_name} ] of [ ${old_rootpath} ] to the current rootfs, it takes about [ ${need_size} ] space,"
|
||||
echo -e " Please confirm whether the partition [/dev/${cur_rootdev}] where [/] is located has enough free space (Available)?"
|
||||
read -p "Are you sure to migrate? y/n [n] " yn
|
||||
if [ "$yn" == "y" ] || [ "$yn" == "Y" ]; then
|
||||
(
|
||||
cd /
|
||||
btrfs send ${old_rootpath}/${SNAPSHOT_PRESTR}${old_snap_name} | btrfs receive ${SNAPSHOT_PRESTR}
|
||||
if [ $? -eq 0 ]; then
|
||||
btrfs property set -ts ${SNAPSHOT_PRESTR}${old_snap_name} ro false
|
||||
cp ${SNAPSHOT_PRESTR}etc-000/config/fstab ${SNAPSHOT_PRESTR}${old_snap_name}/config/
|
||||
cp ${SNAPSHOT_PRESTR}etc-000/fstab ${SNAPSHOT_PRESTR}${old_snap_name}/
|
||||
cp ${SNAPSHOT_PRESTR}etc-000/openwrt_release ${SNAPSHOT_PRESTR}${old_snap_name}/
|
||||
cp ${SNAPSHOT_PRESTR}etc-000/openwrt_version ${SNAPSHOT_PRESTR}${old_snap_name}/
|
||||
cp ${SNAPSHOT_PRESTR}etc-000/flippy-openwrt-release ${SNAPSHOT_PRESTR}${old_snap_name}/
|
||||
cp ${SNAPSHOT_PRESTR}etc-000/banner ${SNAPSHOT_PRESTR}${old_snap_name}/banner
|
||||
btrfs property set -ts ${SNAPSHOT_PRESTR}${old_snap_name} ro true
|
||||
echo "The migration is complete, if you want to apply the snapshot [ ${old_snap_name} ], please use the restore snapshot function."
|
||||
else
|
||||
echo "The migration failed!"
|
||||
fi
|
||||
read -p "Press [ enter ] to return." q
|
||||
return
|
||||
)
|
||||
fi
|
||||
}
|
||||
|
||||
snapshot_help() {
|
||||
clear
|
||||
cat <<EOF
|
||||
============================================================================================================================
|
||||
1. What is a snapshot?
|
||||
A snapshot is the state record of a certain subvolume at a certain point in time, and a snapshot is a special subvolume;
|
||||
When the local snapshot is first generated, it shares the disk space with the original subvolume,
|
||||
so it does not occupy additional space, and only the files that have changed subsequently occupy space;
|
||||
Snapshots migrated from other places are not snapshots in essence, but just ordinary subvolumes, so they take up space.
|
||||
2. How to display existing snapshots?
|
||||
input the command: btrfs subvolume list -rt /
|
||||
---------------------------------------------------------------------------------------------
|
||||
EOF
|
||||
btrfs subvolume list -rt /
|
||||
cat <<EOF
|
||||
---------------------------------------------------------------------------------------------
|
||||
2. How to create a snapshot?
|
||||
btrfs subvolume snapshot -r /etc /.snapshots/snapshot_1 # -r It means to generate a read-only snapshot
|
||||
3. How to delete a snapshot?
|
||||
btrfs subvolume delete -c /.snapshots/snapshot_1 # -c 是 commit 的意思
|
||||
4. How to rename a snapshot?
|
||||
Just use the [ mv ] command of the operating system, for example:
|
||||
mv /.snapshots/snapshot_1 /.snapshots/snapshot_2
|
||||
5. How to restore the snapshot?
|
||||
mv /etc /etc.backup # Back up /etc to /etc.backup, that is, rename the subvolume
|
||||
btrfs subvolume snapshot /.snapshots/etc-001 /etc # Use snapshot etc-001 to generate snapshot etc, no -r parameter
|
||||
# (Yes, snapshots can also be re-generated snapshots)
|
||||
btrfs delete -c /etc.backup # After the previous step is successful, you can delete the etc backup just now
|
||||
6. How to restore a certain file from the snapshot?
|
||||
Example A: Restore the mount point configuration file from snapshot etc-000: /etc/config/fstab
|
||||
cp /.snapshots/etc-000/config/fstab /etc/config/
|
||||
Example B: Restore network configuration from snapshot etc-001:
|
||||
cp /.snapshots/etc-001/config/network /etc/config/
|
||||
Example C: Restore the ssr configuration file from snapshot etc-001:
|
||||
cp /.snapshots/etc-001/config/shadowsocksr /etc/config/
|
||||
# (Yes, it is the [ cp ] command of the operating system)
|
||||
7. How to migrate snapshots from remote?
|
||||
btrfs supports ssh remote migration snapshots, for example:
|
||||
ssh 192.168.1.1 btrfs send /.snapshots/snapshot_x | btrfs receive /.snapshots
|
||||
After the command is completed, the remote snapshot_x is copied to the local /.snapshots/snapshot_x
|
||||
(as mentioned above, the migration is a subvolume, which takes up space)
|
||||
============================================================================================================================
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
print_help() {
|
||||
echo "Usage: $0 -b [ backup ]"
|
||||
echo " $0 -r [ restore ]"
|
||||
echo " $0 -g [ generate fstab ]"
|
||||
echo " $0 -p [ print backup list ]"
|
||||
echo " $0 -l [ list snapshots ]"
|
||||
echo " $0 -c [ create snapshot ]"
|
||||
echo " $0 -s [ restore snapshot ]"
|
||||
echo " $0 -d [ delete snapshot ]"
|
||||
echo " $0 -h [ help ]"
|
||||
echo " $0 -q [ quit ]"
|
||||
exit 0
|
||||
}
|
||||
|
||||
menu() {
|
||||
while :; do
|
||||
clear
|
||||
cat <<EOF
|
||||
|
||||
┌────────[ backup config ]────────┐
|
||||
│ │
|
||||
│ b. backup config │
|
||||
│ r. restore config │
|
||||
│ g. generate fstab │
|
||||
│ p. print backup list │
|
||||
│ │
|
||||
├─────[ Snapshot management ]─────┤
|
||||
│ │
|
||||
│ l. list snapshots │
|
||||
│ c. create snapshot │
|
||||
│ d. delete snapshot │
|
||||
│ R. restore snapshot │
|
||||
│ m. migrate snapshot │
|
||||
│ s. snapshot help │
|
||||
│ │
|
||||
╞═════════════════════════════════╡
|
||||
│ │
|
||||
│ h. help │
|
||||
│ q. quit │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
|
||||
EOF
|
||||
echo -ne "please select: [ ]\b\b"
|
||||
read select
|
||||
case $select in
|
||||
b | backup) backup ;;
|
||||
r | restore)
|
||||
restore
|
||||
gen_fstab
|
||||
;;
|
||||
g | gen_fstab) gen_fstab ;;
|
||||
p | print_list) print_list ;;
|
||||
l | list_snapshot) list_snapshot ;;
|
||||
c | create_snapshot) create_snapshot ;;
|
||||
d | delete_snapshot) delete_snapshot ;;
|
||||
R | restore_snapshot) restore_snapshot ;;
|
||||
m | migrate_snapshot) migrate_snapshot ;;
|
||||
s | snapshot_help) snapshot_help ;;
|
||||
h | help) print_help ;;
|
||||
q | quit) exit 0 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
getopts 'brgplcRmsdhq' opts
|
||||
case $opts in
|
||||
b | backup) backup ;;
|
||||
r | restore)
|
||||
restore
|
||||
gen_fstab
|
||||
;;
|
||||
g | gen_fstab) gen_fstab ;;
|
||||
p | print_list) print_list ;;
|
||||
l | list_snapshot) list_snapshot ;;
|
||||
c | create_snapshot) create_snapshot ;;
|
||||
d | delete_snapshot) delete_snapshot ;;
|
||||
R | restore_snapshot) restore_snapshot ;;
|
||||
m | migrate_snapshot) migrate_snapshot ;;
|
||||
s | snapshot_help) snapshot_help ;;
|
||||
h | help) print_help ;;
|
||||
q | quit) exit 0 ;;
|
||||
*) menu ;;
|
||||
esac
|
||||
@@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
#===========================================================================
|
||||
#
|
||||
# This file is licensed under the terms of the GNU General Public
|
||||
# License version 2. This program is licensed "as is" without any
|
||||
# warranty of any kind, whether express or implied.
|
||||
#
|
||||
# This file is a part of the make OpenWrt for Amlogic s9xxx tv box
|
||||
# https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Description: Backup and restore the system in emmc
|
||||
# Copyright (C) 2017- The function borrowed from armbian/ddbr, Author: xXx
|
||||
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Command: openwrt-ddbr
|
||||
#
|
||||
#========================= Set default parameters ===========================
|
||||
#
|
||||
# Set font color
|
||||
blue_font_prefix="\033[34m"
|
||||
purple_font_prefix="\033[35m"
|
||||
green_font_prefix="\033[32m"
|
||||
yellow_font_prefix="\033[33m"
|
||||
red_font_prefix="\033[31m"
|
||||
font_color_suffix="\033[0m"
|
||||
INFO="[${blue_font_prefix}INFO${font_color_suffix}]"
|
||||
STEPS="[${purple_font_prefix}STEPS${font_color_suffix}]"
|
||||
SUCCESS="[${green_font_prefix}SUCCESS${font_color_suffix}]"
|
||||
OPT="[${yellow_font_prefix}OPT${font_color_suffix}]"
|
||||
ERROR="[${red_font_prefix}ERROR${font_color_suffix}]"
|
||||
#
|
||||
# Check the output path
|
||||
out_path="/ddbr"
|
||||
# File name for backup/restore
|
||||
ddbr_image="BACKUP-arm-64-emmc.img.gz"
|
||||
# Need remaining space, unit: GB
|
||||
need_space="2"
|
||||
#
|
||||
#===========================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "${ERROR} ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_name}" ]] && error_msg "Cannot find the root partition!"
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Check emmc
|
||||
do_checkemmc() {
|
||||
# Get device name
|
||||
mydevice_name="$(cat /proc/device-tree/model | tr -d '\000')"
|
||||
echo -e "${INFO} The device name: [ ${mydevice_name} ]"
|
||||
|
||||
# Find the partition where root is located
|
||||
root_ptname="$(get_root_partition_name)"
|
||||
|
||||
# Find the EMMC drive
|
||||
emmc="$(lsblk -l -o NAME | grep -oE "mmcblk[0-9]boot0" | sort | uniq | sed "s/boot0//g")"
|
||||
# Find emmc disk, find emmc that does not contain the boot0 partition
|
||||
[[ -z "${emmc}" ]] && emmc="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?)' | grep -vE ^${root_ptname:0:-2} | uniq)"
|
||||
# Check if emmc exists
|
||||
[[ -z "${emmc}" ]] && error_msg "The eMMC storage not found in this device!"
|
||||
# Show the emmc name
|
||||
echo -e "${INFO} The device eMMC name: [ /dev/${emmc} ]"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case "${root_ptname}" in
|
||||
mmcblk?p[1-4])
|
||||
disk_name="$(echo ${root_ptname} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
if lsblk -l -o NAME | grep "${disk_name}boot0" >/dev/null; then
|
||||
error_msg "The current system is running on emmc. Please perform backup/restore operation in [ SD/TF/USB ]!"
|
||||
fi
|
||||
link_ptname="p"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
disk_name="$(echo ${root_ptname} | awk '{print substr($1, 1, length($1)-1)}')"
|
||||
link_ptname=""
|
||||
;;
|
||||
nvme?n?p[1-4])
|
||||
disk_name="$(echo ${root_ptname} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
link_ptname="p"
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${root_ptname}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Set check parameters
|
||||
out_path="/mnt/${disk_name}${link_ptname}4"
|
||||
dev_intsize="$(fdisk -s /dev/${emmc})"
|
||||
[[ -z "$(echo "${dev_intsize}" | sed -n "/^[0-9]\+$/p")" ]] && error_msg "Unable to get EMMC size."
|
||||
echo -e "${INFO} The device EMMC size: [ $(($dev_intsize / 1024 / 1024))GB ]"
|
||||
|
||||
# check directory
|
||||
[[ -d "${out_path}" ]] || mkdir -p ${out_path}
|
||||
echo -e "${INFO} The ddbr file path: [ ${out_path}/${ddbr_image} ]\n"
|
||||
}
|
||||
|
||||
# Check the remaining space
|
||||
do_checkspace() {
|
||||
remaining_space="$(df -Tk ${out_path} | grep '/dev/' | awk '{print $5}' | echo $(($(xargs) / 1024 / 1024)))"
|
||||
if [[ -z "$(echo "${remaining_space}" | sed -n "/^[0-9]\+$/p")" ]]; then
|
||||
error_msg "The path is not available, the remaining space cannot be obtained."
|
||||
fi
|
||||
if [[ "${remaining_space}" -lt "${need_space}" ]]; then
|
||||
error_msg "The remaining space is [ ${remaining_space} ] Gb, and more than [ ${need_space} ] Gb space is required."
|
||||
fi
|
||||
}
|
||||
|
||||
# Backup the emmc system
|
||||
do_backup() {
|
||||
echo -e "${STEPS} Start to backup the system in emmc."
|
||||
do_checkspace
|
||||
echo -e "Saving and Compressing [ /dev/${emmc} ] to [ ${out_path}/${ddbr_image} ], Please wait..."
|
||||
rm -f ${out_path}/${ddbr_image} 2>/dev/null && sync
|
||||
dd if=/dev/${emmc} | pv -s ${dev_intsize}"K" | gzip >${out_path}/${ddbr_image}
|
||||
[[ "${?}" -eq "0" ]] && sync && echo -e "${SUCCESS} Backup is complete."
|
||||
}
|
||||
|
||||
# Restore the emmc system
|
||||
do_restore() {
|
||||
echo -e "${STEPS} Start to restore the system in emmc."
|
||||
[[ ! -f ${out_path}/${ddbr_image} ]] && error_msg "The [ ${out_path}/${ddbr_image} ] File not found."
|
||||
echo -e "Restoring [ ${out_path}/${ddbr_image} ] to [ /dev/${emmc} ], Please wait..."
|
||||
gunzip -c ${out_path}/${ddbr_image} | pv -s ${dev_intsize}"K" | dd of=/dev/${emmc}
|
||||
[[ "${?}" -eq "0" ]] && sync && echo -e "${SUCCESS} Restore is complete."
|
||||
}
|
||||
|
||||
echo -e "${STEPS} Welcome to use the EMMC system backup/restore service."
|
||||
# Check script permission
|
||||
[[ -x "/usr/sbin/openwrt-ddbr" ]] || error_msg "Please grant execution permission: [ chmod +x /usr/sbin/openwrt-ddbr ]"
|
||||
# Check emmc
|
||||
do_checkemmc
|
||||
# Prompt the user to select backup/restore
|
||||
echo -ne "${OPT} Do you want to backup or restore? Backup=(b) Restore=(r): "
|
||||
read br
|
||||
case "${br}" in
|
||||
b | B | backup) do_backup ;;
|
||||
r | R | restore) do_restore ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
@@ -0,0 +1,721 @@
|
||||
#!/bin/bash
|
||||
#======================================================================================
|
||||
# Function: Install openwrt to emmc for Amlogic S9xxx STB
|
||||
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
|
||||
#======================================================================================
|
||||
#
|
||||
# The script supports directly setting parameters for installation, skipping interactive selection
|
||||
# openwrt-install-amlogic ${AUTO_MAINLINE_UBOOT} ${ID} ${FDTFILE}:${SOC}:${UBOOT_OVERLOAD} ${SHARED_FSTYPE}
|
||||
# E.g: openwrt-install-amlogic yes 11 auto ext4
|
||||
# E.g: openwrt-install-amlogic no 99 meson-gxl-s905d-phicomm-n1.dtb:s905d:u-boot-n1.bin ext4
|
||||
# Tip: When custom dtb file, set ${SOC_ID} to 99, and parameter ${FDTFILE}:${SOC}:${UBOOT_OVERLOAD} must be set
|
||||
# Tip: ${SHARED_FSTYPE}: Shared partition can be ext4, xfs, btrfs, f2fs
|
||||
|
||||
# You can also execute the script directly, and interactively select related functions
|
||||
# E.g: openwrt-install-amlogic
|
||||
#
|
||||
#======================================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "[ERROR] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_name}" ]] && error_msg "Cannot find the root partition!"
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Receive one-key command related parameters
|
||||
AUTO_MAINLINE_UBOOT="${1}"
|
||||
ZSTD_LEVEL="6"
|
||||
op_release="/etc/flippy-openwrt-release"
|
||||
|
||||
# For [luci-app-amlogic] input parameter: DTB, SOC & UBOOT_OVERLOAD
|
||||
# When there is no input parameter, select manually
|
||||
SPECIFY_ID=""
|
||||
SPECIFY_SOC=""
|
||||
SPECIFY_DTB=""
|
||||
SPECIFY_UBOOT=""
|
||||
[[ -n "${2}" ]] && {
|
||||
SPECIFY_ID="${2}"
|
||||
if [[ "${2}" -eq "99" ]]; then
|
||||
if [[ -n "${3}" ]]; then
|
||||
# E.g: meson-gxl-s905d-phicomm-n1.dtb:s905d:u-boot-n1.bin
|
||||
SPECIFY_DTB="$(echo "${3}" | awk -F ':' '{print $1}')"
|
||||
SPECIFY_SOC="$(echo "${3}" | awk -F ':' '{print $2}')"
|
||||
SPECIFY_UBOOT="$(echo "${3}" | awk -F ':' '{print $3}')"
|
||||
else
|
||||
error_msg "Please enter the DTB file name!"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# shared partition can be ext4, xfs, btrfs, f2fs
|
||||
SHARED_FSTYPE="${4}"
|
||||
|
||||
echo "AUTO_MAINLINE_UBOOT: ${AUTO_MAINLINE_UBOOT}"
|
||||
echo "SPECIFY_DTB: ${SPECIFY_DTB}"
|
||||
echo "SPECIFY_SOC: ${SPECIFY_SOC}"
|
||||
echo "SPECIFY_UBOOT: ${SPECIFY_UBOOT}"
|
||||
echo "SHARED_FSTYPE: ${SHARED_FSTYPE}"
|
||||
|
||||
# Current device model
|
||||
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
|
||||
if [[ -z "${MYDEVICE_NAME}" ]]; then
|
||||
error_msg "The device name is empty and cannot be recognized."
|
||||
elif [[ ! -f "${op_release}" ]]; then
|
||||
error_msg "The [ ${op_release} ] file is missing."
|
||||
else
|
||||
echo -e "Current device: ${MYDEVICE_NAME} [ amlogic ]"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# Find the device name of /
|
||||
root_devname="$(get_root_partition_name)"
|
||||
if lsblk -l | grep -E "^${root_devname}boot0" >/dev/null; then
|
||||
error_msg "you are running in emmc mode, please boot system with usb or tf card!"
|
||||
fi
|
||||
|
||||
install_emmc="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?boot0)' | sed "s/boot0//g")"
|
||||
if [[ "${install_emmc}" == "" ]]; then
|
||||
error_msg "No emmc can be found to install the openwrt system!"
|
||||
fi
|
||||
|
||||
# EMMC DEVICE NAME
|
||||
EMMC_NAME="${install_emmc}"
|
||||
EMMC_DEVPATH="/dev/${EMMC_NAME}"
|
||||
echo ${EMMC_DEVPATH}
|
||||
EMMC_SIZE=$(lsblk -l -b -o NAME,SIZE | grep ${EMMC_NAME} | sort | uniq | head -n1 | awk '{print $2}')
|
||||
echo "${EMMC_NAME} : ${EMMC_SIZE} bytes"
|
||||
|
||||
ROOT_NAME=$(lsblk -l -o NAME,MAJ:MIN,MOUNTPOINT | grep -e '/$' | awk '{print $1}')
|
||||
echo "ROOTFS: ${ROOT_NAME}"
|
||||
|
||||
BOOT_NAME=$(lsblk -l -o NAME,MAJ:MIN,MOUNTPOINT | grep -e '/boot$' | awk '{print $1}')
|
||||
echo "BOOT: ${BOOT_NAME}"
|
||||
|
||||
# box model database
|
||||
# The field separator is :
|
||||
# " " or "" or NA or NULL means this field is null
|
||||
# The fields list:
|
||||
# 1. id
|
||||
# 2. model name
|
||||
# 3. SOC
|
||||
# 4. FDTFILE
|
||||
# 5. UBOOT_OVERLOAD
|
||||
# 6. MAINLINE_UBOOT
|
||||
# 7. ANDROID_UBOOT
|
||||
# 8. brief description
|
||||
#
|
||||
|
||||
# allow use external modal database
|
||||
if [[ -f "/etc/model_database.txt" ]]; then
|
||||
model_database="$(cat /etc/model_database.txt)"
|
||||
else
|
||||
error_msg "[ /etc/model_database.txt ] file is missing."
|
||||
fi
|
||||
|
||||
function display_database() {
|
||||
while read -r line; do
|
||||
if [[ "$line" =~ ^# ]]; then
|
||||
# Process comment lines, starting with #
|
||||
line="${line/#+\s+/}"
|
||||
echo "$line >>>"
|
||||
else
|
||||
# Process data lines, starting with id
|
||||
IFS=':' read -r -a fields <<<"$line"
|
||||
printf "%5s %-48s%-10s%-s\n" "${fields[0]}" "${fields[1]}" "${fields[2]}" "${fields[7]}"
|
||||
fi
|
||||
done < <(echo "${model_database}")
|
||||
}
|
||||
|
||||
function search_model() {
|
||||
local id="${1}"
|
||||
local ret_count="$(echo "${model_database}" | awk -F ':' "\$1~/^$id\$/ {print \$0}" | wc -l)"
|
||||
if [[ "${ret_count}" -eq "1" ]]; then
|
||||
echo "${model_database}" | awk -F ':' "\$1~/^$id\$/ {print \$0}" | sed -e 's/NA//g' -e 's/NULL//g' -e 's/[ ][ ]*//g'
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Please select s9xxx box model:"
|
||||
echo "----------------------------------------------------------------------------------------------------"
|
||||
display_database
|
||||
echo "----------------------------------------------------------------------------------------------------"
|
||||
|
||||
# For [luci-app-amlogic] input parameter: SOC & DTB
|
||||
# When there is no input parameter, select manually
|
||||
if [[ -n "${SPECIFY_ID}" ]]; then
|
||||
boxtype="${SPECIFY_ID}"
|
||||
else
|
||||
echo -n "Please choose: "
|
||||
read boxtype
|
||||
fi
|
||||
|
||||
if [[ "${boxtype}" -eq "99" ]]; then
|
||||
FDTFILE="${SPECIFY_DTB}"
|
||||
AMLOGIC_SOC="${SPECIFY_SOC}"
|
||||
UBOOT_OVERLOAD="${SPECIFY_UBOOT}"
|
||||
MAINLINE_UBOOT=""
|
||||
ANDROID_UBOOT=""
|
||||
elif [[ "${boxtype}" -eq "0" ]]; then
|
||||
read -p "Please Input SoC Name(such as s9xxx): " AMLOGIC_SOC
|
||||
AMLOGIC_SOC="${AMLOGIC_SOC}"
|
||||
|
||||
read -p "Please Input DTB Name(such as meson-xxx.dtb): " FDTFILE
|
||||
FDTFILE="${FDTFILE}"
|
||||
|
||||
read -p "Please Input UBOOT_OVERLOAD Name(such as u-boot-xxx.bin): " UBOOT_OVERLOAD
|
||||
UBOOT_OVERLOAD="${UBOOT_OVERLOAD}"
|
||||
|
||||
read -p "Please Input MAINLINE_UBOOT Name(such as /lib/u-boot/xxx-u-boot.bin.sd.bin): " MAINLINE_UBOOT
|
||||
MAINLINE_UBOOT="${MAINLINE_UBOOT}"
|
||||
|
||||
read -p "Please Input ANDROID_UBOOT Name(such as /lib/u-boot/xxx-bootloader.img): " ANDROID_UBOOT
|
||||
ANDROID_UBOOT="${ANDROID_UBOOT}"
|
||||
else
|
||||
ret="$(search_model ${boxtype})"
|
||||
if [[ -z "${ret}" ]]; then
|
||||
error_msg "Input error, exit!"
|
||||
fi
|
||||
# 3. soc
|
||||
# 4. FDTFILE
|
||||
# 5. UBOOT_OVERLOAD
|
||||
# 6. MAINLINE_UBOOT
|
||||
# 7. ANDROID_UBOOT
|
||||
AMLOGIC_SOC="$(echo "${ret}" | awk -F ':' '{print $3}')"
|
||||
FDTFILE="$(echo "${ret}" | awk -F ':' '{print $4}')"
|
||||
UBOOT_OVERLOAD="$(echo "${ret}" | awk -F ':' '{print $5}')"
|
||||
MAINLINE_UBOOT="$(echo "${ret}" | awk -F ':' '{print $6}')"
|
||||
ANDROID_UBOOT="$(echo "${ret}" | awk -F ':' '{print $7}')"
|
||||
fi
|
||||
|
||||
if [[ -z "${FDTFILE}" || ! -f "/boot/dtb/amlogic/${FDTFILE}" ]]; then
|
||||
error_msg "/boot/dtb/amlogic/${FDTFILE} does not exist!"
|
||||
fi
|
||||
|
||||
echo "AMLOGIC_SOC Value [ ${AMLOGIC_SOC} ]"
|
||||
echo "FDTFILE Value [ ${FDTFILE} ]"
|
||||
echo "UBOOT_OVERLOAD Value [ ${UBOOT_OVERLOAD} ]"
|
||||
echo "MAINLINE_UBOOT Value [ ${MAINLINE_UBOOT} ]"
|
||||
echo "ANDROID_UBOOT Value [ ${ANDROID_UBOOT} ]"
|
||||
|
||||
sed -i "s|^SOC=.*|SOC='${AMLOGIC_SOC}'|g" ${op_release} 2>/dev/null
|
||||
sed -i "s|^FDTFILE=.*|FDTFILE='${FDTFILE}'|g" ${op_release} 2>/dev/null
|
||||
sed -i "s|^UBOOT_OVERLOAD=.*|UBOOT_OVERLOAD='${UBOOT_OVERLOAD}'|g" ${op_release} 2>/dev/null
|
||||
sed -i "s|^MAINLINE_UBOOT=.*|MAINLINE_UBOOT='${MAINLINE_UBOOT}'|g" ${op_release} 2>/dev/null
|
||||
sed -i "s|^ANDROID_UBOOT=.*|ANDROID_UBOOT='${ANDROID_UBOOT}'|g" ${op_release} 2>/dev/null
|
||||
|
||||
K510="1"
|
||||
[[ "$(hexdump -n 15 -x "/boot/zImage" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
|
||||
echo -e "K510 [ ${K510} ]"
|
||||
|
||||
# backup old bootloader
|
||||
if [[ ! -f "/root/BackupOldBootloader.img" ]]; then
|
||||
echo "Backup bootloader -> [ BackupOldBootloader.img ] ... "
|
||||
dd if=/dev/$EMMC_NAME of=/root/BackupOldBootloader.img bs=1M count=4 conv=fsync
|
||||
echo "Backup bootloader complete."
|
||||
echo
|
||||
fi
|
||||
|
||||
swapoff -a
|
||||
|
||||
# umount all other mount points
|
||||
MOUNTS=$(lsblk -l -o MOUNTPOINT)
|
||||
for mnt in $MOUNTS; do
|
||||
if [ "$mnt" == "MOUNTPOINT" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mnt" == "" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mnt" == "/" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mnt" == "/boot" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mnt" == "/opt" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mnt" == "[SWAP]" ]; then
|
||||
echo "swapoff -a"
|
||||
swapoff -a
|
||||
continue
|
||||
fi
|
||||
|
||||
if echo $mnt | grep $EMMC_NAME; then
|
||||
echo "umount -f $mnt"
|
||||
umount -f $mnt
|
||||
if [ $? -ne 0 ]; then
|
||||
error_msg "$mnt Cannot be uninstalled, the installation process is aborted."
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Delete old partition if exists
|
||||
p=$(lsblk -l | grep -e "${EMMC_NAME}p" | wc -l)
|
||||
echo "A total of [ $p ] old partitions on EMMC will be deleted"
|
||||
>/tmp/fdisk.script
|
||||
while [ $p -ge 1 ]; do
|
||||
echo "d" >>/tmp/fdisk.script
|
||||
if [ $p -gt 1 ]; then
|
||||
echo "$p" >>/tmp/fdisk.script
|
||||
fi
|
||||
p=$((p - 1))
|
||||
done
|
||||
|
||||
# you can change ROOT size(MB) >= 320
|
||||
ROOT1="2048"
|
||||
ROOT2="2048"
|
||||
if [[ "${AMLOGIC_SOC}" == "s912" ]] && [[ "${boxtype}" == "213" || "${boxtype}" == "2e" ]]; then
|
||||
BOOT="512"
|
||||
BLANK1="700"
|
||||
BLANK2="220"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${AMLOGIC_SOC}" == "s912" || "${AMLOGIC_SOC}" == "s905d" ]]; then
|
||||
BOOT="512"
|
||||
BLANK1="68"
|
||||
BLANK2="220"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${AMLOGIC_SOC}" == "s905x" ]]; then
|
||||
BOOT="160"
|
||||
BLANK1="700"
|
||||
BLANK2="0"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${FDTFILE}" == "meson-sm1-skyworth-lb2004-a4091.dtb" ]]; then
|
||||
BOOT="512"
|
||||
BLANK1="108"
|
||||
BLANK2="562"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${AMLOGIC_SOC}" == "s905l3a" ]] && [[ "${boxtype}" == "304" || "${boxtype}" == "34" ]]; then
|
||||
# e900v22c/d(s905l3a)
|
||||
BOOT="256"
|
||||
BLANK1="570"
|
||||
BLANK2="0"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${AMLOGIC_SOC}" == "s905l3a" ]] && [[ "${boxtype}" == "305" || "${boxtype}" == "33" ]]; then
|
||||
# CM311-1a-YST(s905l3a)
|
||||
BOOT="512"
|
||||
BLANK1="108"
|
||||
BLANK2="778"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${AMLOGIC_SOC}" == "s905l3b" ]]; then
|
||||
# M302A/M304A(s905l3b)
|
||||
BOOT="512"
|
||||
BLANK1="128"
|
||||
BLANK2="720"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${AMLOGIC_SOC}" == "s905x3" ]] && [[ "${boxtype}" == "525" || "${boxtype}" == "5n" ]]; then
|
||||
# Whale(s905x3)
|
||||
BOOT="512"
|
||||
BLANK1="108"
|
||||
BLANK2="650"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
elif [[ "${boxtype}" =~ ^(409|410|49|4a)$ ]]; then
|
||||
# WXY-OES(A311D):409/49, WXY-OES-PLUS(S922X):410/4a
|
||||
BOOT="512"
|
||||
BLANK1="700"
|
||||
BLANK2="0"
|
||||
BLANK3="0"
|
||||
BLANK4="0"
|
||||
else
|
||||
BOOT="160"
|
||||
BLANK1="68"
|
||||
BLANK2="0"
|
||||
BLANK3="162"
|
||||
BLANK4="0"
|
||||
fi
|
||||
|
||||
DST_TOTAL_MB=$((EMMC_SIZE / 1024 / 1024))
|
||||
|
||||
start1=$((BLANK1 * 2048))
|
||||
end1=$((start1 + (BOOT * 2048) - 1))
|
||||
|
||||
start2=$(((BLANK2 * 2048) + end1 + 1))
|
||||
end2=$((start2 + (ROOT1 * 2048) - 1))
|
||||
|
||||
start3=$(((BLANK3 * 2048) + end2 + 1))
|
||||
end3=$((start3 + (ROOT2 * 2048) - 1))
|
||||
|
||||
start4=$(((BLANK4 * 2048) + end3 + 1))
|
||||
end4=$((DST_TOTAL_MB * 2048 - 1))
|
||||
|
||||
cat >>/tmp/fdisk.script <<EOF
|
||||
n
|
||||
p
|
||||
1
|
||||
$start1
|
||||
$end1
|
||||
n
|
||||
p
|
||||
2
|
||||
$start2
|
||||
$end2
|
||||
n
|
||||
p
|
||||
3
|
||||
$start3
|
||||
$end3
|
||||
n
|
||||
p
|
||||
$start4
|
||||
$end4
|
||||
t
|
||||
1
|
||||
c
|
||||
t
|
||||
2
|
||||
83
|
||||
t
|
||||
3
|
||||
83
|
||||
t
|
||||
4
|
||||
83
|
||||
w
|
||||
EOF
|
||||
|
||||
fdisk /dev/${EMMC_NAME} </tmp/fdisk.script 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "The fdisk partition fails, Please try again."
|
||||
dd if=/root/BackupOldBootloader.img of=/dev/${EMMC_NAME} conv=fsync && sync
|
||||
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=512 count=1 && sync
|
||||
exit 1
|
||||
fi
|
||||
echo "Partition complete."
|
||||
|
||||
# write some zero data to part begin
|
||||
seek=$((start1 / 2048))
|
||||
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
|
||||
|
||||
seek=$((start2 / 2048))
|
||||
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
|
||||
|
||||
seek=$((start3 / 2048))
|
||||
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
|
||||
|
||||
seek=$((start4 / 2048))
|
||||
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1M count=1 seek=$seek conv=fsync
|
||||
|
||||
#Mainline U-BOOT detection
|
||||
FLASH_MAINLINE_UBOOT=0
|
||||
if [[ -n "${MAINLINE_UBOOT}" && -f "${MAINLINE_UBOOT}" ]]; then
|
||||
cat <<EOF
|
||||
----------------------------------------------------------------------------------
|
||||
Found an available mainline bootloader (Mainline u-boot), you can flash into EMMC.
|
||||
----------------------------------------------------------------------------------
|
||||
EOF
|
||||
while :; do
|
||||
# For [luci-app-amlogic] input parameter: SOC & DTB
|
||||
# When there is no input parameter, select manually
|
||||
if [[ "${AUTO_MAINLINE_UBOOT}" == "yes" ]]; then
|
||||
if [[ "${K510}" -eq "1" ]]; then
|
||||
yn="y"
|
||||
else
|
||||
yn="n"
|
||||
fi
|
||||
elif [[ "${AUTO_MAINLINE_UBOOT}" == "no" ]]; then
|
||||
yn="n"
|
||||
else
|
||||
read -p "Please choose whether to write the mainline bootloader to EMMC? y/n " yn
|
||||
fi
|
||||
case $yn in
|
||||
y | Y)
|
||||
FLASH_MAINLINE_UBOOT=1
|
||||
break
|
||||
;;
|
||||
n | N)
|
||||
FLASH_MAINLINE_UBOOT=0
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${FLASH_MAINLINE_UBOOT}" -eq "1" ]]; then
|
||||
echo -e "Write Mainline bootloader: [ ${MAINLINE_UBOOT} ]"
|
||||
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
|
||||
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
|
||||
elif [[ -n "${ANDROID_UBOOT}" && -f "${ANDROID_UBOOT}" ]]; then
|
||||
echo -e "Write Android bootloader: [ ${ANDROID_UBOOT} ]"
|
||||
dd if=${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
|
||||
dd if=${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
|
||||
else
|
||||
echo "Did not change the original bootloader."
|
||||
fi
|
||||
|
||||
# fix wifi macaddr
|
||||
if [ -x /usr/bin/fix_wifi_macaddr.sh ]; then
|
||||
/usr/bin/fix_wifi_macaddr.sh
|
||||
fi
|
||||
|
||||
# mkfs
|
||||
echo "Start creating file system ... "
|
||||
echo "Create a boot file system ... "
|
||||
|
||||
echo "format boot partiton..."
|
||||
mkfs.fat -n EMMC_BOOT -F 32 /dev/${EMMC_NAME}p1
|
||||
mkdir -p /mnt/${EMMC_NAME}p1
|
||||
sleep 2
|
||||
umount -f /mnt/${EMMC_NAME}p1 2>/dev/null
|
||||
|
||||
echo "format rootfs1 partiton..."
|
||||
ROOTFS1_UUID=$(/usr/bin/uuidgen)
|
||||
mkfs.btrfs -f -U ${ROOTFS1_UUID} -L EMMC_ROOTFS1 -m single /dev/${EMMC_NAME}p2
|
||||
mkdir -p /mnt/${EMMC_NAME}p2
|
||||
sleep 2
|
||||
umount -f /mnt/${EMMC_NAME}p2 2>/dev/null
|
||||
|
||||
echo "format rootfs2 partiton..."
|
||||
ROOTFS2_UUID=$(/usr/bin/uuidgen)
|
||||
mkfs.btrfs -f -U ${ROOTFS2_UUID} -L EMMC_ROOTFS2 -m single /dev/${EMMC_NAME}p3
|
||||
mkdir -p /mnt/${EMMC_NAME}p3
|
||||
sleep 2
|
||||
umount -f /mnt/${EMMC_NAME}p3 2>/dev/null
|
||||
|
||||
# mount and copy
|
||||
echo "Wait for the boot file system to mount ... "
|
||||
i=1
|
||||
max_try=10
|
||||
while [ $i -le $max_try ]; do
|
||||
mount -t vfat /dev/${EMMC_NAME}p1 /mnt/${EMMC_NAME}p1 2>/dev/null
|
||||
sleep 2
|
||||
mnt=$(lsblk -l -o MOUNTPOINT | grep /mnt/${EMMC_NAME}p1)
|
||||
|
||||
if [ "$mnt" == "" ]; then
|
||||
if [ $i -lt $max_try ]; then
|
||||
echo "Not mounted successfully, try again ..."
|
||||
i=$((i + 1))
|
||||
else
|
||||
error_msg "Cannot mount the boot file system, give up!"
|
||||
fi
|
||||
else
|
||||
echo "Successfully mounted."
|
||||
echo "copy boot ..."
|
||||
cd /mnt/${EMMC_NAME}p1
|
||||
rm -rf /boot/'System Volume Information/'
|
||||
(cd /boot && tar cf - .) | tar xf -
|
||||
sync
|
||||
|
||||
echo "Edit uEnv.txt ..."
|
||||
[[ -f "uEnv.txt" ]] && {
|
||||
sed -i -E \
|
||||
-e "s|/dtb/amlogic.*|/dtb/amlogic/${FDTFILE}|" \
|
||||
-e "s|UUID=[^ ]*|UUID=${ROOTFS1_UUID}|" \
|
||||
-e "s|rootflags=compress=zstd:[^ ]*|rootflags=compress=zstd:${ZSTD_LEVEL}|" \
|
||||
uEnv.txt
|
||||
}
|
||||
|
||||
# Replace the extlinux/extlinux.conf if it exists
|
||||
[[ -f "extlinux/extlinux.conf" ]] && {
|
||||
sed -i -E \
|
||||
-e "s|/dtb/amlogic.*|/dtb/amlogic/${FDTFILE}|" \
|
||||
-e "s|UUID=[^ ]*|UUID=${ROOTFS1_UUID}|" \
|
||||
-e "s|rootflags=compress=zstd:[^ ]*|rootflags=compress=zstd:${ZSTD_LEVEL}|" \
|
||||
extlinux/extlinux.conf
|
||||
}
|
||||
|
||||
rm -f s905_autoscript* aml_autoscript*
|
||||
|
||||
if [ ${K510} -eq 1 ]; then
|
||||
if [ -f ${UBOOT_OVERLOAD} ]; then
|
||||
cp -f -v ${UBOOT_OVERLOAD} u-boot.emmc
|
||||
elif [ -f "u-boot.ext" ]; then
|
||||
cp -f -v u-boot.ext u-boot.emmc
|
||||
fi
|
||||
fi
|
||||
|
||||
mv -f boot-emmc.ini boot.ini
|
||||
mv -f boot-emmc.cmd boot.cmd
|
||||
mv -f boot-emmc.scr boot.scr
|
||||
|
||||
sync
|
||||
echo "complete."
|
||||
cd /
|
||||
umount -f /mnt/${EMMC_NAME}p1
|
||||
break
|
||||
fi
|
||||
done
|
||||
echo "complete."
|
||||
|
||||
echo "Wait for the rootfs file system to mount ... "
|
||||
i=1
|
||||
while [ $i -le $max_try ]; do
|
||||
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} /dev/${EMMC_NAME}p2 /mnt/${EMMC_NAME}p2 2>/dev/null
|
||||
sleep 2
|
||||
mnt=$(lsblk -l -o MOUNTPOINT | grep /mnt/${EMMC_NAME}p2)
|
||||
if [ "$mnt" == "" ]; then
|
||||
if [ $i -lt $max_try ]; then
|
||||
echo "Not mounted successfully, try again ..."
|
||||
i=$((i + 1))
|
||||
else
|
||||
error_msg "Cannot mount rootfs file system, give up!"
|
||||
fi
|
||||
else
|
||||
echo "Successfully mounted"
|
||||
echo "Create folder ... "
|
||||
cd /mnt/${EMMC_NAME}p2
|
||||
btrfs subvolume create etc
|
||||
mkdir -p bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www .reserved .snapshots
|
||||
ln -sf lib/ lib64
|
||||
ln -sf tmp/ var
|
||||
sync
|
||||
echo "complete."
|
||||
|
||||
COPY_SRC="root etc bin sbin lib opt usr www"
|
||||
echo "Copy data ... "
|
||||
for src in $COPY_SRC; do
|
||||
echo "copy [ $src ] ..."
|
||||
(cd / && tar cf - $src) | tar xf -
|
||||
sync
|
||||
done
|
||||
echo "Copy complete."
|
||||
sync
|
||||
|
||||
cat >etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"bip": "172.31.0.1/24",
|
||||
"data-root": "/mnt/${EMMC_NAME}p4/docker/",
|
||||
"log-level": "warn",
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "5"
|
||||
},
|
||||
"registry-mirrors": [
|
||||
"https://mirror.baidubce.com/",
|
||||
"https://hub-mirror.c.163.com"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# change data_root value in /etc/config/dockerd
|
||||
if [[ -f "/etc/init.d/dockerman" ]] && [[ -f "/etc/config/dockerd" ]]; then
|
||||
sed -i "s|option data_root.*|option data_root '/mnt/${EMMC_NAME}p4/docker/'|g" etc/config/dockerd
|
||||
fi
|
||||
rm -rf opt/docker && ln -sf /mnt/${EMMC_NAME}p4/docker/ opt/docker >/dev/null
|
||||
rm -rf usr/bin/AdGuardHome && ln -sf /mnt/${EMMC_NAME}p4/AdGuardHome usr/bin/ >/dev/null
|
||||
|
||||
echo "Edit configuration file ..."
|
||||
#cd /mnt/${EMMC_NAME}p2/usr/bin/
|
||||
#rm -f openwrt-install-amlogic openwrt-update-amlogic
|
||||
cd /mnt/${EMMC_NAME}p2/etc/rc.d
|
||||
ln -sf ../init.d/dockerd S99dockerd
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
cd /mnt/${EMMC_NAME}p2/etc
|
||||
cat >fstab <<EOF
|
||||
UUID=${ROOTFS1_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
|
||||
LABEL=EMMC_BOOT /boot vfat defaults 0 2
|
||||
#tmpfs /tmp tmpfs defaults,nosuid 0 0
|
||||
EOF
|
||||
|
||||
cd /mnt/${EMMC_NAME}p2/etc/config
|
||||
cat >fstab <<EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '1'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '0'
|
||||
|
||||
config mount
|
||||
option target '/rom'
|
||||
option uuid '${ROOTFS1_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'btrfs'
|
||||
option options 'compress=zstd:${ZSTD_LEVEL}'
|
||||
|
||||
config mount
|
||||
option target '/boot'
|
||||
option label 'EMMC_BOOT'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'vfat'
|
||||
|
||||
EOF
|
||||
|
||||
echo -n "Create initial etc snapshot -> .snapshots/etc-000"
|
||||
cd /mnt/${EMMC_NAME}p2 &&
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-000
|
||||
sync
|
||||
|
||||
cd /
|
||||
umount -f /mnt/${EMMC_NAME}p2
|
||||
break
|
||||
fi
|
||||
done
|
||||
echo "complete."
|
||||
|
||||
echo "Create a shared file system."
|
||||
mkdir -p /mnt/${EMMC_NAME}p4
|
||||
|
||||
# When there is no input parameter, select manually
|
||||
if [[ -n "${SHARED_FSTYPE}" ]]; then
|
||||
TARGET_SHARED_FSTYPE=${SHARED_FSTYPE}
|
||||
else
|
||||
cat <<EOF
|
||||
---------------------------------------------------------------------------------
|
||||
Please select the type of shared file system:
|
||||
1. ext4: [Default options] suitable for general use.
|
||||
2. btrfs: Which can extend the service life of ssd/mmc.
|
||||
3. f2fs: Fast reading and writing speed, but the compatibility is slightly poor.
|
||||
4. xfs: Very good file system, alternative to ext4.
|
||||
---------------------------------------------------------------------------------
|
||||
EOF
|
||||
read -p "Please Input ID: " TARGET_SHARED_FSTYPE
|
||||
fi
|
||||
case $TARGET_SHARED_FSTYPE in
|
||||
2 | btrfs)
|
||||
mkfs.btrfs -f -L EMMC_SHARED -m single /dev/${EMMC_NAME}p4 >/dev/null
|
||||
mount -t btrfs /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
|
||||
;;
|
||||
3 | f2fs)
|
||||
mkfs.f2fs -f -l EMMC_SHARED /dev/${EMMC_NAME}p4 >/dev/null
|
||||
mount -t f2fs /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
|
||||
;;
|
||||
4 | xfs)
|
||||
mkfs.xfs -f -L EMMC_SHARED /dev/${EMMC_NAME}p4 >/dev/null
|
||||
mount -t xfs /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
|
||||
;;
|
||||
*)
|
||||
mkfs.ext4 -F -L EMMC_SHARED /dev/${EMMC_NAME}p4 >/dev/null
|
||||
mount -t ext4 /dev/${EMMC_NAME}p4 /mnt/${EMMC_NAME}p4
|
||||
;;
|
||||
esac
|
||||
mkdir -p /mnt/${EMMC_NAME}p4/docker /mnt/${EMMC_NAME}p4/AdGuardHome/data
|
||||
sync
|
||||
|
||||
echo "Successful installed, please unplug the USB, re-insert the power supply to start the openwrt."
|
||||
exit 0
|
||||
@@ -0,0 +1,516 @@
|
||||
#!/bin/bash
|
||||
#====================================================================================
|
||||
#
|
||||
# Function: Update the kernel for OpenWrt (Amlogic s9xxx, Allwinner, Rockchip)
|
||||
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Support the kernel: boot-*.tar.gz, dtb-*.tar.gz, modules-*.tar.gz
|
||||
# It is recommended to install MAINLINE_UBOOT for kernel versions above 5.10.y
|
||||
# openwrt-kernel ${AUTO_MAINLINE_UBOOT}
|
||||
# E.g: openwrt-kernel yes
|
||||
# openwrt-kernel no
|
||||
#
|
||||
#================================== Functions list ==================================
|
||||
#
|
||||
# error_msg : Output error message
|
||||
# get_textoffset : Get kernel TEXT_OFFSET
|
||||
# init_var : Initialize all variables
|
||||
# check_kernel : Check kernel files list
|
||||
# chech_files_same : Check file consistency
|
||||
# restore_kernel : Restore current kernel
|
||||
# update_kernel : Update the kernel
|
||||
# update_uboot : Update the uboot
|
||||
#
|
||||
#============================== Set default parameters ==============================
|
||||
#
|
||||
# Receive one-key command related parameters
|
||||
AUTO_MAINLINE_UBOOT="no"
|
||||
# Set the release check file
|
||||
release_file="/etc/flippy-openwrt-release"
|
||||
#
|
||||
#====================================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "[Error] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the /boot file system
|
||||
get_boot_partition_name() {
|
||||
local paths="/boot"
|
||||
local partition_name
|
||||
|
||||
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get kernel TEXT_OFFSET, For u-boot.ext and u-boot.emmc
|
||||
get_textoffset() {
|
||||
boot_tgz_file="${1}"
|
||||
vmlinuz_name="${2}"
|
||||
K510="1"
|
||||
temp_dir="$(mktemp -d)"
|
||||
(
|
||||
cd ${temp_dir}
|
||||
tar -xf "${boot_tgz_file}" "${vmlinuz_name}"
|
||||
)
|
||||
# With TEXT_OFFSET patch is [ 0108 ], without TEXT_OFFSET patch is [ 0000 ]
|
||||
[[ "$(hexdump -n 15 -x "${temp_dir}/${vmlinuz_name}" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
|
||||
}
|
||||
|
||||
init_var() {
|
||||
# Receive one-key command related parameters
|
||||
[[ "${1}" == "yes" ]] && AUTO_MAINLINE_UBOOT="yes"
|
||||
|
||||
# Check dependencies
|
||||
[[ -n "$(busybox which tar)" ]] || error_msg "Missing [ tar ] in OpenWrt firmware, unable to update kernel"
|
||||
|
||||
# Check release file
|
||||
if [[ -s "${release_file}" ]]; then
|
||||
source "${release_file}"
|
||||
PLATFORM="${PLATFORM}"
|
||||
MODEL_ID="${MODEL_ID}"
|
||||
UBOOT_OVERLOAD="${UBOOT_OVERLOAD}"
|
||||
MAINLINE_UBOOT="${MAINLINE_UBOOT}"
|
||||
ANDROID_UBOOT="${ANDROID_UBOOT}"
|
||||
SOC="${SOC}"
|
||||
LOCK_KERNEL="${LOCK_KERNEL}"
|
||||
else
|
||||
error_msg "${release_file} file is missing!"
|
||||
fi
|
||||
[[ -n "${PLATFORM}" ]] || error_msg "Missing ${PLATFORM} value in ${release_file} file."
|
||||
|
||||
# Define supported platforms
|
||||
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
|
||||
[[ -n "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" ]] || error_msg "[ ${PLATFORM} ] is not supported."
|
||||
|
||||
# Check and repair partition mount points
|
||||
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
|
||||
echo -e "Partition mount point error, start repairing..."
|
||||
openwrt-backup -g
|
||||
}
|
||||
|
||||
# Set /boot/vmlinuz-* replication names for different SoCs
|
||||
MYBOOT_VMLINUZ="$(ls -l /boot/*Image 2>/dev/null | awk '{print $9}' | head -n 1)"
|
||||
MYBOOT_VMLINUZ="${MYBOOT_VMLINUZ##*/}"
|
||||
[[ -n "${MYBOOT_VMLINUZ}" ]] || error_msg "Failed to get Image name: [ ${MYBOOT_VMLINUZ} ]"
|
||||
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case "${ROOT_PTNAME}" in
|
||||
mmcblk?p[1-9])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
[hsv]d[a-z][1-9])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')"
|
||||
PARTITION_NAME=""
|
||||
;;
|
||||
nvme?n?p[1-9])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
P4_PATH="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
|
||||
# Move kernel related files to the ${P4_PATH} directory
|
||||
mv -f /tmp/upload/* ${P4_PATH} 2>/dev/null
|
||||
|
||||
# Current device model
|
||||
MYDEVICE_NAME="$(cat /proc/device-tree/model | tr -d '\000')"
|
||||
[[ "${PLATFORM}" == "qemu-aarch64" ]] && MYDEVICE_NAME="KVM Virtual Machine"
|
||||
echo -e "Current device: ${MYDEVICE_NAME} [ ${PLATFORM} ], Use in [ ${EMMC_NAME} ]"
|
||||
sync && echo ""
|
||||
}
|
||||
|
||||
# Check kernel files list
|
||||
check_kernel() {
|
||||
cd ${P4_PATH}
|
||||
|
||||
# Determine custom kernel filename
|
||||
kernel_boot="$(ls boot-*.tar.gz 2>/dev/null | head -n 1)"
|
||||
kernel_name="${kernel_boot:5:-7}"
|
||||
|
||||
KERNEL_VERSION="$(echo ${kernel_name} | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+')"
|
||||
echo -e "Kernel name: ${kernel_name}"
|
||||
|
||||
# check if kernel is locked
|
||||
if [ -n "${LOCK_KERNEL}" ]; then
|
||||
if [ "${LOCK_KERNEL}" != "${kernel_name}" ]; then
|
||||
if ! echo "${kernel_name}" | grep -E '^5.10.\d+-.*?rk35.*?$' >/dev/null; then
|
||||
error_msg "The kernel version is locked to [ ${LOCK_KERNEL} ], but your kernel is [ ${kernel_name} ]. "
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if the file is added with TEXT_OFFSET patch
|
||||
get_textoffset "${P4_PATH}/${kernel_boot}" "vmlinuz-${kernel_name}"
|
||||
echo -e "K510 [ ${K510} ]"
|
||||
if [[ "${PLATFORM}" == "amlogic" && "${K510}" -eq "1" ]]; then
|
||||
[[ -n "${UBOOT_OVERLOAD}" && -f "/boot/${UBOOT_OVERLOAD}" ]] || error_msg "The UBOOT_OVERLOAD file is missing and cannot be update."
|
||||
fi
|
||||
|
||||
# Check the sha256sums file
|
||||
sha256sums_file="sha256sums"
|
||||
sha256sums_check="1"
|
||||
[[ -s "${sha256sums_file}" && -n "$(cat ${sha256sums_file})" ]] || sha256sums_check="0"
|
||||
[[ -n "$(busybox which sha256sum)" ]] || sha256sums_check="0"
|
||||
[[ "${sha256sums_check}" -eq "1" ]] && echo -e "Enable sha256sum checking..."
|
||||
|
||||
# Loop check file
|
||||
i="1"
|
||||
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
|
||||
kernel_list=("boot" "modules")
|
||||
else
|
||||
kernel_list=("boot" "dtb-${PLATFORM}" "modules")
|
||||
fi
|
||||
for kernel_file in ${kernel_list[*]}; do
|
||||
# Set check filename
|
||||
tmp_file="${kernel_file}-${kernel_name}.tar.gz"
|
||||
# Check if file exists
|
||||
[[ -s "${tmp_file}" ]] || error_msg "The [ ${kernel_file} ] file is missing."
|
||||
# Check if the file sha256sum is correct
|
||||
if [[ "${sha256sums_check}" -eq "1" ]]; then
|
||||
tmp_sha256sum="$(sha256sum "${tmp_file}" | awk '{print $1}')"
|
||||
tmp_checkcode="$(cat ${sha256sums_file} | grep ${tmp_file} | awk '{print $1}')"
|
||||
[[ "${tmp_sha256sum}" == "${tmp_checkcode}" ]] || error_msg "${tmp_file}: sha256sum verification failed."
|
||||
echo -e "(${i}/3) [ ${tmp_file} ] file sha256sum check same."
|
||||
fi
|
||||
let i++
|
||||
done
|
||||
|
||||
sync && echo ""
|
||||
}
|
||||
|
||||
# Check the consistency of amlogic device files
|
||||
chech_files_same() {
|
||||
i="0"
|
||||
max_try="5"
|
||||
while [[ "${i}" -le "${max_try}" ]]; do
|
||||
if [[ "$(sha256sum "${1}" | awk '{print $1}')" == "$(sha256sum "${2}" | awk '{print $1}')" ]]; then
|
||||
echo "" && break
|
||||
else
|
||||
cp -f ${1} ${2}
|
||||
i="$((i + 1))"
|
||||
fi
|
||||
done
|
||||
[[ "${i}" -gt "${max_try}" ]] && echo "God, it's different after ${max_try} copies: [ ${1} ]"
|
||||
}
|
||||
|
||||
# Restore the kernel when the update fails
|
||||
restore_kernel() {
|
||||
(
|
||||
cd /boot
|
||||
rm -rf \
|
||||
config-${kernel_name} \
|
||||
System.map-${kernel_name} \
|
||||
initrd.img-${kernel_name} \
|
||||
uInitrd-${kernel_name} \
|
||||
vmlinuz-${kernel_name} \
|
||||
initrd.img \
|
||||
uInitrd \
|
||||
zImage \
|
||||
Image \
|
||||
vmlinuz \
|
||||
dtb* 2>/dev/null
|
||||
tar -xzf /tmp/boot-backup.tar.gz 2>/dev/null
|
||||
)
|
||||
error_msg "Kernel update failed and has been reverted."
|
||||
}
|
||||
|
||||
# Update the kernel
|
||||
update_kernel() {
|
||||
local cur_kernel_name=$(uname -r)
|
||||
local boot_fstype=$(df -T /boot | tail -n1 | awk '{print $2}')
|
||||
echo -e "Start unpacking the kernel..."
|
||||
|
||||
# 01. for /boot five files
|
||||
# Backup the current_kernel
|
||||
(
|
||||
cd /boot
|
||||
tar -czf /tmp/boot-backup.tar.gz \
|
||||
config-${cur_kernel_name} \
|
||||
System.map-${cur_kernel_name} \
|
||||
initrd.img-${cur_kernel_name} \
|
||||
uInitrd-${cur_kernel_name} \
|
||||
vmlinuz-${cur_kernel_name} \
|
||||
initrd.img \
|
||||
uInitrd \
|
||||
zImage \
|
||||
Image \
|
||||
vmlinuz \
|
||||
dtb* 2>/dev/null
|
||||
rm -rf \
|
||||
config-${cur_kernel_name} \
|
||||
System.map-${cur_kernel_name} \
|
||||
initrd.img-${cur_kernel_name} \
|
||||
uInitrd-${cur_kernel_name} \
|
||||
vmlinuz-${cur_kernel_name} \
|
||||
initrd.img \
|
||||
uInitrd \
|
||||
zImage \
|
||||
Image \
|
||||
vmlinuz \
|
||||
dtb* 2>/dev/null
|
||||
)
|
||||
# Extract the new kernel
|
||||
tar -xf ${P4_PATH}/boot-${kernel_name}.tar.gz -C /boot
|
||||
|
||||
# Check if the file exists
|
||||
local valid_files
|
||||
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
|
||||
valid_files="vmlinuz-${kernel_name} initrd.img-${kernel_name} config-${kernel_name} System.map-${kernel_name}"
|
||||
rm -f /boot/uInitrd*
|
||||
else
|
||||
valid_files="vmlinuz-${kernel_name} uInitrd-${kernel_name} config-${kernel_name} System.map-${kernel_name}"
|
||||
# wxy-oect: MODEL_ID numbers r304,r306 and w[0-9]{3}, require special handling of uInitrd
|
||||
[[ "${MODEL_ID}" =~ ^(r304|r306|w[0-9]{3})$ ]] || rm -f /boot/initrd.img*
|
||||
fi
|
||||
for f in ${valid_files}; do [[ -f "/boot/${f}" ]] || restore_kernel; done
|
||||
|
||||
# Check if the files are the same
|
||||
(
|
||||
cd /boot
|
||||
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
|
||||
ln -sf initrd.img-${kernel_name} initrd.img
|
||||
ln -sf vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ}
|
||||
elif [[ "$boot_fstype" == "vfat" ]]; then
|
||||
cp -f uInitrd-${kernel_name} uInitrd
|
||||
[[ -z "$(chech_files_same uInitrd-${kernel_name} uInitrd)" ]] || restore_kernel
|
||||
cp -f vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ}
|
||||
[[ -z "$(chech_files_same vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ})" ]] || restore_kernel
|
||||
else
|
||||
ln -sf uInitrd-${kernel_name} uInitrd
|
||||
ln -sf vmlinuz-${kernel_name} ${MYBOOT_VMLINUZ}
|
||||
fi
|
||||
|
||||
# wxy-oect: MODEL_ID numbers r304 and r306, require special handling of uInitrd
|
||||
[[ "${MODEL_ID}" =~ ^(r304|r306)$ ]] && ln -sf initrd.img-${kernel_name} uInitrd
|
||||
)
|
||||
|
||||
echo -e "(1/3) Unpacking [ boot-${kernel_name}.tar.gz ] done."
|
||||
|
||||
if [[ "${PLATFORM}" == "qemu-aarch64" ]]; then
|
||||
echo -e "(2/3) skip unpack dtb files."
|
||||
else
|
||||
# 02. for /boot/dtb/${PLATFORM}/*
|
||||
if [[ "${boot_fstype}" == "vfat" ]]; then
|
||||
(cd /boot && mkdir -p dtb/${PLATFORM})
|
||||
else
|
||||
(cd /boot && mkdir -p dtb-${kernel_name}/${PLATFORM} && ln -sf dtb-${kernel_name} dtb)
|
||||
fi
|
||||
tar -xf ${P4_PATH}/dtb-${PLATFORM}-${kernel_name}.tar.gz -C /boot/dtb/${PLATFORM}
|
||||
[[ "$(ls /boot/dtb/${PLATFORM} -l 2>/dev/null | grep "^-" | wc -l)" -ge "1" ]] || error_msg "/boot/dtb/${PLATFORM} file is missing."
|
||||
echo -e "(2/3) Unpacking [ dtb-${PLATFORM}-${kernel_name}.tar.gz ] done."
|
||||
fi
|
||||
|
||||
# 03. for /lib/modules/*
|
||||
rm -rf /lib/modules/*
|
||||
tar -xf ${P4_PATH}/modules-${kernel_name}.tar.gz -C /lib/modules
|
||||
(
|
||||
cd /lib/modules/${kernel_name}
|
||||
rm -f *.ko
|
||||
find ./ -type f -name '*.ko' -exec ln -s {} ./ \;
|
||||
sync && sleep 3
|
||||
x=$(ls *.ko -l 2>/dev/null | grep "^l" | wc -l)
|
||||
[[ "${x}" -eq "0" ]] && error_msg "Error *.ko Files not found."
|
||||
)
|
||||
echo -e "(3/3) Unpacking [ modules-${kernel_name}.tar.gz ] done."
|
||||
|
||||
# Delete kernel tmpfiles
|
||||
rm -f ${P4_PATH}/*-${kernel_name}.tar.gz
|
||||
rm -f ${P4_PATH}/sha256sums
|
||||
|
||||
sync && echo ""
|
||||
}
|
||||
|
||||
# Update the uboot
|
||||
update_uboot() {
|
||||
# Only amlogic SoCs needs to be updated
|
||||
if [[ "${PLATFORM}" == "amlogic" ]]; then
|
||||
# Copy u-boot.ext and u-boot.emmc
|
||||
if [[ "${K510}" -eq "1" && -n "${UBOOT_OVERLOAD}" && -f "/boot/${UBOOT_OVERLOAD}" ]]; then
|
||||
[[ ! -f "/boot/u-boot.ext" ]] && cp -f "/boot/${UBOOT_OVERLOAD}" /boot/u-boot.ext && chmod +x /boot/u-boot.ext
|
||||
[[ ! -f "/boot/u-boot.emmc" ]] && cp -f "/boot/u-boot.ext" /boot/u-boot.emmc && chmod +x /boot/u-boot.emmc
|
||||
echo -e "The ${UBOOT_OVERLOAD} file copy is complete."
|
||||
elif [[ "${K510}" -eq "0" ]]; then
|
||||
rm -f "/boot/u-boot.ext" "/boot/u-boot.emmc"
|
||||
fi
|
||||
|
||||
# Write Mainline bootloader
|
||||
if [[ -f "${MAINLINE_UBOOT}" && "${AUTO_MAINLINE_UBOOT}" == "yes" ]]; then
|
||||
echo -e "Write Mainline bootloader: [ ${MAINLINE_UBOOT} ] to [ /dev/${EMMC_NAME} ]"
|
||||
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=442 conv=fsync
|
||||
dd if=${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
|
||||
echo -e "The MAINLINE_UBOOT file write is complete."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update release file
|
||||
sed -i "s|^KERNEL_VERSION=.*|KERNEL_VERSION='${kernel_name}'|g" ${release_file} 2>/dev/null
|
||||
# Update banner file
|
||||
sed -i "s| Kernel.*| Kernel: ${kernel_name}|g" /etc/banner 2>/dev/null
|
||||
|
||||
sync && echo ""
|
||||
}
|
||||
|
||||
# Rescue the kernel
|
||||
sos_kernel() {
|
||||
echo -e "Start rescuing kernel..."
|
||||
|
||||
# Supports specifying disks, such as: [ openwrt-kernel -s mmcblk1 ]
|
||||
box_disk="${2}"
|
||||
|
||||
if [[ -n "${box_disk}" ]]; then
|
||||
# Format the disk names
|
||||
box_disk="${box_disk//\/dev\//}"
|
||||
|
||||
# Check if the disk exists
|
||||
[[ -b "/dev/${box_disk}" ]] || error_msg "The specified disk [ ${box_disk} ] does not exist."
|
||||
|
||||
# Check if the disk is the same as the current system disk
|
||||
[[ "${box_disk}" == "${EMMC_NAME}" ]] && error_msg "The specified disk [ ${box_disk} ] is the same as the current system disk [ ${EMMC_NAME} ]."
|
||||
|
||||
echo -e "The device name of the specified disk: [ ${box_disk} ]"
|
||||
else
|
||||
# Find emmc disk, first find emmc containing boot0 partition
|
||||
box_disk="$(lsblk -l -o NAME | grep -oE '(mmcblk[0-9]?|nvme[0-9]?n[0-9]?|[hsv]d[a-z])' | grep -vE ^${EMMC_NAME} | sort -u | head -n 1)"
|
||||
|
||||
# Check if disk exists
|
||||
[[ -z "${box_disk}" ]] && error_msg "Unable to locate the storage requiring rescue."
|
||||
|
||||
echo -e "The device name of the target disk: [ ${box_disk} ]"
|
||||
fi
|
||||
|
||||
rescue_disk="/dev/${box_disk}"
|
||||
echo -e "The current OpenWrt is running on [ /dev/${EMMC_NAME} ], and the target disk for restoration is [ ${rescue_disk} ]."
|
||||
|
||||
# Create a temporary mount directory
|
||||
umount ${P4_PATH}/bootfs 2>/dev/null
|
||||
umount ${P4_PATH}/rootfs 2>/dev/null
|
||||
rm -rf ${P4_PATH}/bootfs ${P4_PATH}/rootfs 2>/dev/null
|
||||
mkdir -p ${P4_PATH}/{bootfs/,rootfs/} && sync
|
||||
[[ "${?}" -ne "0" ]] && error_msg "Failed to create temporary mount directory [ ${P4_PATH} ]"
|
||||
|
||||
# Mount target bootfs partition
|
||||
[[ "${box_disk}" =~ ^([hsv]d[a-z]) ]] && rescue_disk_partition_name="" || rescue_disk_partition_name="p"
|
||||
mount ${rescue_disk}${rescue_disk_partition_name}1 ${P4_PATH}/bootfs
|
||||
[[ "${?}" -ne "0" ]] && error_msg "mount ${rescue_disk}${PARTITION_NAME}1 failed!"
|
||||
echo -e "The [ ${rescue_disk}${rescue_disk_partition_name}1 ] partition is mounted on [ ${P4_PATH}/bootfs ]."
|
||||
|
||||
# Search uuid file
|
||||
if [[ -f "${P4_PATH}/bootfs/uEnv.txt" ]]; then
|
||||
search_file="uEnv.txt"
|
||||
elif [[ -f "${P4_PATH}/bootfs/armbianEnv.txt" ]]; then
|
||||
search_file="armbianEnv.txt"
|
||||
elif [[ -f "${P4_PATH}/bootfs/extlinux/extlinux.conf" ]]; then
|
||||
search_file="extlinux/extlinux.conf"
|
||||
else
|
||||
error_msg "The [ uEnv.txt, armbianEnv.txt, extlinux/extlinux.conf ] file does not exist, stop rescuing."
|
||||
fi
|
||||
|
||||
# Get the target partition uuid and rootfs
|
||||
target_parttion_uuid="$(grep '=UUID=' ${P4_PATH}/bootfs/${search_file} | sed -n 's/.*=UUID=\([a-f0-9-]*\).*/\1/p')"
|
||||
[[ -z "${target_parttion_uuid}" ]] && error_msg "The [ ${search_file} ] file does not contain the UUID value."
|
||||
target_rootfs="$(blkid | grep ${target_parttion_uuid} | awk -F':' '{print $1;}')"
|
||||
[[ -z "${target_rootfs}" ]] && error_msg "The [ ${target_parttion_uuid} ] UUID does not exist in the system."
|
||||
|
||||
# Mount target rootfs partition
|
||||
mount ${target_rootfs} ${P4_PATH}/rootfs
|
||||
[[ "${?}" -ne "0" ]] && error_msg "mount ${rescue_disk}${PARTITION_NAME}2 failed!"
|
||||
echo -e "The [ ${target_rootfs} ] partition is mounted on [ ${P4_PATH}/rootfs ]."
|
||||
|
||||
# Identify the current kernel files
|
||||
kernel_signature="$(uname -r)"
|
||||
|
||||
# 01. For /boot files
|
||||
[[ -d "${P4_PATH}/bootfs" ]] && {
|
||||
cd ${P4_PATH}/bootfs
|
||||
rm -rf config-* initrd.img-* System.map-* vmlinuz-* uInitrd* *Image dtb* u-boot.ext u-boot.emmc
|
||||
[[ -f "/boot/u-boot.ext" ]] && {
|
||||
cp -f /boot/u-boot.ext .
|
||||
cp -f /boot/u-boot.ext u-boot.emmc
|
||||
chmod +x u-boot.ext u-boot.emmc
|
||||
}
|
||||
cp -rf /boot/{*-${kernel_signature},uInitrd,*Image,dtb} .
|
||||
[[ "${?}" -ne "0" ]] && error_msg "(1/2) [ boot ] kernel files rescue failed."
|
||||
echo -e "(1/2) [ boot ] kernel files rescue succeeded."
|
||||
|
||||
[[ -f "/boot/emmc_autoscript.cmd" ]] && cp -f /boot/emmc_autoscript.cmd .
|
||||
[[ -f "/boot/emmc_autoscript" ]] && cp -f /boot/emmc_autoscript .
|
||||
[[ -f "/boot/s905_autoscript.cmd" ]] && cp -f /boot/s905_autoscript.cmd .
|
||||
[[ -f "/boot/s905_autoscript" ]] && cp -f /boot/s905_autoscript .
|
||||
} || error_msg "(1/2) The [ ${P4_PATH}/bootfs ] folder does not exist, stop rescuing."
|
||||
|
||||
# 02. For /lib/modules/${kernel_signature}
|
||||
[[ -d "${P4_PATH}/rootfs/lib/modules" ]] && {
|
||||
cd ${P4_PATH}/rootfs/lib/modules
|
||||
rm -rf *
|
||||
cp -rf /lib/modules/${kernel_signature} .
|
||||
[[ "${?}" -ne "0" ]] && error_msg "(2/2) [ modules ] kernel files rescue failed."
|
||||
echo -e "(2/2) [ modules ] kernel files rescue succeeded."
|
||||
} || error_msg "(2/2) The [ ${P4_PATH}/rootfs/lib/modules ] folder does not exist, stop rescuing."
|
||||
|
||||
# Unmount the emmc partition
|
||||
cd ${P4_PATH}
|
||||
umount -f ${P4_PATH}/bootfs
|
||||
[[ "${?}" -ne "0" ]] && error_msg "Failed to umount [ ${P4_PATH}/bootfs ]"
|
||||
umount -f ${P4_PATH}/rootfs
|
||||
[[ "${?}" -ne "0" ]] && error_msg "Failed to umount [ ${P4_PATH}/rootfs ]"
|
||||
# Remove the temporary mount directory
|
||||
rm -rf ${P4_PATH}/bootfs ${P4_PATH}/rootfs
|
||||
|
||||
sync && echo ""
|
||||
}
|
||||
|
||||
echo -e "Welcome to the OpenWrt Kernel Management Tool."
|
||||
# Operation environment check
|
||||
[[ -x "/usr/sbin/openwrt-kernel" ]] || error_msg "Please grant execution permission: chmod +x /usr/sbin/openwrt-kernel"
|
||||
|
||||
# Execute relevant functions based on the options
|
||||
if [[ "${@}" =~ ^-s(\s)* ]]; then
|
||||
# Initialize all variables
|
||||
init_var "${@}"
|
||||
# Start rescuing the kernel
|
||||
sos_kernel "${@}"
|
||||
|
||||
# Kernel restore successful
|
||||
sync && sleep 3
|
||||
echo -e "Kernel rescue successful, please remove the disk and restart the OpenWrt system."
|
||||
exit 0
|
||||
else
|
||||
# Initialize all variables
|
||||
init_var "${@}"
|
||||
# Check kernel files list
|
||||
check_kernel
|
||||
# Update the kernel
|
||||
update_kernel
|
||||
# Update the uboot
|
||||
update_uboot
|
||||
|
||||
# Kernel update successful
|
||||
sync && sleep 3
|
||||
echo "Successfully updated, automatic restarting..."
|
||||
reboot
|
||||
exit 0
|
||||
fi
|
||||
@@ -0,0 +1,662 @@
|
||||
#!/bin/bash
|
||||
#======================================================================================
|
||||
# Function: Update openwrt to emmc for Allwinner STB
|
||||
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
|
||||
#======================================================================================
|
||||
#
|
||||
# The script supports directly setting parameters for update, skipping interactive selection
|
||||
# openwrt-update-allwinner ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG}
|
||||
# E.g: openwrt-update-allwinner openwrt_s905d.img.gz yes restore
|
||||
# E.g: openwrt-update-allwinner openwrt_s905d.img.gz no no-restore
|
||||
|
||||
# You can also execute the script directly, and interactively select related functions
|
||||
# E.g: openwrt-update-allwinner
|
||||
#
|
||||
#======================================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "[ERROR] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the /boot file system
|
||||
get_boot_partition_name() {
|
||||
local paths="/boot"
|
||||
local partition_name
|
||||
|
||||
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition message of the root file system
|
||||
get_root_partition_msg() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
|
||||
[[ -n "${partition_msg}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
|
||||
echo "${partition_msg}"
|
||||
}
|
||||
|
||||
# Receive one-key command related parameters
|
||||
IMG_NAME=${1}
|
||||
AUTO_MAINLINE_UBOOT=${2}
|
||||
BACKUP_RESTORE_CONFIG=${3}
|
||||
|
||||
# Current FDT file
|
||||
if [[ -f "/boot/uEnv.txt" ]]; then
|
||||
source /boot/uEnv.txt 2>/dev/null
|
||||
MYDTB_FDTFILE=$(basename $FDT)
|
||||
elif [[ -f "/boot/armbianEnv.txt" ]]; then
|
||||
source /boot/armbianEnv.txt 2>/dev/null
|
||||
MYDTB_FDTFILE="$(basename $fdtfile)"
|
||||
elif [[ -f "/etc/flippy-openwrt-release" ]]; then
|
||||
source /etc/flippy-openwrt-release 2>/dev/null
|
||||
MYDTB_FDTFILE="${FDTFILE}"
|
||||
fi
|
||||
|
||||
[[ -z "${MYDTB_FDTFILE}" ]] && error_msg "Invalid FDTFILE: [ ${MYDTB_FDTFILE} ]"
|
||||
|
||||
# Current device model
|
||||
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
|
||||
if [[ -z "${MYDEVICE_NAME}" ]]; then
|
||||
error_msg "The device name is empty and cannot be recognized."
|
||||
elif [[ "$(echo ${MYDEVICE_NAME} | grep "V-Plus Cloud")" == "" ]]; then
|
||||
error_msg "[ ${MYDEVICE_NAME} ] is not [ V-Plus Cloud ] device, please select the correct script."
|
||||
else
|
||||
echo -e "Current device: ${MYDEVICE_NAME} [ vplus ]"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# Check and repair partition mount points
|
||||
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
|
||||
echo -e "Partition mount point error, start repairing..."
|
||||
openwrt-backup -g
|
||||
}
|
||||
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case ${ROOT_PTNAME} in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
|
||||
PARTITION_NAME="p"
|
||||
LB_PRE="EMMC_"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
|
||||
PARTITION_NAME=""
|
||||
LB_PRE=""
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
cd /mnt/${EMMC_NAME}${PARTITION_NAME}4/
|
||||
mv -f /tmp/upload/* . 2>/dev/null && sync
|
||||
|
||||
if [[ "${IMG_NAME}" == *.img ]]; then
|
||||
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
xz_file=$(ls *.img.xz | head -n 1)
|
||||
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
|
||||
xz -d ${xz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.img.gz | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
gzip -df ${gz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.7z | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
bsdtar -xmf ${gz_file} 2>/dev/null
|
||||
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
zip_file=$(ls *.zip | head -n 1)
|
||||
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
|
||||
unzip -o ${zip_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
else
|
||||
echo -e "Please upload or specify the update openwrt firmware file."
|
||||
echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
|
||||
echo -e "Specify method: Place the openwrt firmware file in [ /mnt/${EMMC_NAME}${PARTITION_NAME}4/ ]"
|
||||
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
|
||||
echo -e "After upload the openwrt firmware file, run again."
|
||||
exit 1
|
||||
fi
|
||||
sync
|
||||
|
||||
# check file
|
||||
if [ ! -f "${IMG_NAME}" ]; then
|
||||
error_msg "No update file found."
|
||||
else
|
||||
echo "Start update from [ ${IMG_NAME} ]"
|
||||
fi
|
||||
|
||||
# find boot partition
|
||||
BOOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot$/ {print $0}')
|
||||
if [ "${BOOT_PART_MSG}" == "" ]; then
|
||||
error_msg "The boot partition is not exists or not mounted, so it cannot be upgraded with this script!"
|
||||
fi
|
||||
|
||||
BR_FLAG=1
|
||||
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
|
||||
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
|
||||
yn="y"
|
||||
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
|
||||
yn="n"
|
||||
else
|
||||
read yn
|
||||
fi
|
||||
case $yn in
|
||||
n* | N*)
|
||||
BR_FLAG=0
|
||||
;;
|
||||
esac
|
||||
|
||||
BOOT_NAME=$(echo ${BOOT_PART_MSG} | awk '{print $1}')
|
||||
BOOT_PATH=$(echo ${BOOT_PART_MSG} | awk '{print $2}')
|
||||
BOOT_UUID=$(echo ${BOOT_PART_MSG} | awk '{print $4}')
|
||||
|
||||
# find root partition
|
||||
ROOT_PART_MSG="$(get_root_partition_msg)"
|
||||
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
|
||||
ROOT_PATH=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
|
||||
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
|
||||
case ${ROOT_NAME} in
|
||||
${EMMC_NAME}${PARTITION_NAME}2)
|
||||
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}3"
|
||||
NEW_ROOT_LABEL="${LB_PRE}ROOTFS2"
|
||||
;;
|
||||
${EMMC_NAME}${PARTITION_NAME}3)
|
||||
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}2"
|
||||
NEW_ROOT_LABEL="${LB_PRE}ROOTFS1"
|
||||
;;
|
||||
*)
|
||||
error_msg "The root partition location is invalid, so it cannot be upgraded with this script!"
|
||||
;;
|
||||
esac
|
||||
|
||||
# find new root partition
|
||||
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
|
||||
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
|
||||
error_msg "The new root partition is not exists, so it cannot be upgraded with this script!"
|
||||
fi
|
||||
NEW_ROOT_NAME=$(echo $NEW_ROOT_PART_MSG | awk '{print $1}')
|
||||
NEW_ROOT_PATH=$(echo $NEW_ROOT_PART_MSG | awk '{print $2}')
|
||||
NEW_ROOT_UUID=$(echo $NEW_ROOT_PART_MSG | awk '{print $4}')
|
||||
NEW_ROOT_MP=$(echo $NEW_ROOT_PART_MSG | awk '{print $5}')
|
||||
|
||||
# losetup
|
||||
losetup -f -P $IMG_NAME
|
||||
if [ $? -eq 0 ]; then
|
||||
LOOP_DEV=$(losetup | grep "$IMG_NAME" | awk '{print $1}')
|
||||
if [ "$LOOP_DEV" == "" ]; then
|
||||
error_msg "loop device not found!"
|
||||
fi
|
||||
else
|
||||
error_msg "losetup $IMG_FILE failed!"
|
||||
fi
|
||||
|
||||
# fix loopdev issue in kernel 5.19
|
||||
function fix_loopdev() {
|
||||
local parentdev=${1##*/}
|
||||
if [ ! -d /sys/block/${parentdev} ]; then
|
||||
return
|
||||
fi
|
||||
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
|
||||
for subdev in $subdevs; do
|
||||
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
|
||||
return
|
||||
elif [ -b /dev/${sub_dev} ]; then
|
||||
continue
|
||||
fi
|
||||
source /sys/block/${parentdev}/${subdev}/uevent
|
||||
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
|
||||
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
|
||||
done
|
||||
}
|
||||
fix_loopdev ${LOOP_DEV}
|
||||
|
||||
WAIT=3
|
||||
echo -n "The loopdev is $LOOP_DEV, wait ${WAIT} seconds "
|
||||
while [ $WAIT -ge 1 ]; do
|
||||
echo -n "."
|
||||
sleep 1
|
||||
WAIT=$((WAIT - 1))
|
||||
done
|
||||
echo
|
||||
|
||||
# umount loop devices (openwrt will auto mount some partition)
|
||||
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$LOOP_DEV" | awk '$3 !~ /^$/ {print $2}')
|
||||
for dev in $MOUNTED_DEVS; do
|
||||
while :; do
|
||||
echo -n "umount $dev ... "
|
||||
umount -f $dev
|
||||
sleep 1
|
||||
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$dev" | awk '$3 !~ /^$/ {print $2}')
|
||||
if [ "$mnt" == "" ]; then
|
||||
echo "ok"
|
||||
break
|
||||
else
|
||||
echo "try again ..."
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# mount src part
|
||||
WORK_DIR=$PWD
|
||||
P1=${WORK_DIR}/boot
|
||||
P2=${WORK_DIR}/root
|
||||
mkdir -p $P1 $P2
|
||||
echo -n "mount ${LOOP_DEV}p1 -> ${P1} ... "
|
||||
mount -t vfat -o ro ${LOOP_DEV}p1 ${P1}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "mount failed"
|
||||
losetup -D
|
||||
exit 1
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
|
||||
echo -n "mount ${LOOP_DEV}p2 -> ${P2} ... "
|
||||
ZSTD_LEVEL=6
|
||||
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "mount failed"
|
||||
umount -f ${P1}
|
||||
losetup -D
|
||||
exit 1
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
|
||||
# Prepare the dockerman config file
|
||||
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
|
||||
|
||||
flg=0
|
||||
# get current docker data root
|
||||
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
|
||||
if [ "$data_root" == "" ]; then
|
||||
flg=1
|
||||
# get current config from /etc/docker/daemon.json
|
||||
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
|
||||
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
|
||||
|
||||
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
|
||||
[ "$bip" == "null" ] && bip="172.31.0.1/24"
|
||||
|
||||
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
|
||||
[ "$log_level" == "null" ] && log_level="warn"
|
||||
|
||||
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
|
||||
[ "$_iptables" == "null" ] && _iptables="true"
|
||||
|
||||
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$data_root" == "" ]; then
|
||||
data_root="/opt/docker/" # the default data root
|
||||
fi
|
||||
|
||||
if ! uci get dockerd.globals >/dev/null 2>&1; then
|
||||
uci set dockerd.globals='globals'
|
||||
uci commit
|
||||
fi
|
||||
|
||||
# delete alter config , use inner config
|
||||
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
|
||||
uci delete dockerd.globals.alt_config_file
|
||||
uci commit
|
||||
fi
|
||||
|
||||
if [ $flg -eq 1 ]; then
|
||||
uci set dockerd.globals.data_root=$data_root
|
||||
[ "$bip" != "" ] && uci set dockerd.globals.bip=$bip
|
||||
[ "$log_level" != "" ] && uci set dockerd.globals.log_level=$log_level
|
||||
[ "$_iptables" != "" ] && uci set dockerd.globals.iptables=$_iptables
|
||||
if [ "$registry_mirrors" != "" ]; then
|
||||
for reg in $registry_mirrors; do
|
||||
uci add_list dockerd.globals.registry_mirrors=$reg
|
||||
done
|
||||
fi
|
||||
uci set dockerd.globals.auto_start='1'
|
||||
uci commit
|
||||
fi
|
||||
fi
|
||||
|
||||
#format NEW_ROOT
|
||||
echo "umount ${NEW_ROOT_MP}"
|
||||
umount -f "${NEW_ROOT_MP}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "umount failed, please reboot and try again!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "format ${NEW_ROOT_PATH}"
|
||||
NEW_ROOT_UUID=$(uuidgen)
|
||||
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} ${NEW_ROOT_PATH}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "format ${NEW_ROOT_PATH} failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP}"
|
||||
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_PATH} ${NEW_ROOT_MP}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP} failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# begin copy rootfs
|
||||
cd ${NEW_ROOT_MP}
|
||||
echo "Start copy data from ${P2} to ${NEW_ROOT_MP} ..."
|
||||
ENTRYS=$(ls)
|
||||
for entry in $ENTRYS; do
|
||||
if [ "$entry" == "lost+found" ]; then
|
||||
continue
|
||||
fi
|
||||
echo -n "remove old $entry ... "
|
||||
rm -rf $entry
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok"
|
||||
else
|
||||
error_msg "failed"
|
||||
fi
|
||||
done
|
||||
echo
|
||||
|
||||
echo "create etc subvolume ..."
|
||||
btrfs subvolume create etc
|
||||
echo -n "make dirs ... "
|
||||
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
|
||||
ln -sf lib/ lib64
|
||||
ln -sf tmp/ var
|
||||
echo "done"
|
||||
echo
|
||||
|
||||
COPY_SRC="root etc bin sbin lib opt usr www"
|
||||
echo "copy data ... "
|
||||
for src in $COPY_SRC; do
|
||||
echo -n "copy $src ... "
|
||||
(cd ${P2} && tar cf - $src) | tar xf -
|
||||
sync
|
||||
echo "done"
|
||||
done
|
||||
|
||||
SHFS="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
|
||||
echo "Modify config files ... "
|
||||
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
|
||||
rm -f ./etc/bench.log
|
||||
if [ -x ./usr/sbin/balethirq.pl ]; then
|
||||
if grep "balethirq.pl" "./etc/rc.local"; then
|
||||
echo "balance irq is enabled"
|
||||
else
|
||||
echo "enable balance irq"
|
||||
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
|
||||
fi
|
||||
fi
|
||||
cat >./etc/fstab <<EOF
|
||||
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
|
||||
LABEL=${LB_PRE}BOOT /boot vfat defaults 0 2
|
||||
#tmpfs /tmp tmpfs defaults,nosuid 0 0
|
||||
EOF
|
||||
|
||||
cat >./etc/config/fstab <<EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '1'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '0'
|
||||
|
||||
config mount
|
||||
option target '/rom'
|
||||
option uuid '${NEW_ROOT_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'btrfs'
|
||||
option options 'compress=zstd:${ZSTD_LEVEL}'
|
||||
|
||||
config mount
|
||||
option target '/boot'
|
||||
option label '${LB_PRE}BOOT'
|
||||
option enabled '1'
|
||||
option enabled_fsck '0'
|
||||
option fstype 'vfat'
|
||||
|
||||
EOF
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
sync
|
||||
|
||||
echo "create the first etc snapshot -> .snapshots/etc-000"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-000
|
||||
|
||||
[ -d ${SHFS}/docker ] || mkdir -p ${SHFS}/docker
|
||||
rm -rf opt/docker && ln -sf ${SHFS}/docker/ opt/docker
|
||||
|
||||
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
|
||||
[ -d ${SHFS}/AdGuardHome/data ] || mkdir -p ${SHFS}/AdGuardHome/data
|
||||
if [ ! -L /usr/bin/AdGuardHome ]; then
|
||||
[ -d /usr/bin/AdGuardHome ] &&
|
||||
cp -a /usr/bin/AdGuardHome/* ${SHFS}/AdGuardHome/
|
||||
fi
|
||||
ln -sf ${SHFS}/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
|
||||
fi
|
||||
|
||||
BOOTLOADER="./lib/u-boot/u-boot-sunxi-with-spl.bin"
|
||||
if [ -f ${BOOTLOADER} ]; then
|
||||
echo "update u-boot ... "
|
||||
# erase from 8kb to 4mb
|
||||
dd if=/dev/zero of=/dev/${EMMC_NAME} bs=1024 seek=8 count=4088 conv=fsync
|
||||
# write u-boot
|
||||
dd if=${BOOTLOADER} of=/dev/${EMMC_NAME} bs=1024 seek=8 conv=fsync
|
||||
echo "done"
|
||||
fi
|
||||
sync
|
||||
echo "copy done"
|
||||
echo
|
||||
|
||||
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
|
||||
if [ $BR_FLAG -eq 1 ]; then
|
||||
echo -n "Restore your old config files ... "
|
||||
(
|
||||
cd /
|
||||
eval tar czf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
)
|
||||
tar xzf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz
|
||||
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
|
||||
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
|
||||
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync
|
||||
|
||||
# 还原 fstab
|
||||
cp -f .snapshots/etc-000/fstab ./etc/fstab
|
||||
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
|
||||
# 还原 luci
|
||||
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
|
||||
# 还原/etc/config/rpcd
|
||||
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
|
||||
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
fi
|
||||
|
||||
rm -f ./etc/bench.log
|
||||
cat >>./etc/crontabs/root <<EOF
|
||||
17 3 * * * /etc/coremark.sh
|
||||
EOF
|
||||
|
||||
sed -e 's/ttyAMA0/ttyS0/' -i ./etc/inittab
|
||||
sss=$(date +%s)
|
||||
ddd=$((sss / 86400))
|
||||
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
|
||||
# 修复amule每次升级后重复添加条目的问题
|
||||
sed -e "/amule:x:/d" -i ./etc/shadow
|
||||
# 修复dropbear每次升级后重复添加sshd条目的问题
|
||||
sed -e "/sshd:x:/d" -i ./etc/shadow
|
||||
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
|
||||
echo "sshd:x:22:sshd" >>./etc/group
|
||||
fi
|
||||
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
|
||||
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
|
||||
fi
|
||||
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
|
||||
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
|
||||
fi
|
||||
|
||||
if [ $BR_FLAG -eq 1 ]; then
|
||||
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
|
||||
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
|
||||
fi
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
fi
|
||||
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
sync
|
||||
|
||||
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
|
||||
rm -f ./etc/part_size ./etc/first_run.sh
|
||||
mv ./etc/rc.local ./etc/rc.local.orig
|
||||
cat >"./etc/rc.local" <<EOF
|
||||
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
|
||||
/etc/init.d/dockerd enable
|
||||
/etc/init.d/dockerd start
|
||||
fi
|
||||
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
|
||||
/etc/init.d/dockerman enable
|
||||
/etc/init.d/dockerman start
|
||||
fi
|
||||
opkg remove --force-removal-of-dependent-packages shairport-sync-openssl
|
||||
mv /etc/rc.local.orig /etc/rc.local
|
||||
chmod 755 /etc/rc.local
|
||||
exec /etc/rc.local
|
||||
exit
|
||||
EOF
|
||||
chmod 755 ./etc/rc.local*
|
||||
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
|
||||
echo "create the second etc snapshot -> .snapshots/etc-001"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-001
|
||||
|
||||
# 2021.04.01添加
|
||||
# 强制锁定fstab,防止用户擅自修改挂载点
|
||||
# 开启了快照功能之后,不再需要锁定fstab
|
||||
#chattr +ia ./etc/config/fstab
|
||||
|
||||
cd ${WORK_DIR}
|
||||
|
||||
echo "Start copy data from ${P1} to /boot ..."
|
||||
cd /boot
|
||||
echo -n "remove old boot files ..."
|
||||
rm -rf *
|
||||
echo "done"
|
||||
echo -n "copy new boot files ... "
|
||||
(cd ${P1} && tar cf - .) | tar xf -
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
|
||||
echo -n "Update boot args ... "
|
||||
cat >uEnv.txt <<EOF
|
||||
LINUX=/zImage
|
||||
INITRD=/uInitrd
|
||||
|
||||
# Example:
|
||||
# FDT=/dtb/allwinner/sun50i-h6-vplus-cloud.dtb
|
||||
# FDT=/dtb/allwinner/sun50i-h6-vplus-cloud-2ghz.dtb
|
||||
FDT=/dtb/allwinner/${MYDTB_FDTFILE}
|
||||
|
||||
APPEND=root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyS0,115200n8 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
|
||||
EOF
|
||||
|
||||
# Compatible with armbianEnv.txt file
|
||||
[[ -f "armbianEnv.txt" ]] && {
|
||||
echo "Update armbianEnv.txt settings."
|
||||
sed -i "s|^rootdev=.*|rootdev=UUID=${NEW_ROOT_UUID}|g" armbianEnv.txt
|
||||
rm -f uEnv.txt
|
||||
}
|
||||
|
||||
# Replace the UUID for extlinux/extlinux.conf if it exists
|
||||
[[ -f "extlinux/extlinux.conf" ]] && {
|
||||
sed -i -E "s|UUID=[^ ]*|UUID=${NEW_ROOT_UUID}|" extlinux/extlinux.conf 2>/dev/null
|
||||
}
|
||||
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
|
||||
cd $WORK_DIR
|
||||
umount -f ${P1} ${P2} 2>/dev/null
|
||||
losetup -D 2>/dev/null
|
||||
rmdir ${P1} ${P2} 2>/dev/null
|
||||
rm -f ${IMG_NAME} 2>/dev/null
|
||||
rm -f sha256sums 2>/dev/null
|
||||
sync
|
||||
|
||||
echo "Successfully updated, automatic restarting..."
|
||||
sleep 3
|
||||
reboot
|
||||
exit 0
|
||||
@@ -0,0 +1,859 @@
|
||||
#!/bin/bash
|
||||
#======================================================================================
|
||||
# Function: Update openwrt to emmc for Amlogic S9xxx STB
|
||||
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
|
||||
#======================================================================================
|
||||
#
|
||||
# The script supports directly setting parameters for update, skipping interactive selection
|
||||
# openwrt-update-amlogic ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG}
|
||||
# E.g: openwrt-update-amlogic openwrt_s905d.img.gz yes restore
|
||||
# E.g: openwrt-update-amlogic openwrt_s905d.img.gz no no-restore
|
||||
|
||||
# You can also execute the script directly, and interactively select related functions
|
||||
# E.g: openwrt-update-amlogic
|
||||
#
|
||||
#======================================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "[ERROR] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the /boot file system
|
||||
get_boot_partition_name() {
|
||||
local paths="/boot"
|
||||
local partition_name
|
||||
|
||||
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition message of the root file system
|
||||
get_root_partition_msg() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
|
||||
[[ -n "${partition_msg}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
|
||||
echo "${partition_msg}"
|
||||
}
|
||||
|
||||
# Receive one-key command related parameters
|
||||
IMG_NAME="${1}"
|
||||
AUTO_MAINLINE_UBOOT="${2}"
|
||||
BACKUP_RESTORE_CONFIG="${3}"
|
||||
|
||||
# Current device model
|
||||
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
|
||||
if [[ -z "${MYDEVICE_NAME}" ]]; then
|
||||
error_msg "The device name is empty and cannot be recognized."
|
||||
elif [[ ! -f "/etc/flippy-openwrt-release" ]]; then
|
||||
error_msg "The [ /etc/flippy-openwrt-release ] file is missing."
|
||||
else
|
||||
echo -e "Current device: ${MYDEVICE_NAME} [ amlogic ]"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# Check and repair partition mount points
|
||||
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
|
||||
echo -e "Partition mount point error, start repairing..."
|
||||
openwrt-backup -g
|
||||
}
|
||||
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case ${ROOT_PTNAME} in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
|
||||
if lsblk -l -o NAME | grep "${EMMC_NAME}boot0" >/dev/null; then
|
||||
ROOT_DISK_TYPE="EMMC"
|
||||
else
|
||||
ROOT_DISK_TYPE="SD"
|
||||
fi
|
||||
PARTITION_NAME="p"
|
||||
LB_PRE="${ROOT_DISK_TYPE}_"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
|
||||
ROOT_DISK_TYPE="USB"
|
||||
PARTITION_NAME=""
|
||||
LB_PRE="${ROOT_DISK_TYPE}_"
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
DOCKER_ROOT="/mnt/${EMMC_NAME}${PARTITION_NAME}4/docker/"
|
||||
cd /mnt/${EMMC_NAME}${PARTITION_NAME}4/
|
||||
mv -f /tmp/upload/* . 2>/dev/null && sync
|
||||
|
||||
if [[ "${IMG_NAME}" == *.img ]]; then
|
||||
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
xz_file=$(ls *.img.xz | head -n 1)
|
||||
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
|
||||
xz -d ${xz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.img.gz | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
gzip -df ${gz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.7z | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
bsdtar -xmf ${gz_file} 2>/dev/null
|
||||
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
zip_file=$(ls *.zip | head -n 1)
|
||||
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
|
||||
unzip -o ${zip_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
else
|
||||
echo -e "Please upload or specify the update openwrt firmware file."
|
||||
echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
|
||||
echo -e "Specify method: Place the openwrt firmware file in [ /mnt/${EMMC_NAME}${PARTITION_NAME}4/ ]"
|
||||
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
|
||||
echo -e "After upload the openwrt firmware file, run again."
|
||||
exit 1
|
||||
fi
|
||||
sync
|
||||
|
||||
# check file
|
||||
if [ ! -f "${IMG_NAME}" ]; then
|
||||
error_msg "No update file found."
|
||||
else
|
||||
echo "Start update from [ ${IMG_NAME} ]"
|
||||
fi
|
||||
|
||||
# Check the necessary dependencies
|
||||
DEPENDS="lsblk uuidgen grep awk btrfs mkfs.fat mkfs.btrfs md5sum fatlabel"
|
||||
echo "Check the necessary dependencies..."
|
||||
for dep in ${DEPENDS}; do
|
||||
WITCH=$(busybox which ${dep})
|
||||
if [ "${WITCH}" == "" ]; then
|
||||
error_msg "Dependent command: ${dep} does not exist, upgrade cannot be performed, only flash through U disk/TF card!"
|
||||
else
|
||||
echo "${dep} path: ${WITCH}"
|
||||
fi
|
||||
done
|
||||
echo "Check passed"
|
||||
|
||||
# find boot partition
|
||||
BOOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot$/ {print $0}')
|
||||
if [ "${BOOT_PART_MSG}" == "" ]; then
|
||||
error_msg "Boot The partition does not exist, so the update cannot be continued!"
|
||||
fi
|
||||
BOOT_NAME=$(echo ${BOOT_PART_MSG} | awk '{print $1}')
|
||||
BOOT_PATH=$(echo ${BOOT_PART_MSG} | awk '{print $2}')
|
||||
BOOT_UUID=$(echo ${BOOT_PART_MSG} | awk '{print $4}')
|
||||
|
||||
BR_FLAG=1
|
||||
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
|
||||
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
|
||||
yn="y"
|
||||
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
|
||||
yn="n"
|
||||
else
|
||||
read yn
|
||||
fi
|
||||
case $yn in
|
||||
n* | N*)
|
||||
BR_FLAG=0
|
||||
;;
|
||||
esac
|
||||
|
||||
# find root partition
|
||||
ROOT_PART_MSG="$(get_root_partition_msg)"
|
||||
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
|
||||
ROOT_PATH=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
|
||||
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
|
||||
|
||||
case ${ROOT_NAME} in
|
||||
${EMMC_NAME}${PARTITION_NAME}2)
|
||||
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}3"
|
||||
NEW_ROOT_LABEL="${LB_PRE}ROOTFS2"
|
||||
;;
|
||||
${EMMC_NAME}${PARTITION_NAME}3)
|
||||
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}2"
|
||||
NEW_ROOT_LABEL="${LB_PRE}ROOTFS1"
|
||||
;;
|
||||
*)
|
||||
error_msg "ROOTFS The partition location is incorrect, so the update cannot continue!"
|
||||
;;
|
||||
esac
|
||||
echo "NEW_ROOT_NAME: [ ${NEW_ROOT_NAME} ]"
|
||||
|
||||
# find new root partition
|
||||
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
|
||||
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
|
||||
error_msg "The new ROOTFS partition does not exist, so the update cannot continue!"
|
||||
fi
|
||||
NEW_ROOT_NAME=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $1}')
|
||||
NEW_ROOT_PATH=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $2}')
|
||||
NEW_ROOT_UUID=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $4}')
|
||||
NEW_ROOT_MP=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $5}')
|
||||
echo "NEW_ROOT_MP: [ ${NEW_ROOT_MP} ]"
|
||||
|
||||
# backup old bootloader
|
||||
if [ ! -f /root/BackupOldBootloader.img ]; then
|
||||
echo "Backup bootloader -> [ BackupOldBootloader.img ] ... "
|
||||
dd if=/dev/${EMMC_NAME} of=/root/BackupOldBootloader.img bs=1M count=4 conv=fsync
|
||||
echo "Backup bootloader complete."
|
||||
echo
|
||||
fi
|
||||
|
||||
# losetup
|
||||
losetup -f -P ${IMG_NAME}
|
||||
if [ ${?} -eq 0 ]; then
|
||||
LOOP_DEV=$(losetup | grep "${IMG_NAME}" | awk '{print $1}')
|
||||
if [ "${LOOP_DEV}" == "" ]; then
|
||||
error_msg "loop device not found!"
|
||||
fi
|
||||
else
|
||||
error_msg "losetup [ ${IMG_FILE} ] failed!"
|
||||
fi
|
||||
|
||||
# fix loopdev issue in kernel 5.19
|
||||
function fix_loopdev() {
|
||||
local parentdev=${1##*/}
|
||||
if [ ! -d /sys/block/${parentdev} ]; then
|
||||
return
|
||||
fi
|
||||
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
|
||||
for subdev in ${subdevs}; do
|
||||
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
|
||||
return
|
||||
elif [ -b /dev/${sub_dev} ]; then
|
||||
continue
|
||||
fi
|
||||
source /sys/block/${parentdev}/${subdev}/uevent
|
||||
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
|
||||
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
|
||||
done
|
||||
}
|
||||
fix_loopdev ${LOOP_DEV}
|
||||
|
||||
WAIT=3
|
||||
echo "The loopdev is [ $LOOP_DEV ], wait [ ${WAIT} ] seconds. "
|
||||
while [[ "${WAIT}" -ge "1" ]]; do
|
||||
sleep 1
|
||||
WAIT=$((WAIT - 1))
|
||||
done
|
||||
|
||||
# umount loop devices (openwrt will auto mount some partition)
|
||||
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${LOOP_DEV}" | awk '$3 !~ /^$/ {print $2}')
|
||||
for dev in ${MOUNTED_DEVS}; do
|
||||
while :; do
|
||||
echo "umount [ ${dev} ] ... "
|
||||
umount -f ${dev}
|
||||
sleep 1
|
||||
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${dev}" | awk '$3 !~ /^$/ {print $2}')
|
||||
if [ "${mnt}" == "" ]; then
|
||||
break
|
||||
else
|
||||
echo "Retry ..."
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# mount src part
|
||||
WORK_DIR=${PWD}
|
||||
P1=${WORK_DIR}/boot
|
||||
P2=${WORK_DIR}/root
|
||||
mkdir -p $P1 $P2
|
||||
|
||||
echo "Mount [ ${LOOP_DEV}p1 ] -> [ ${P1} ] ... "
|
||||
mount -t vfat -o ro ${LOOP_DEV}p1 ${P1}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Mount p1 [ ${LOOP_DEV}p1 ] failed!"
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Mount [ ${LOOP_DEV}p2 ] -> [ ${P2} ] ... "
|
||||
ZSTD_LEVEL=6
|
||||
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Mount p2 [ ${LOOP_DEV}p2 ] failed!"
|
||||
umount -f ${P1}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Prepare the dockerman config file
|
||||
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
|
||||
|
||||
flg=0
|
||||
# get current docker data root
|
||||
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
|
||||
if [ "${data_root}" == "" ]; then
|
||||
flg=1
|
||||
# get current config from /etc/docker/daemon.json
|
||||
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
|
||||
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
|
||||
|
||||
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
|
||||
[ "${bip}" == "null" ] && bip="172.31.0.1/24"
|
||||
|
||||
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
|
||||
[ "${log_level}" == "null" ] && log_level="warn"
|
||||
|
||||
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
|
||||
[ "${_iptables}" == "null" ] && _iptables="true"
|
||||
|
||||
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${data_root}" == "" ]; then
|
||||
data_root="/opt/docker/" # the default data root
|
||||
fi
|
||||
|
||||
if ! uci get dockerd.globals >/dev/null 2>&1; then
|
||||
uci set dockerd.globals='globals'
|
||||
uci commit
|
||||
fi
|
||||
|
||||
# delete alter config , use inner config
|
||||
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
|
||||
uci delete dockerd.globals.alt_config_file
|
||||
uci commit
|
||||
fi
|
||||
|
||||
if [ ${flg} -eq 1 ]; then
|
||||
uci set dockerd.globals.data_root=${data_root}
|
||||
[ "${bip}" != "" ] && uci set dockerd.globals.bip=${bip}
|
||||
[ "${log_level}" != "" ] && uci set dockerd.globals.log_level=${log_level}
|
||||
[ "${_iptables}" != "" ] && uci set dockerd.globals.iptables=${_iptables}
|
||||
if [ "${registry_mirrors}" != "" ]; then
|
||||
for reg in ${registry_mirrors}; do
|
||||
uci add_list dockerd.globals.registry_mirrors=${reg}
|
||||
done
|
||||
fi
|
||||
uci set dockerd.globals.auto_start='1'
|
||||
uci commit
|
||||
fi
|
||||
fi
|
||||
|
||||
#update version prompt
|
||||
source /boot/uEnv.txt 2>/dev/null
|
||||
CUR_FDTFILE=${FDT}
|
||||
echo -e "FDT Value [ ${CUR_FDTFILE} ]"
|
||||
cp /boot/uEnv.txt /tmp/uEnv.txt && sync
|
||||
|
||||
K510="1"
|
||||
[[ "$(hexdump -n 15 -x "${P1}/zImage" 2>/dev/null | head -n 1 | awk '{print $7}')" == "0108" ]] && K510="0"
|
||||
echo -e "K510 [ ${K510} ]"
|
||||
|
||||
# flippy-openwrt-release info
|
||||
UBOOT_OVERLOAD=""
|
||||
MAINLINE_UBOOT=""
|
||||
ANDROID_UBOOT=""
|
||||
env_openwrt_file=""
|
||||
|
||||
if [ -f "${P2}/etc/flippy-openwrt-release" ]; then
|
||||
env_openwrt_file="${P2}/etc/flippy-openwrt-release"
|
||||
elif [ -f "/etc/flippy-openwrt-release" ]; then
|
||||
env_openwrt_file="/etc/flippy-openwrt-release"
|
||||
else
|
||||
env_openwrt_file=""
|
||||
fi
|
||||
|
||||
if [ -n "${env_openwrt_file}" ]; then
|
||||
source "${env_openwrt_file}" 2>/dev/null
|
||||
# Update the parameters used
|
||||
UBOOT_OVERLOAD=${UBOOT_OVERLOAD}
|
||||
MAINLINE_UBOOT=${MAINLINE_UBOOT}
|
||||
ANDROID_UBOOT=${ANDROID_UBOOT}
|
||||
|
||||
# Unused parameters
|
||||
FDTFILE=${FDTFILE}
|
||||
U_BOOT_EXT=${U_BOOT_EXT}
|
||||
KERNEL_VERSION=${KERNEL_VERSION}
|
||||
SOC=${SOC}
|
||||
fi
|
||||
|
||||
#format NEW_ROOT
|
||||
echo "umount [ ${NEW_ROOT_MP} ]"
|
||||
umount -f "${NEW_ROOT_MP}"
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
echo "Umount [ ${NEW_ROOT_MP} ] failed, Please restart and try again!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check and fix partition
|
||||
function check_and_fix_partition() {
|
||||
local target_dev_name=${1} # mmcblk2
|
||||
local target_pt_name=${2} # p2
|
||||
local target_pt_idx=${3} # 2
|
||||
local safe_pt_begin_mb=${4} # 800
|
||||
local safe_pt_begin_byte=$((${safe_pt_begin_mb} * 1024 * 1024))
|
||||
|
||||
local cur_pt_begin_sector=$(fdisk -l /dev/${target_dev_name} | grep ${target_dev_name}${target_pt_name} | awk '{printf $2}')
|
||||
local cur_pt_begin_mb=$((${cur_pt_begin_sector} * 512 / 1024 / 1024))
|
||||
|
||||
if [ ${cur_pt_begin_mb} -ge ${safe_pt_begin_mb} ]; then
|
||||
# check pass
|
||||
return
|
||||
fi
|
||||
|
||||
local cur_pt_end_sector=$(fdisk -l /dev/${target_dev_name} | grep ${target_dev_name}${target_pt_name} | awk '{printf $3}')
|
||||
local cur_pt_end_byte=$(((${cur_pt_end_sector} + 1) * 512 - 1))
|
||||
|
||||
echo "Unsafe partition found, repairing ... "
|
||||
parted /dev/${target_dev_name} rm ${target_pt_idx} ||
|
||||
(
|
||||
error_msg "rm partion ${target_pt_idx} failed"
|
||||
)
|
||||
parted /dev/${target_dev_name} mkpart primary btrfs "${safe_pt_begin_byte}b" "${cur_pt_end_byte}b" ||
|
||||
(
|
||||
error_msg "create new partion ${target_pt_idx} failed"
|
||||
)
|
||||
echo "Partition repaired"
|
||||
}
|
||||
|
||||
# check if need fix partition
|
||||
if [ "${NEW_ROOT_NAME}" == "mmcblk2p2" ]; then
|
||||
if [ "${MYDEVICE_NAME}" == "Phicomm N1" ] || [ "${MYDEVICE_NAME}" == "Octopus Planet" ]; then
|
||||
# 最新研究结果:
|
||||
# Phicomm N1当采用官方 "天天链" 固件底包时,
|
||||
# 796MB开始的 12 字节在每次重启后会被 bootloader 覆写,
|
||||
# 因此把安全位置设定在800MB之后
|
||||
# The latest research results:
|
||||
# When Phicomm N1 uses the official "tian tian lian" firmware bottom package,
|
||||
# the 12 bytes starting from 796MB will be overwritten by bootloader after each reboot,
|
||||
# so the safe location is set after 800MB
|
||||
SAFE_PT_BEGIN_MB=800
|
||||
check_and_fix_partition "${EMMC_NAME}" "p2" 2 ${SAFE_PT_BEGIN_MB}
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Format [ ${NEW_ROOT_PATH} ]"
|
||||
NEW_ROOT_UUID=$(uuidgen)
|
||||
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} -m single ${NEW_ROOT_PATH}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Format [ ${NEW_ROOT_PATH} ] failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Mount [ ${NEW_ROOT_PATH} ] -> [ ${NEW_ROOT_MP} ]"
|
||||
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_PATH} ${NEW_ROOT_MP}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Mount [ ${NEW_ROOT_PATH} ] -> [ ${NEW_ROOT_MP} ] failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# begin copy rootfs
|
||||
cd ${NEW_ROOT_MP}
|
||||
echo "Start copying data, From [ ${P2} ] TO [ ${NEW_ROOT_MP} ] ..."
|
||||
ENTRYS=$(ls)
|
||||
for entry in ${ENTRYS}; do
|
||||
if [[ "${entry}" == "lost+found" ]]; then
|
||||
continue
|
||||
fi
|
||||
echo "Remove old [ ${entry} ] ... "
|
||||
rm -rf ${entry}
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
error_msg "failed."
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Create folder ... "
|
||||
btrfs subvolume create etc
|
||||
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
|
||||
ln -sf lib/ lib64
|
||||
ln -sf tmp/ var
|
||||
sync
|
||||
|
||||
COPY_SRC="root etc bin sbin lib opt usr www"
|
||||
echo "Copy data begin ... "
|
||||
for src in ${COPY_SRC}; do
|
||||
echo "Copy [ ${src} ] ... "
|
||||
(cd ${P2} && tar cf - ${src}) | tar xf -
|
||||
sync
|
||||
done
|
||||
|
||||
# if not backup, then force rewrite the etc/docker/daemon.json
|
||||
if [ "${BR_FLAG}" -eq 0 ]; then
|
||||
cat >./etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"bip": "172.31.0.1/24",
|
||||
"data-root": "${DOCKER_ROOT}",
|
||||
"log-level": "warn",
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "5"
|
||||
},
|
||||
"registry-mirrors": [
|
||||
"https://mirror.baidubce.com/",
|
||||
"https://hub-mirror.c.163.com"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >./etc/fstab <<EOF
|
||||
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
|
||||
LABEL=${LB_PRE}BOOT /boot vfat defaults 0 2
|
||||
#tmpfs /tmp tmpfs defaults,nosuid 0 0
|
||||
EOF
|
||||
|
||||
cat >./etc/config/fstab <<EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '1'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '0'
|
||||
|
||||
config mount
|
||||
option target '/rom'
|
||||
option uuid '${NEW_ROOT_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'btrfs'
|
||||
option options 'compress=zstd:${ZSTD_LEVEL}'
|
||||
|
||||
config mount
|
||||
option target '/boot'
|
||||
option label '${LB_PRE}BOOT'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'vfat'
|
||||
|
||||
EOF
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
sync
|
||||
|
||||
echo "Create initial etc snapshot -> .snapshots/etc-000"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-000
|
||||
sync
|
||||
|
||||
[ -d /mnt/${EMMC_NAME}${PARTITION_NAME}4/docker ] || mkdir -p /mnt/${EMMC_NAME}${PARTITION_NAME}4/docker
|
||||
rm -rf opt/docker && ln -sf /mnt/${EMMC_NAME}${PARTITION_NAME}4/docker/ opt/docker
|
||||
|
||||
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
|
||||
[ -d /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome/data ] || mkdir -p /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome/data
|
||||
if [ ! -L /usr/bin/AdGuardHome ]; then
|
||||
[ -d /usr/bin/AdGuardHome ] &&
|
||||
cp -a /usr/bin/AdGuardHome/* /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome/
|
||||
fi
|
||||
ln -sf /mnt/${EMMC_NAME}${PARTITION_NAME}4/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
|
||||
fi
|
||||
|
||||
#rm -f /mnt/${NEW_ROOT_NAME}/usr/sbin/openwrt-install-amlogic
|
||||
#rm -f /mnt/${NEW_ROOT_NAME}/usr/sbin/openwrt-update-amlogic
|
||||
rm -f /mnt/${NEW_ROOT_NAME}/root/install-to-emmc.sh
|
||||
sync
|
||||
echo "Copy data complete ..."
|
||||
|
||||
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
|
||||
if [[ "${BR_FLAG}" -eq "1" && -n "${BACKUP_LIST}" ]]; then
|
||||
echo -n "Start restoring configuration files ... "
|
||||
(
|
||||
cd /
|
||||
eval tar czf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
)
|
||||
tar xzf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz
|
||||
|
||||
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
|
||||
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
|
||||
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync 2>/dev/null
|
||||
|
||||
# Restore fstab
|
||||
cp -f .snapshots/etc-000/fstab ./etc/fstab
|
||||
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
|
||||
# 还原 luci
|
||||
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
|
||||
# 还原/etc/config/rpcd
|
||||
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
|
||||
|
||||
sync
|
||||
echo "Restore configuration information complete."
|
||||
fi
|
||||
|
||||
echo "Modify the configuration file ... "
|
||||
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
|
||||
rm -rf "./opt/docker" && ln -sf "/mnt/${EMMC_NAME}${PARTITION_NAME}4/docker" "./opt/docker"
|
||||
rm -f ./etc/bench.log
|
||||
cat >>./etc/crontabs/root <<EOF
|
||||
37 5 * * * /etc/coremark.sh
|
||||
EOF
|
||||
|
||||
sed -e 's/ttyAMA0/ttyAML0/' -i ./etc/inittab
|
||||
sed -e 's/ttyS0/tty0/' -i ./etc/inittab
|
||||
sss=$(date +%s)
|
||||
ddd=$((sss / 86400))
|
||||
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
|
||||
# Fix the problem of repeatedly adding amule entries after each upgrade
|
||||
sed -e "/amule:x:/d" -i ./etc/shadow
|
||||
# Fix the problem of repeatedly adding sshd entries after each upgrade of dropbear
|
||||
sed -e "/sshd:x:/d" -i ./etc/shadow
|
||||
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
|
||||
echo "sshd:x:22:sshd" >>./etc/group
|
||||
fi
|
||||
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
|
||||
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
|
||||
fi
|
||||
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
|
||||
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
|
||||
fi
|
||||
|
||||
if [ "${BR_FLAG}" -eq "1" ]; then
|
||||
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
|
||||
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
|
||||
fi
|
||||
sync
|
||||
fi
|
||||
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
|
||||
rm -f ./etc/part_size ./etc/first_run.sh
|
||||
if [ -x ./usr/sbin/balethirq.pl ]; then
|
||||
if grep "balethirq.pl" "./etc/rc.local"; then
|
||||
echo "balance irq is enabled"
|
||||
else
|
||||
echo "enable balance irq"
|
||||
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
|
||||
fi
|
||||
fi
|
||||
|
||||
mv ./etc/rc.local ./etc/rc.local.orig
|
||||
cat >"./etc/rc.local" <<EOF
|
||||
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
|
||||
/etc/init.d/dockerd enable
|
||||
/etc/init.d/dockerd start
|
||||
fi
|
||||
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
|
||||
/etc/init.d/dockerman enable
|
||||
/etc/init.d/dockerman start
|
||||
fi
|
||||
mv /etc/rc.local.orig /etc/rc.local
|
||||
chmod 755 /etc/rc.local
|
||||
exec /etc/rc.local
|
||||
exit
|
||||
EOF
|
||||
chmod 755 ./etc/rc.local*
|
||||
|
||||
#Mainline U-BOOT detection
|
||||
FLASH_MAINLINE_UBOOT=0
|
||||
if [[ -n "${MAINLINE_UBOOT}" && -f "${P2}${MAINLINE_UBOOT}" ]]; then
|
||||
cat <<EOF
|
||||
----------------------------------------------------------------------------------
|
||||
Found an available mainline bootloader (Mainline u-boot), you can flash into EMMC.
|
||||
----------------------------------------------------------------------------------
|
||||
EOF
|
||||
while :; do
|
||||
if [[ "${AUTO_MAINLINE_UBOOT}" == "yes" ]]; then
|
||||
if [[ "${K510}" -eq "1" ]]; then
|
||||
yn="y"
|
||||
else
|
||||
yn="n"
|
||||
fi
|
||||
elif [[ "${AUTO_MAINLINE_UBOOT}" == "no" ]]; then
|
||||
yn="n"
|
||||
else
|
||||
read -p "Please choose whether to write the mainline bootloader to EMMC? y/n " yn
|
||||
fi
|
||||
|
||||
case ${yn} in
|
||||
y | Y)
|
||||
FLASH_MAINLINE_UBOOT=1
|
||||
break
|
||||
;;
|
||||
n | N)
|
||||
FLASH_MAINLINE_UBOOT=0
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${FLASH_MAINLINE_UBOOT}" -eq "1" ]]; then
|
||||
echo -e "Write Mainline bootloader: [ ${MAINLINE_UBOOT} ]"
|
||||
dd if=${P2}${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
|
||||
dd if=${P2}${MAINLINE_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
|
||||
elif [[ -n "${ANDROID_UBOOT}" && -f "${P2}${ANDROID_UBOOT}" ]]; then
|
||||
echo -e "Write Android bootloader: [ ${ANDROID_UBOOT} ]"
|
||||
dd if=${P2}${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=1 count=444 conv=fsync
|
||||
dd if=${P2}${ANDROID_UBOOT} of=/dev/${EMMC_NAME} bs=512 skip=1 seek=1 conv=fsync
|
||||
else
|
||||
echo "Did not change the original bootloader."
|
||||
fi
|
||||
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
|
||||
echo "Create etc snapshot -> .snapshots/etc-001"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-001
|
||||
|
||||
cd ${WORK_DIR}
|
||||
|
||||
echo "Change the label of ${BOOT_PATH} ... "
|
||||
fatlabel ${BOOT_PATH} "${LB_PRE}BOOT"
|
||||
echo "Start copying data, from [ ${P1} ] to [ /boot ] ..."
|
||||
cd /boot
|
||||
echo "Delete the old boot file ..."
|
||||
rm -rf * && sync
|
||||
|
||||
echo "Copy the new boot file ... "
|
||||
(cd ${P1} && tar cf - .) | tar xf - 2>/dev/null
|
||||
sync
|
||||
|
||||
if [ -f ${P1}/uInitrd ]; then
|
||||
i=1
|
||||
max_try=10
|
||||
while [ "${i}" -le "${max_try}" ]; do
|
||||
uInitrd_original=$(md5sum ${P1}/uInitrd | awk '{print $1}')
|
||||
uInitrd_new=$(md5sum uInitrd | awk '{print $1}')
|
||||
if [ "${uInitrd_original}" = "${uInitrd_new}" ]; then
|
||||
break
|
||||
else
|
||||
rm -f uInitrd && sync
|
||||
cp -f ${P1}/uInitrd uInitrd 2>/dev/null && sync
|
||||
let i++
|
||||
continue
|
||||
fi
|
||||
done
|
||||
[ "${i}" -eq "10" ] && error_msg "uInitrd file copy failed."
|
||||
else
|
||||
echo "uInitrd file is missing."
|
||||
fi
|
||||
|
||||
if [ -f ${P1}/zImage ]; then
|
||||
i=1
|
||||
max_try=10
|
||||
while [ "${i}" -le "${max_try}" ]; do
|
||||
zImage_original=$(md5sum ${P1}/zImage | awk '{print $1}')
|
||||
zImage_new=$(md5sum zImage | awk '{print $1}')
|
||||
if [ "${zImage_original}" = "${zImage_new}" ]; then
|
||||
break
|
||||
else
|
||||
rm -f zImage && sync
|
||||
cp -f ${P1}/zImage zImage 2>/dev/null && sync
|
||||
let i++
|
||||
continue
|
||||
fi
|
||||
done
|
||||
[ "${i}" -eq "10" ] && error_msg "zImage file copy failed."
|
||||
else
|
||||
error_msg "zImage file is missing."
|
||||
fi
|
||||
|
||||
if [ ${ROOT_DISK_TYPE} == "EMMC" ]; then
|
||||
rm -f s905_autoscript* aml_autoscript*
|
||||
mv -f boot-emmc.ini boot.ini
|
||||
mv -f boot-emmc.cmd boot.cmd
|
||||
mv -f boot-emmc.scr boot.scr
|
||||
fi
|
||||
|
||||
if [ "${K510}" -eq "1" ]; then
|
||||
if [ -f "u-boot.ext" ]; then
|
||||
cp -vf u-boot.ext u-boot.emmc
|
||||
elif [ -f ${P1}/${UBOOT_OVERLOAD} ]; then
|
||||
cp -vf ${P1}/${UBOOT_OVERLOAD} ${UBOOT_OVERLOAD}
|
||||
cp -vf ${P1}/${UBOOT_OVERLOAD} u-boot.ext
|
||||
cp -vf ${P1}/${UBOOT_OVERLOAD} u-boot.emmc
|
||||
chmod +x u-boot*
|
||||
fi
|
||||
else
|
||||
rm -f u-boot.ext 2>/dev/null
|
||||
rm -f u-boot.emmc 2>/dev/null
|
||||
fi
|
||||
|
||||
sync
|
||||
|
||||
echo "Update boot parameters ... "
|
||||
if [ -f /tmp/uEnv.txt ]; then
|
||||
lines=$(wc -l </tmp/uEnv.txt)
|
||||
lines=$((lines - 1))
|
||||
head -n $lines /tmp/uEnv.txt >uEnv.txt
|
||||
cat >>uEnv.txt <<EOF
|
||||
APPEND=root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
|
||||
EOF
|
||||
else
|
||||
cat >uEnv.txt <<EOF
|
||||
LINUX=/zImage
|
||||
INITRD=/uInitrd
|
||||
FDT=${CUR_FDTFILE}
|
||||
APPEND=root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyAML0,115200n8 console=tty0 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
|
||||
EOF
|
||||
fi
|
||||
sync
|
||||
|
||||
# Replace the UUID for extlinux/extlinux.conf if it exists
|
||||
[[ -f "extlinux/extlinux.conf" ]] && {
|
||||
sed -i -E "s|UUID=[^ ]*|UUID=${NEW_ROOT_UUID}|" extlinux/extlinux.conf 2>/dev/null
|
||||
}
|
||||
|
||||
cd $WORK_DIR
|
||||
umount -f ${P1} ${P2} 2>/dev/null
|
||||
losetup -D 2>/dev/null
|
||||
rm -rf ${P1} ${P2} 2>/dev/null
|
||||
rm -f ${IMG_NAME} 2>/dev/null
|
||||
rm -f sha256sums 2>/dev/null
|
||||
sync
|
||||
wait
|
||||
|
||||
echo "Successfully updated, automatic restarting..."
|
||||
sleep 3
|
||||
reboot
|
||||
exit 0
|
||||
@@ -0,0 +1,674 @@
|
||||
#!/bin/bash
|
||||
#======================================================================================
|
||||
# Function: Update the QEMU AARCH64 KVM vitual machine openwrt firmware
|
||||
# Copyright (C) 2022-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2022-- https://github.com/ophub
|
||||
#======================================================================================
|
||||
#
|
||||
# The script supports directly setting parameters for update, skipping interactive selection
|
||||
# openwrt-update-amlogic ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG} ${WORK_DIR}
|
||||
# E.g: openwrt-update-kvm openwrt_qemu-aarch64.img.gz no restore /mnt/vda4
|
||||
# E.g: openwrt-update-kvm openwrt_qemu-aarch64.img.gz no no-restore /mnt/data
|
||||
|
||||
# You can also execute the script directly, and interactively select related functions
|
||||
# E.g: openwrt-update-kvm
|
||||
#
|
||||
#======================================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "[ERROR] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the /boot file system
|
||||
get_boot_partition_name() {
|
||||
local paths="/boot"
|
||||
local partition_name
|
||||
|
||||
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition message of the root file system
|
||||
get_root_partition_msg() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
|
||||
[[ -n "${partition_msg}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
|
||||
echo "${partition_msg}"
|
||||
}
|
||||
|
||||
# Receive one-key command related parameters
|
||||
IMG_NAME="${1}"
|
||||
AUTO_MAINLINE_UBOOT="${2}"
|
||||
BACKUP_RESTORE_CONFIG="${3}"
|
||||
WORK_DIR="${4}"
|
||||
|
||||
# Check the necessary dependencies
|
||||
DEPENDS="lsblk uuidgen grep awk btrfs mkfs.fat mkfs.btrfs md5sum fatlabel jq"
|
||||
echo "Check the necessary dependencies..."
|
||||
for dep in ${DEPENDS}; do
|
||||
WITCH=$(busybox which ${dep})
|
||||
if [ "${WITCH}" == "" ]; then
|
||||
error_msg "Dependent command: ${dep} does not exist, upgrade cannot be performed!"
|
||||
else
|
||||
echo "${dep} path: ${WITCH}"
|
||||
fi
|
||||
done
|
||||
echo "Check passed"
|
||||
|
||||
# Current device model
|
||||
source /etc/flippy-openwrt-release
|
||||
if [[ -z "${PLATFORM}" ]]; then
|
||||
error_msg "The platform is empty."
|
||||
elif [[ "${PLATFORM}" != "qemu-aarch64" ]]; then
|
||||
error_msg "The platform is missing, only support qemu-aarch64."
|
||||
else
|
||||
echo -e "Current platform: [ ${PLATFORM} ]"
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# Check and repair partition mount points
|
||||
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
|
||||
echo -e "Partition mount point error, start repairing..."
|
||||
openwrt-backup -g
|
||||
}
|
||||
|
||||
# Find the partition where root is located
|
||||
# vda2 or vda3
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports sd?? hd?? vd??
|
||||
case ${ROOT_PTNAME} in
|
||||
[hsv]d[a-z][1-4])
|
||||
DISK_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
|
||||
PART_PRESTR=""
|
||||
LABEL_PRESTR=""
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
function get_docker_root {
|
||||
local data_root
|
||||
if [[ -f /etc/config/dockerd ]]; then
|
||||
data_root=$(uci get dockerd.globals.data_root)
|
||||
fi
|
||||
if [[ -z "${data_root}" ]] && [[ -f /etc/docker/daemon.json ]]; then
|
||||
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
|
||||
fi
|
||||
echo "$data_root"
|
||||
}
|
||||
DOCKER_ROOT=$(get_docker_root)
|
||||
|
||||
if [[ -z "${WORK_DIR}" ]]; then
|
||||
WORK_DIR="/mnt/${DISK_NAME}${PART_PRESTR}4/"
|
||||
fi
|
||||
if [[ ! -d "${WORK_DIR}" ]]; then
|
||||
error_msg "the work directory is not exists. [ ${WORK_DIR} ]"
|
||||
fi
|
||||
|
||||
cd "${WORK_DIR}"
|
||||
if [[ -d "/tmp/upload" ]] && [[ -f "/tmp/upload/*img*" ]]; then
|
||||
mv -f /tmp/upload/*img* .
|
||||
if [[ $? -ne 0 ]]; then
|
||||
error_msg "move file failed."
|
||||
fi
|
||||
fi
|
||||
sync
|
||||
|
||||
if [[ "${IMG_NAME}" == *.img ]]; then
|
||||
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
xz_file=$(ls *.img.xz | head -n 1)
|
||||
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
|
||||
xz -d ${xz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.img.gz | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
gzip -df ${gz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.7z | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
bsdtar -xmf ${gz_file} 2>/dev/null
|
||||
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
zip_file=$(ls *.zip | head -n 1)
|
||||
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
|
||||
unzip -o ${zip_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
else
|
||||
echo -e "Please upload or specify the update openwrt firmware file."
|
||||
#echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
|
||||
echo -e "Specify method: Place the openwrt firmware file in [ ${WORK_DIR} ]"
|
||||
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
|
||||
echo -e "After upload the openwrt firmware file, run again."
|
||||
exit 1
|
||||
fi
|
||||
sync
|
||||
|
||||
# check file
|
||||
if [ ! -f "${IMG_NAME}" ]; then
|
||||
error_msg "No update file found."
|
||||
else
|
||||
echo "Start update from [ ${IMG_NAME} ]"
|
||||
fi
|
||||
|
||||
# find efi partition
|
||||
EFI_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot\/efi$/ {print $0}')
|
||||
if [ "${EFI_PART_MSG}" == "" ]; then
|
||||
error_msg "The EFI partition does not exist, so the update cannot be continued!"
|
||||
fi
|
||||
EFI_NAME=$(echo $EFI_PART_MSG | awk '{print $1}')
|
||||
EFI_DEV=$(echo $EFI_PART_MSG | awk '{print $2}')
|
||||
EFI_UUID=$(echo $EFI_PART_MSG | awk '{print $4}')
|
||||
|
||||
BR_FLAG=1
|
||||
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
|
||||
BR_FLAG=1
|
||||
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
|
||||
BR_FLAG=0
|
||||
else
|
||||
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
|
||||
read yn
|
||||
case $yn in
|
||||
n* | N*) BR_FLAG=0 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# find root partition
|
||||
ROOT_PART_MSG="$(get_root_partition_msg)"
|
||||
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
|
||||
ROOT_DEV=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
|
||||
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
|
||||
|
||||
case ${ROOT_NAME} in
|
||||
${DISK_NAME}${PART_PRESTR}2)
|
||||
NEW_ROOT_NAME="${DISK_NAME}${PART_PRESTR}3"
|
||||
NEW_ROOT_LABEL="${LABEL_PRESTR}ROOTFS2"
|
||||
;;
|
||||
${DISK_NAME}${PART_PRESTR}3)
|
||||
NEW_ROOT_NAME="${DISK_NAME}${PART_PRESTR}2"
|
||||
NEW_ROOT_LABEL="${LABEL_PRESTR}ROOTFS1"
|
||||
;;
|
||||
*)
|
||||
error_msg "ROOTFS The partition location is incorrect, so the update cannot continue!"
|
||||
;;
|
||||
esac
|
||||
echo "NEW_ROOT_NAME: [ ${NEW_ROOT_NAME} ]"
|
||||
|
||||
# find new root partition
|
||||
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
|
||||
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
|
||||
error_msg "The new ROOTFS partition does not exist, so the update cannot continue!"
|
||||
fi
|
||||
NEW_ROOT_NAME=$(echo $NEW_ROOT_PART_MSG | awk '{print $1}')
|
||||
NEW_ROOT_DEV=$(echo $NEW_ROOT_PART_MSG | awk '{print $2}')
|
||||
NEW_ROOT_UUID=$(echo $NEW_ROOT_PART_MSG | awk '{print $4}')
|
||||
NEW_ROOT_MOUNTPOINT=$(echo $NEW_ROOT_PART_MSG | awk '{print $5}')
|
||||
echo "NEW_ROOT_MOUNTPOINT: [ ${NEW_ROOT_MOUNTPOINT} ]"
|
||||
|
||||
# losetup
|
||||
losetup -f -P $IMG_NAME
|
||||
if [ $? -eq 0 ]; then
|
||||
LOOP_DEV=$(losetup | grep "$IMG_NAME" | awk '{print $1}')
|
||||
if [ "$LOOP_DEV" == "" ]; then
|
||||
error_msg "loop device not found!"
|
||||
fi
|
||||
else
|
||||
error_msg "losetup [ $IMG_FILE ] failed!"
|
||||
fi
|
||||
|
||||
# fix loopdev issue in kernel 5.19
|
||||
function fix_loopdev() {
|
||||
local parentdev=${1##*/}
|
||||
if [ ! -d /sys/block/${parentdev} ]; then
|
||||
return
|
||||
fi
|
||||
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
|
||||
for subdev in $subdevs; do
|
||||
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
|
||||
return
|
||||
elif [ -b /dev/${sub_dev} ]; then
|
||||
continue
|
||||
fi
|
||||
source /sys/block/${parentdev}/${subdev}/uevent
|
||||
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
|
||||
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
|
||||
done
|
||||
}
|
||||
fix_loopdev ${LOOP_DEV}
|
||||
|
||||
WAIT=3
|
||||
echo "The loopdev is [ $LOOP_DEV ], wait [ ${WAIT} ] seconds. "
|
||||
while [ $WAIT -ge 1 ]; do
|
||||
sleep 1
|
||||
WAIT=$((WAIT - 1))
|
||||
done
|
||||
|
||||
# umount loop devices (openwrt will auto mount some partition)
|
||||
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$LOOP_DEV" | awk '$3 !~ /^$/ {print $2}')
|
||||
for dev in $MOUNTED_DEVS; do
|
||||
while :; do
|
||||
echo "umount [ $dev ] ... "
|
||||
umount -f $dev
|
||||
sleep 1
|
||||
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "$dev" | awk '$3 !~ /^$/ {print $2}')
|
||||
if [ "$mnt" == "" ]; then
|
||||
break
|
||||
else
|
||||
echo "Retry ..."
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# mount src part
|
||||
P1=${WORK_DIR}/efi
|
||||
P2=${WORK_DIR}/root
|
||||
mkdir -p $P1 $P2
|
||||
|
||||
echo "Mount [ ${LOOP_DEV}p1 ] -> [ ${P1} ] ... "
|
||||
mount -t vfat -o ro ${LOOP_DEV}p1 ${P1}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Mount p1 [ ${LOOP_DEV}p1 ] failed!"
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Mount [ ${LOOP_DEV}p2 ] -> [ ${P2} ] ... "
|
||||
ZSTD_LEVEL="6"
|
||||
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Mount p2 [ ${LOOP_DEV}p2 ] failed!"
|
||||
umount -f ${P1}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Prepare the dockerman config file
|
||||
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
|
||||
|
||||
flg=0
|
||||
# get current docker data root
|
||||
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
|
||||
if [ "$data_root" == "" ]; then
|
||||
flg=1
|
||||
# get current config from /etc/docker/daemon.json
|
||||
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
|
||||
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
|
||||
|
||||
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
|
||||
[ "$bip" == "null" ] && bip="172.31.0.1/24"
|
||||
|
||||
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
|
||||
[ "$log_level" == "null" ] && log_level="warn"
|
||||
|
||||
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
|
||||
[ "$_iptables" == "null" ] && _iptables="true"
|
||||
|
||||
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$data_root" == "" ]; then
|
||||
data_root="/opt/docker/" # the default data root
|
||||
fi
|
||||
|
||||
if ! uci get dockerd.globals >/dev/null 2>&1; then
|
||||
uci set dockerd.globals='globals'
|
||||
uci commit
|
||||
fi
|
||||
|
||||
# delete alter config , use inner config
|
||||
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
|
||||
uci delete dockerd.globals.alt_config_file
|
||||
uci commit
|
||||
fi
|
||||
|
||||
if [ $flg -eq 1 ]; then
|
||||
uci set dockerd.globals.data_root=$data_root
|
||||
[ "$bip" != "" ] && uci set dockerd.globals.bip=$bip
|
||||
[ "$log_level" != "" ] && uci set dockerd.globals.log_level=$log_level
|
||||
[ "$_iptables" != "" ] && uci set dockerd.globals.iptables=$_iptables
|
||||
if [ "$registry_mirrors" != "" ]; then
|
||||
for reg in $registry_mirrors; do
|
||||
uci add_list dockerd.globals.registry_mirrors=$reg
|
||||
done
|
||||
fi
|
||||
uci set dockerd.globals.auto_start='1'
|
||||
uci commit
|
||||
fi
|
||||
fi
|
||||
|
||||
#format NEW_ROOT
|
||||
echo "umount [ ${NEW_ROOT_MOUNTPOINT} ]"
|
||||
umount -f "${NEW_ROOT_MOUNTPOINT}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Umount [ ${NEW_ROOT_MOUNTPOINT} ] failed, Please restart and try again!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Format [ ${NEW_ROOT_DEV} ]"
|
||||
NEW_ROOT_UUID=$(uuidgen)
|
||||
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} ${NEW_ROOT_DEV}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Format [ ${NEW_ROOT_DEV} ] failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Mount [ ${NEW_ROOT_DEV} ] -> [ ${NEW_ROOT_MOUNTPOINT} ]"
|
||||
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_DEV} ${NEW_ROOT_MOUNTPOINT}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Mount [ ${NEW_ROOT_DEV} ] -> [ ${NEW_ROOT_MOUNTPOINT} ] failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# begin copy rootfs
|
||||
cd ${NEW_ROOT_MOUNTPOINT}
|
||||
echo "Start copying data, From [ ${P2} ] TO [ ${NEW_ROOT_MOUNTPOINT} ] ..."
|
||||
ENTRYS=$(ls)
|
||||
for entry in $ENTRYS; do
|
||||
if [ "$entry" == "lost+found" ]; then
|
||||
continue
|
||||
fi
|
||||
echo "Remove old [ $entry ] ... "
|
||||
rm -rf $entry
|
||||
if [ $? -ne 0 ]; then
|
||||
error_msg "failed."
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Create folder ... "
|
||||
btrfs subvolume create etc
|
||||
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
|
||||
ln -sf lib/ lib64
|
||||
ln -sf tmp/ var
|
||||
sync
|
||||
|
||||
COPY_SRC="boot root etc bin sbin lib opt usr www"
|
||||
echo "Copy data begin ... "
|
||||
for src in $COPY_SRC; do
|
||||
echo "Copy [ $src ] ... "
|
||||
(cd ${P2} && tar cf - $src) | tar xf -
|
||||
sync
|
||||
done
|
||||
|
||||
# if not backup, then force rewrite the etc/docker/daemon.json
|
||||
if [ "${BR_FLAG}" -eq 0 ]; then
|
||||
cat >./etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"bip": "172.31.0.1/24",
|
||||
"data-root": "${DOCKER_ROOT}",
|
||||
"log-level": "warn",
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "5"
|
||||
},
|
||||
"registry-mirrors": [
|
||||
"https://mirror.baidubce.com/",
|
||||
"https://hub-mirror.c.163.com"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >./etc/fstab <<EOF
|
||||
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
|
||||
LABEL=EFI /boot/efi vfat defaults 0 2
|
||||
#tmpfs /tmp tmpfs defaults,nosuid 0 0
|
||||
EOF
|
||||
|
||||
cat >./etc/config/fstab <<EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '1'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '0'
|
||||
|
||||
config mount
|
||||
option target '/rom'
|
||||
option uuid '${NEW_ROOT_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'btrfs'
|
||||
option options 'compress=zstd:${ZSTD_LEVEL}'
|
||||
|
||||
config mount
|
||||
option target '/boot/efi'
|
||||
option label 'EFI'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'vfat'
|
||||
|
||||
EOF
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
sync
|
||||
|
||||
echo "Create initial etc snapshot -> .snapshots/etc-000"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-000
|
||||
sync
|
||||
|
||||
[ -d /mnt/${DISK_NAME}${PART_PRESTR}4/docker ] || mkdir -p /mnt/${DISK_NAME}${PART_PRESTR}4/docker
|
||||
rm -rf opt/docker && ln -sf /mnt/${DISK_NAME}${PART_PRESTR}4/docker/ opt/docker
|
||||
|
||||
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
|
||||
[ -d /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome/data ] || mkdir -p /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome/data
|
||||
if [ ! -L /usr/bin/AdGuardHome ]; then
|
||||
[ -d /usr/bin/AdGuardHome ] &&
|
||||
cp -a /usr/bin/AdGuardHome/* /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome/
|
||||
fi
|
||||
ln -sf /mnt/${DISK_NAME}${PART_PRESTR}4/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
|
||||
fi
|
||||
sync
|
||||
echo "Copy data complete ..."
|
||||
|
||||
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
|
||||
if [[ "${BR_FLAG}" -eq "1" && -n "${BACKUP_LIST}" ]]; then
|
||||
echo -n "Start restoring configuration files ... "
|
||||
(
|
||||
cd /
|
||||
eval tar czf ${NEW_ROOT_MOUNTPOINT}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
)
|
||||
tar xzf ${NEW_ROOT_MOUNTPOINT}/.reserved/openwrt_config.tar.gz
|
||||
|
||||
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
|
||||
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
|
||||
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync 2>/dev/null
|
||||
|
||||
# Restore fstab
|
||||
cp -f .snapshots/etc-000/fstab ./etc/fstab
|
||||
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
|
||||
# 还原 luci
|
||||
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
|
||||
# 还原/etc/config/rpcd
|
||||
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
|
||||
|
||||
sync
|
||||
echo "Restore configuration information complete."
|
||||
fi
|
||||
|
||||
echo "Modify the configuration file ... "
|
||||
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
|
||||
rm -rf "./opt/docker" && ln -sf "/mnt/${DISK_NAME}${PART_PRESTR}4/docker" "./opt/docker"
|
||||
rm -f ./etc/bench.log
|
||||
cat >>./etc/crontabs/root <<EOF
|
||||
37 5 * * * /etc/coremark.sh
|
||||
EOF
|
||||
|
||||
sss=$(date +%s)
|
||||
ddd=$((sss / 86400))
|
||||
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
|
||||
# Fix the problem of repeatedly adding amule entries after each upgrade
|
||||
sed -e "/amule:x:/d" -i ./etc/shadow
|
||||
# Fix the problem of repeatedly adding sshd entries after each upgrade of dropbear
|
||||
sed -e "/sshd:x:/d" -i ./etc/shadow
|
||||
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
|
||||
echo "sshd:x:22:sshd" >>./etc/group
|
||||
fi
|
||||
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
|
||||
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
|
||||
fi
|
||||
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
|
||||
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
|
||||
fi
|
||||
|
||||
if [ "${BR_FLAG}" -eq "1" ]; then
|
||||
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
|
||||
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
|
||||
fi
|
||||
sync
|
||||
fi
|
||||
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
|
||||
rm -f ./etc/part_size ./etc/first_run.sh
|
||||
if [ -x ./usr/sbin/balethirq.pl ]; then
|
||||
if grep "balethirq.pl" "./etc/rc.local"; then
|
||||
echo "balance irq is enabled"
|
||||
else
|
||||
echo "enable balance irq"
|
||||
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
|
||||
fi
|
||||
fi
|
||||
|
||||
mv ./etc/rc.local ./etc/rc.local.orig
|
||||
cat >"./etc/rc.local" <<EOF
|
||||
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
|
||||
/etc/init.d/dockerd enable
|
||||
/etc/init.d/dockerd start
|
||||
fi
|
||||
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
|
||||
/etc/init.d/dockerman enable
|
||||
/etc/init.d/dockerman start
|
||||
fi
|
||||
mv /etc/rc.local.orig /etc/rc.local
|
||||
chmod 755 /etc/rc.local
|
||||
exec /etc/rc.local
|
||||
exit
|
||||
EOF
|
||||
chmod 755 ./etc/rc.local*
|
||||
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
|
||||
echo "Create etc snapshot -> .snapshots/etc-001"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-001
|
||||
|
||||
cd ${WORK_DIR}
|
||||
|
||||
echo "Copy efi files ..."
|
||||
fatlabel ${EFI_DEV} "EFI"
|
||||
cd /boot/efi
|
||||
mv ./EFI/BOOT/grub.cfg /tmp/grub.cfg.prev
|
||||
rm -rf *
|
||||
cp -a ${P1}/* .
|
||||
# 如果想启动上一个版本的openwrt,可以把 /boot/efi/EFI/BOOT/grub.cfg.prev 复制成 /boot/efi/EFI/BOOT/grub.cfg
|
||||
mv /tmp/grub.cfg.prev ./EFI/BOOT/
|
||||
|
||||
echo "Modify efi configuration ... "
|
||||
cd /boot/efi/EFI/BOOT
|
||||
cat >grub.cfg <<EOF
|
||||
echo "search fs_uuid ${NEW_ROOT_UUID} ..."
|
||||
search.fs_uuid ${NEW_ROOT_UUID} root
|
||||
echo "root=\$root"
|
||||
echo "set prefix ... "
|
||||
set prefix=(\$root)'/boot/grub2'
|
||||
echo "prefix=\$prefix"
|
||||
source \${prefix}/grub.cfg
|
||||
EOF
|
||||
|
||||
echo "Modify boot configuration ... "
|
||||
cd ${NEW_ROOT_MOUNTPOINT}/boot/grub2
|
||||
cat >grub.cfg <<EOF
|
||||
insmod gzio
|
||||
insmod part_gpt
|
||||
insmod zstd
|
||||
insmod btrfs
|
||||
terminal_input console
|
||||
terminal_output console
|
||||
|
||||
set default="0"
|
||||
set timeout=3
|
||||
|
||||
menuentry "OpenWrt" {
|
||||
echo 'Loading linux kernel ...'
|
||||
linux /boot/vmlinuz root=UUID=${NEW_ROOT_UUID} rootfstype=btrfs rootflags=compress=zstd:${ZSTD_LEVEL} console=ttyAMA0,115200n8 no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1
|
||||
echo 'Loading initial ramdisk ...'
|
||||
initrd /boot/initrd.img
|
||||
}
|
||||
EOF
|
||||
|
||||
sync
|
||||
|
||||
cd $WORK_DIR
|
||||
umount -f ${P1} ${P2} 2>/dev/null
|
||||
losetup -D 2>/dev/null
|
||||
rm -rf ${P1} ${P2} 2>/dev/null
|
||||
rm -f ${IMG_NAME} 2>/dev/null
|
||||
rm -f sha256sums 2>/dev/null
|
||||
sync
|
||||
wait
|
||||
|
||||
echo "Successfully updated, automatic restarting..."
|
||||
sleep 3
|
||||
reboot
|
||||
exit 0
|
||||
@@ -0,0 +1,916 @@
|
||||
#!/bin/bash
|
||||
#======================================================================================
|
||||
# Function: Update openwrt to emmc for Rockchip STB
|
||||
# Copyright (C) 2020-- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021-- https://github.com/ophub/luci-app-amlogic
|
||||
#======================================================================================
|
||||
#
|
||||
# The script supports directly setting parameters for update, skipping interactive selection
|
||||
# openwrt-update-rockchip ${OPENWRT_FILE} ${AUTO_MAINLINE_UBOOT} ${RESTORE_CONFIG}
|
||||
# E.g: openwrt-update-rockchip openwrt_s905d.img.gz yes restore
|
||||
# E.g: openwrt-update-rockchip openwrt_s905d.img.gz no no-restore
|
||||
|
||||
# You can also execute the script directly, and interactively select related functions
|
||||
# E.g: openwrt-update-rockchip
|
||||
#
|
||||
#======================================================================================
|
||||
|
||||
# Encountered a serious error, abort the script execution
|
||||
error_msg() {
|
||||
echo -e "[ERROR] ${1}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the /boot file system
|
||||
get_boot_partition_name() {
|
||||
local paths="/boot"
|
||||
local partition_name
|
||||
|
||||
partition_name=$(df "${paths}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Get the partition message of the root file system
|
||||
get_root_partition_msg() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_msg=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ "^" "'"${path}"'" "$" {print $0}')
|
||||
[[ -n "${partition_msg}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_msg}" ]] && error_msg "Cannot find the root partition message!"
|
||||
echo "${partition_msg}"
|
||||
}
|
||||
|
||||
# Receive one-key command related parameters
|
||||
IMG_NAME="${1}"
|
||||
AUTO_MAINLINE_UBOOT="${2}"
|
||||
BACKUP_RESTORE_CONFIG="${3}"
|
||||
|
||||
# Current device model
|
||||
if [ -f /boot/armbianEnv.txt ]; then
|
||||
source /boot/armbianEnv.txt 2>/dev/null
|
||||
CURRENT_FDTFILE=$(basename ${fdtfile})
|
||||
fi
|
||||
MYDEVICE_NAME=$(cat /proc/device-tree/model | tr -d '\000')
|
||||
case $MYDEVICE_NAME in
|
||||
"")
|
||||
error_msg "The device name is empty and cannot be recognized."
|
||||
;;
|
||||
|
||||
"Chainedbox L1 Pro")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3328-l1pro-1296mhz.dtb"
|
||||
fi
|
||||
SOC="l1pro"
|
||||
;;
|
||||
"BeikeYun")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3328-beikeyun-1296mhz.dtb"
|
||||
fi
|
||||
SOC="beikeyun"
|
||||
;;
|
||||
"ZCuble1 Max")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3399-zcube1-max.dtb"
|
||||
fi
|
||||
SOC="zcube1 max"
|
||||
;;
|
||||
"JP TVbox 3566")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3566-jp-tvbox.dtb"
|
||||
fi
|
||||
SOC="jp-tvbox"
|
||||
;;
|
||||
"Radxa CM3 RPI CM4 IO")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3566-radxa-cm3-rpi-cm4-io.dtb"
|
||||
fi
|
||||
SOC="radxa-cm3-rpi-cm4-io"
|
||||
;;
|
||||
"FastRhino R66S" | "Lunzn FastRhino R66S")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-fastrhino-r66s.dtb"
|
||||
fi
|
||||
SOC="r66s"
|
||||
;;
|
||||
"FastRhino R68S" | "Lunzn FastRhino R68S")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-fastrhino-r68s.dtb"
|
||||
fi
|
||||
SOC="r68s"
|
||||
;;
|
||||
"RK3568 EC-X")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-ec-x.dtb"
|
||||
fi
|
||||
SOC="ec-x"
|
||||
;;
|
||||
"HINLINK OPC-H66K Board" | "Hlink H66K")
|
||||
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-opc-h66k.dtb" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-hlink-h66k.dtb"
|
||||
fi
|
||||
SOC="h66k"
|
||||
;;
|
||||
"HINLINK OPC-H68K Board" | "Hlink H68K")
|
||||
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-opc-h68k.dtb" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-hlink-h68k.dtb"
|
||||
fi
|
||||
SOC="h68k"
|
||||
;;
|
||||
"HINLINK OPC-H69K Board" | "Hlink H69K")
|
||||
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-opc-h69k.dtb" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-hlink-h69k.dtb"
|
||||
fi
|
||||
SOC="h69k"
|
||||
;;
|
||||
"Radxa E25" | "Radxa E25 Carrier Board")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-radxa-e25.dtb"
|
||||
fi
|
||||
SOC="e25"
|
||||
;;
|
||||
"HINLINK OWL H88K-V3 Board" | "Hlink H88K-V3")
|
||||
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-hinlink-h88k-v3.dtb" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588-hlink-h88k-v3.dtb"
|
||||
fi
|
||||
SOC="h88k-v3"
|
||||
;;
|
||||
"Hlink H88K V3.1")
|
||||
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-hinlink-h88k-v31.dtb" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588-hlink-h88k-v31.dtb"
|
||||
fi
|
||||
SOC="h88k-v3"
|
||||
;;
|
||||
"HINLINK OWL H88K Board" | "Hlink H88K")
|
||||
if [ -n "${CURRENT_FDTFILE}" ] && [ "${CURRENT_FDTFILE}" != "rk3568-hinlink-h88k.dtb" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588-hlink-h88k.dtb"
|
||||
fi
|
||||
SOC="ak88/h88k"
|
||||
;;
|
||||
"Hlink H28K")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3528-hlink-h28k.dtb"
|
||||
fi
|
||||
SOC="h28k"
|
||||
;;
|
||||
"Hlink HT2")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3528-hlink-ht2.dtb"
|
||||
fi
|
||||
SOC="ht2"
|
||||
;;
|
||||
"Radxa E20C")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3528-radxa-e20c.dtb"
|
||||
fi
|
||||
SOC="e20c"
|
||||
;;
|
||||
"Radxa E24C")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3528-radxa-e24c.dtb"
|
||||
fi
|
||||
SOC="e24c"
|
||||
;;
|
||||
"YiXun Rs6Pro")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3528-yixun-rs6pro.dtb"
|
||||
fi
|
||||
SOC="rs6pro"
|
||||
;;
|
||||
"Ariaboard Photonicat")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-photonicat.dtb"
|
||||
fi
|
||||
SOC="photonicat"
|
||||
;;
|
||||
"NLnet Watermelon Pi V3")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-watermelon-pi-v3.dtb"
|
||||
fi
|
||||
SOC="watermelon-pi-v3"
|
||||
;;
|
||||
"NLnet Watermelon Pi")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3568-watermelon-pi.dtb"
|
||||
fi
|
||||
SOC="watermelon-pi"
|
||||
;;
|
||||
"Rockchip RK3576 DshanPi A1 Board")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3576-100ask-dshanpi-a1.dtb"
|
||||
fi
|
||||
SOC="100ask-dshanpi-a1"
|
||||
;;
|
||||
"Radxa ROCK 5B" | "Radxa ROCK 5 Model B")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588-rock-5b.dtb"
|
||||
fi
|
||||
SOC="rock5b"
|
||||
;;
|
||||
"Radxa ROCK 5C" | "Radxa ROCK 5 Model C")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588s-rock-5c.dtb"
|
||||
fi
|
||||
SOC="rock5c"
|
||||
;;
|
||||
"Radxa E52C")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588s-radxa-e52c.dtb"
|
||||
fi
|
||||
SOC="e52c"
|
||||
;;
|
||||
"Radxa E54C")
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="rk3588s-radxa-e54c.dtb"
|
||||
fi
|
||||
SOC="e54c"
|
||||
;;
|
||||
*) #default
|
||||
if [ -f "/etc/flippy-openwrt-release" ]; then
|
||||
source /etc/flippy-openwrt-release 2>/dev/null
|
||||
if [ -n "${CURRENT_FDTFILE}" ]; then
|
||||
MYDTB_FDTFILE="${CURRENT_FDTFILE}"
|
||||
else
|
||||
MYDTB_FDTFILE="${FDTFILE}"
|
||||
fi
|
||||
SOC="${SOC}"
|
||||
else
|
||||
error_msg "Unknown device: [ ${MYDEVICE_NAME} ], Not supported."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ -z "${MYDTB_FDTFILE}" || -z "${SOC}" ]] && {
|
||||
error_msg "Invalid FDTFILE or SOC: [ ${MYDTB_FDTFILE} / ${SOC} ]"
|
||||
}
|
||||
|
||||
echo -e "Current device: ${MYDEVICE_NAME} [ ${SOC} ]"
|
||||
sleep 3
|
||||
|
||||
# Check and repair partition mount points
|
||||
[[ -z "$(get_boot_partition_name)" || -z "$(get_root_partition_name)" ]] && {
|
||||
echo -e "Partition mount point error, start repairing..."
|
||||
openwrt-backup -g
|
||||
}
|
||||
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case ${ROOT_PTNAME} in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
|
||||
PARTITION_NAME="p"
|
||||
LB_PRE="EMMC_"
|
||||
;;
|
||||
nvme?n?p?)
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
|
||||
PARTITION_NAME="p"
|
||||
LB_PRE="NVME_"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
|
||||
PARTITION_NAME=""
|
||||
LB_PRE="USB_"
|
||||
;;
|
||||
*)
|
||||
error_msg "Unable to recognize the disk type of ${ROOT_PTNAME}!"
|
||||
;;
|
||||
esac
|
||||
|
||||
cd /mnt/${EMMC_NAME}${PARTITION_NAME}4/
|
||||
mv -f /tmp/upload/* . 2>/dev/null && sync
|
||||
|
||||
if [[ "${IMG_NAME}" == *.img ]]; then
|
||||
echo -e "Update using [ ${IMG_NAME} ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
echo -e "Update using [ ${IMG_NAME} ] ] file. Please wait a moment ..."
|
||||
elif [ $(ls *.img.xz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
xz_file=$(ls *.img.xz | head -n 1)
|
||||
echo -e "Update using [ ${xz_file} ] file. Please wait a moment ..."
|
||||
xz -d ${xz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.img.gz -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.img.gz | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
gzip -df ${gz_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.7z -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
gz_file=$(ls *.7z | head -n 1)
|
||||
echo -e "Update using [ ${gz_file} ] file. Please wait a moment ..."
|
||||
bsdtar -xmf ${gz_file} 2>/dev/null
|
||||
[ $? -eq 0 ] || 7z x ${gz_file} -aoa -y 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
elif [ $(ls *.zip -l 2>/dev/null | grep "^-" | wc -l) -ge 1 ]; then
|
||||
zip_file=$(ls *.zip | head -n 1)
|
||||
echo -e "Update using [ ${zip_file} ] file. Please wait a moment ..."
|
||||
unzip -o ${zip_file} 2>/dev/null
|
||||
IMG_NAME=$(ls *.img | head -n 1)
|
||||
else
|
||||
echo -e "Please upload or specify the update openwrt firmware file."
|
||||
echo -e "Upload method: system menu → Amlogic Service → Manually Upload Update"
|
||||
echo -e "Specify method: Place the openwrt firmware file in [ /mnt/${EMMC_NAME}${PARTITION_NAME}4/ ]"
|
||||
echo -e "The supported file suffixes are: *.img, *.img.xz, *.img.gz, *.7z, *.zip"
|
||||
echo -e "After upload the openwrt firmware file, run again."
|
||||
exit 1
|
||||
fi
|
||||
sync
|
||||
|
||||
# check file
|
||||
if [ ! -f "${IMG_NAME}" ]; then
|
||||
error_msg "No update file found."
|
||||
else
|
||||
echo "Start update from [ ${IMG_NAME} ]"
|
||||
fi
|
||||
|
||||
# find boot partition
|
||||
BOOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | awk '$3~/^part$/ && $5 ~ /^\/boot$/ {print $0}')
|
||||
if [ "${BOOT_PART_MSG}" == "" ]; then
|
||||
error_msg "The boot partition is not exists or not mounted, so it cannot be upgraded with this script!"
|
||||
fi
|
||||
|
||||
BR_FLAG=1
|
||||
echo -ne "Whether to backup and restore the current config files? y/n [y]\b\b"
|
||||
if [[ ${BACKUP_RESTORE_CONFIG} == "restore" ]]; then
|
||||
yn="y"
|
||||
elif [[ ${BACKUP_RESTORE_CONFIG} == "no-restore" ]]; then
|
||||
yn="n"
|
||||
else
|
||||
read yn
|
||||
fi
|
||||
case ${yn} in
|
||||
n* | N*)
|
||||
BR_FLAG=0
|
||||
;;
|
||||
esac
|
||||
|
||||
BOOT_NAME=$(echo ${BOOT_PART_MSG} | awk '{print $1}')
|
||||
BOOT_PATH=$(echo ${BOOT_PART_MSG} | awk '{print $2}')
|
||||
BOOT_UUID=$(echo ${BOOT_PART_MSG} | awk '{print $4}')
|
||||
|
||||
# find root partition
|
||||
ROOT_PART_MSG="$(get_root_partition_msg)"
|
||||
ROOT_NAME=$(echo ${ROOT_PART_MSG} | awk '{print $1}')
|
||||
ROOT_PATH=$(echo ${ROOT_PART_MSG} | awk '{print $2}')
|
||||
ROOT_UUID=$(echo ${ROOT_PART_MSG} | awk '{print $4}')
|
||||
case ${ROOT_NAME} in
|
||||
${EMMC_NAME}${PARTITION_NAME}2)
|
||||
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}3"
|
||||
NEW_ROOT_LABEL="${LB_PRE}ROOTFS2"
|
||||
;;
|
||||
${EMMC_NAME}${PARTITION_NAME}3)
|
||||
NEW_ROOT_NAME="${EMMC_NAME}${PARTITION_NAME}2"
|
||||
NEW_ROOT_LABEL="${LB_PRE}ROOTFS1"
|
||||
;;
|
||||
*)
|
||||
error_msg "The root partition location is invalid, so it cannot be upgraded with this script!"
|
||||
;;
|
||||
esac
|
||||
|
||||
# find new root partition
|
||||
NEW_ROOT_PART_MSG=$(lsblk -l -o NAME,PATH,TYPE,UUID,MOUNTPOINT | grep "${NEW_ROOT_NAME}" | awk '$3 ~ /^part$/ && $5 !~ /^\/$/ && $5 !~ /^\/boot$/ {print $0}')
|
||||
if [ "${NEW_ROOT_PART_MSG}" == "" ]; then
|
||||
error_msg "The new root partition is not exists, so it cannot be upgraded with this script!"
|
||||
fi
|
||||
NEW_ROOT_NAME=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $1}')
|
||||
NEW_ROOT_PATH=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $2}')
|
||||
NEW_ROOT_UUID=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $4}')
|
||||
NEW_ROOT_MP=$(echo ${NEW_ROOT_PART_MSG} | awk '{print $5}')
|
||||
|
||||
# losetup
|
||||
losetup -f -P ${IMG_NAME}
|
||||
if [[ "${?}" -eq "0" ]]; then
|
||||
LOOP_DEV=$(losetup | grep "${IMG_NAME}" | awk '{print $1}')
|
||||
if [ "$LOOP_DEV" == "" ]; then
|
||||
error_msg "loop device not found!"
|
||||
fi
|
||||
else
|
||||
error_msg "losetup ${IMG_FILE} failed!"
|
||||
fi
|
||||
|
||||
# fix loopdev issue in kernel 5.19
|
||||
function fix_loopdev() {
|
||||
local parentdev=${1##*/}
|
||||
if [ ! -d /sys/block/${parentdev} ]; then
|
||||
return
|
||||
fi
|
||||
subdevs=$(lsblk -l -o NAME | grep -E "^${parentdev}.+\$")
|
||||
for subdev in ${subdevs}; do
|
||||
if [ ! -d /sys/block/${parentdev}/${subdev} ]; then
|
||||
return
|
||||
elif [ -b /dev/${sub_dev} ]; then
|
||||
continue
|
||||
fi
|
||||
source /sys/block/${parentdev}/${subdev}/uevent
|
||||
mknod /dev/${subdev} b ${MAJOR} ${MINOR}
|
||||
unset MAJOR MINOR DEVNAME DEVTYPE DISKSEQ PARTN PARTNAME
|
||||
done
|
||||
}
|
||||
fix_loopdev ${LOOP_DEV}
|
||||
|
||||
WAIT=3
|
||||
echo -n "The loopdev is ${LOOP_DEV}, wait ${WAIT} seconds "
|
||||
while [ ${WAIT} -ge 1 ]; do
|
||||
echo -n "."
|
||||
sleep 1
|
||||
WAIT=$((WAIT - 1))
|
||||
done
|
||||
echo
|
||||
|
||||
# umount loop devices (openwrt will auto mount some partition)
|
||||
MOUNTED_DEVS=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${LOOP_DEV}" | awk '$3 !~ /^$/ {print $2}')
|
||||
for dev in ${MOUNTED_DEVS}; do
|
||||
while :; do
|
||||
echo -n "umount ${dev} ... "
|
||||
umount -f ${dev}
|
||||
sleep 1
|
||||
mnt=$(lsblk -l -o NAME,PATH,MOUNTPOINT | grep "${dev}" | awk '$3 !~ /^$/ {print $2}')
|
||||
if [ "${mnt}" == "" ]; then
|
||||
echo "ok"
|
||||
break
|
||||
else
|
||||
echo "try again ..."
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# mount src part
|
||||
WORK_DIR=${PWD}
|
||||
P1=${WORK_DIR}/boot
|
||||
P2=${WORK_DIR}/root
|
||||
mkdir -p $P1 $P2
|
||||
echo -n "mount ${LOOP_DEV}p1 -> ${P1} ... "
|
||||
mount -t ext4 -o ro ${LOOP_DEV}p1 ${P1}
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
echo "mount failed"
|
||||
losetup -D
|
||||
exit 1
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
|
||||
echo -n "mount ${LOOP_DEV}p2 -> ${P2} ... "
|
||||
ZSTD_LEVEL=6
|
||||
mount -t btrfs -o ro,compress=zstd:${ZSTD_LEVEL} ${LOOP_DEV}p2 ${P2}
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
echo "mount failed"
|
||||
umount -f ${P1}
|
||||
losetup -D
|
||||
exit 1
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
|
||||
# Prepare the dockerman config file
|
||||
if [ -f ${P2}/etc/init.d/dockerman ] && [ -f ${P2}/etc/config/dockerd ]; then
|
||||
|
||||
flg=0
|
||||
# get current docker data root
|
||||
data_root=$(uci get dockerd.globals.data_root 2>/dev/null)
|
||||
if [ "${data_root}" == "" ]; then
|
||||
flg=1
|
||||
# get current config from /etc/docker/daemon.json
|
||||
if [ -f "/etc/docker/daemon.json" ] && [ -x "/usr/bin/jq" ]; then
|
||||
data_root=$(jq -r '."data-root"' /etc/docker/daemon.json)
|
||||
|
||||
bip=$(jq -r '."bip"' /etc/docker/daemon.json)
|
||||
[ "${bip}" == "null" ] && bip="172.31.0.1/24"
|
||||
|
||||
log_level=$(jq -r '."log-level"' /etc/docker/daemon.json)
|
||||
[ "${log_level}" == "null" ] && log_level="warn"
|
||||
|
||||
_iptables=$(jq -r '."iptables"' /etc/docker/daemon.json)
|
||||
[ "${_iptables}" == "null" ] && _iptables="true"
|
||||
|
||||
registry_mirrors=$(jq -r '."registry-mirrors"[]' /etc/docker/daemon.json 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${data_root}" == "" ]; then
|
||||
data_root="/opt/docker/" # the default data root
|
||||
fi
|
||||
|
||||
if ! uci get dockerd.globals >/dev/null 2>&1; then
|
||||
uci set dockerd.globals='globals'
|
||||
uci commit
|
||||
fi
|
||||
|
||||
# delete alter config , use inner config
|
||||
if uci get dockerd.globals.alt_config_file >/dev/null 2>&1; then
|
||||
uci delete dockerd.globals.alt_config_file
|
||||
uci commit
|
||||
fi
|
||||
|
||||
if [[ "${flg}" -eq "1" ]]; then
|
||||
uci set dockerd.globals.data_root=${data_root}
|
||||
[ "${bip}" != "" ] && uci set dockerd.globals.bip=${bip}
|
||||
[ "${log_level}" != "" ] && uci set dockerd.globals.log_level=${log_level}
|
||||
[ "${_iptables}" != "" ] && uci set dockerd.globals.iptables=${_iptables}
|
||||
if [ "${registry_mirrors}" != "" ]; then
|
||||
for reg in ${registry_mirrors}; do
|
||||
uci add_list dockerd.globals.registry_mirrors=${reg}
|
||||
done
|
||||
fi
|
||||
uci set dockerd.globals.auto_start='1'
|
||||
uci commit
|
||||
fi
|
||||
fi
|
||||
|
||||
#format NEW_ROOT
|
||||
echo "umount ${NEW_ROOT_MP}"
|
||||
umount -f "${NEW_ROOT_MP}"
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
echo "umount failed, please reboot and try again!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "format ${NEW_ROOT_PATH}"
|
||||
NEW_ROOT_UUID=$(uuidgen)
|
||||
mkfs.btrfs -f -U ${NEW_ROOT_UUID} -L ${NEW_ROOT_LABEL} -m single ${NEW_ROOT_PATH}
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
echo "format ${NEW_ROOT_PATH} failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP}"
|
||||
mount -t btrfs -o compress=zstd:${ZSTD_LEVEL} ${NEW_ROOT_PATH} ${NEW_ROOT_MP}
|
||||
if [[ "${?}" -ne "0" ]]; then
|
||||
echo "mount ${NEW_ROOT_PATH} to ${NEW_ROOT_MP} failed!"
|
||||
umount -f ${P1}
|
||||
umount -f ${P2}
|
||||
losetup -D
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# begin copy rootfs
|
||||
cd ${NEW_ROOT_MP}
|
||||
echo "Start copy data from ${P2} to ${NEW_ROOT_MP} ..."
|
||||
ENTRYS=$(ls)
|
||||
for entry in ${ENTRYS}; do
|
||||
if [ "${entry}" == "lost+found" ]; then
|
||||
continue
|
||||
fi
|
||||
echo -n "remove old ${entry} ... "
|
||||
rm -rf ${entry}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok"
|
||||
else
|
||||
echo "failed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo
|
||||
|
||||
echo "create etc subvolume ..."
|
||||
btrfs subvolume create etc
|
||||
echo -n "make dirs ... "
|
||||
mkdir -p .snapshots .reserved bin boot dev lib opt mnt overlay proc rom root run sbin sys tmp usr www
|
||||
ln -sf lib/ lib64
|
||||
ln -sf tmp/ var
|
||||
echo "done"
|
||||
echo
|
||||
|
||||
COPY_SRC="root etc bin sbin lib opt usr www"
|
||||
echo "copy data ... "
|
||||
for src in ${COPY_SRC}; do
|
||||
echo -n "copy ${src} ... "
|
||||
(cd ${P2} && tar cf - ${src}) | tar xf -
|
||||
sync
|
||||
echo "done"
|
||||
done
|
||||
|
||||
SHFS="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
|
||||
echo "Modify config files ... "
|
||||
if [ -x ./usr/sbin/balethirq.pl ]; then
|
||||
if grep "balethirq.pl" "./etc/rc.local"; then
|
||||
echo "balance irq is enabled"
|
||||
else
|
||||
echo "enable balance irq"
|
||||
sed -e "/exit/i\/usr/sbin/balethirq.pl" -i ./etc/rc.local
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f ./etc/bench.log
|
||||
cat >./etc/fstab <<EOF
|
||||
UUID=${NEW_ROOT_UUID} / btrfs compress=zstd:${ZSTD_LEVEL} 0 1
|
||||
UUID=${BOOT_UUID} /boot ext4 defaults 0 2
|
||||
#tmpfs /tmp tmpfs defaults,nosuid 0 0
|
||||
EOF
|
||||
|
||||
cat >./etc/config/fstab <<EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '1'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '0'
|
||||
|
||||
config mount
|
||||
option target '/rom'
|
||||
option uuid '${NEW_ROOT_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '1'
|
||||
option fstype 'btrfs'
|
||||
option options 'compress=zstd:${ZSTD_LEVEL}'
|
||||
|
||||
config mount
|
||||
option target '/boot'
|
||||
option uuid '${BOOT_UUID}'
|
||||
option enabled '1'
|
||||
option enabled_fsck '0'
|
||||
option fstype 'ext4'
|
||||
|
||||
EOF
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
sync
|
||||
|
||||
echo "create the first etc snapshot -> .snapshots/etc-000"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-000
|
||||
|
||||
[ -d ${SHFS}/docker ] || mkdir -p ${SHFS}/docker
|
||||
rm -rf opt/docker && ln -sf ${SHFS}/docker/ opt/docker
|
||||
|
||||
if [ -f /mnt/${NEW_ROOT_NAME}/etc/config/AdGuardHome ]; then
|
||||
[ -d ${SHFS}/AdGuardHome/data ] || mkdir -p ${SHFS}/AdGuardHome/data
|
||||
if [ ! -L /usr/bin/AdGuardHome ]; then
|
||||
[ -d /usr/bin/AdGuardHome ] &&
|
||||
cp -a /usr/bin/AdGuardHome/* ${SHFS}/AdGuardHome/
|
||||
fi
|
||||
ln -sf ${SHFS}/AdGuardHome /mnt/${NEW_ROOT_NAME}/usr/bin/AdGuardHome
|
||||
fi
|
||||
|
||||
sync
|
||||
echo "copy done"
|
||||
echo
|
||||
|
||||
BACKUP_LIST=$(${P2}/usr/sbin/openwrt-backup -p)
|
||||
if [ $BR_FLAG -eq 1 ]; then
|
||||
echo -n "Restore your old config files ... "
|
||||
(
|
||||
cd /
|
||||
eval tar czf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
)
|
||||
tar xzf ${NEW_ROOT_MP}/.reserved/openwrt_config.tar.gz
|
||||
[ -f ./etc/config/dockerman ] && sed -e "s/option wan_mode 'false'/option wan_mode 'true'/" -i ./etc/config/dockerman 2>/dev/null
|
||||
[ -f ./etc/config/dockerd ] && sed -e "s/option wan_mode '0'/option wan_mode '1'/" -i ./etc/config/dockerd 2>/dev/null
|
||||
[ -f ./etc/config/verysync ] && sed -e 's/config setting/config verysync/' -i ./etc/config/verysync
|
||||
|
||||
# 还原 fstab
|
||||
cp -f .snapshots/etc-000/fstab ./etc/fstab
|
||||
cp -f .snapshots/etc-000/config/fstab ./etc/config/fstab
|
||||
# 还原 luci
|
||||
cp -f .snapshots/etc-000/config/luci ./etc/config/luci
|
||||
# 还原/etc/config/rpcd
|
||||
cp -f .snapshots/etc-000/config/rpcd ./etc/config/rpcd
|
||||
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
fi
|
||||
|
||||
cat >>./etc/crontabs/root <<EOF
|
||||
17 3 * * * /etc/coremark.sh
|
||||
EOF
|
||||
|
||||
sed -e 's/ttyAMA0/ttyS2/' -i ./etc/inittab
|
||||
|
||||
[ "${SOC}" != "h28k" ] && \
|
||||
[ "${SOC}" != "h29k" ] && \
|
||||
[ "${SOC}" != "ht2" ] && \
|
||||
[ "${SOC}" != "e20c" ] && \
|
||||
[ "${SOC}" != "e24c" ] && \
|
||||
sed -e 's/ttyS0/tty1/' -i ./etc/inittab
|
||||
|
||||
sss=$(date +%s)
|
||||
ddd=$((sss / 86400))
|
||||
sed -e "s/:0:0:99999:7:::/:${ddd}:0:99999:7:::/" -i ./etc/shadow
|
||||
# 修复amule每次升级后重复添加条目的问题
|
||||
sed -e "/amule:x:/d" -i ./etc/shadow
|
||||
# 修复dropbear每次升级后重复添加sshd条目的问题
|
||||
sed -e "/sshd:x:/d" -i ./etc/shadow
|
||||
if ! grep "sshd:x:22:sshd" ./etc/group >/dev/null; then
|
||||
echo "sshd:x:22:sshd" >>./etc/group
|
||||
fi
|
||||
if ! grep "sshd:x:22:22:sshd:" ./etc/passwd >/dev/null; then
|
||||
echo "sshd:x:22:22:sshd:/var/run/sshd:/bin/false" >>./etc/passwd
|
||||
fi
|
||||
if ! grep "sshd:x:" ./etc/shadow >/dev/null; then
|
||||
echo "sshd:x:${ddd}:0:99999:7:::" >>./etc/shadow
|
||||
fi
|
||||
|
||||
if [ $BR_FLAG -eq 1 ]; then
|
||||
if [ -x ./bin/bash ] && [ -f ./etc/profile.d/30-sysinfo.sh ]; then
|
||||
sed -e 's/\/bin\/ash/\/bin\/bash/' -i ./etc/passwd
|
||||
fi
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
fi
|
||||
sed -e "s/option hw_flow '1'/option hw_flow '0'/" -i ./etc/config/turboacc
|
||||
(
|
||||
cd etc/rc.d
|
||||
rm -f S??shortcut-fe
|
||||
if grep "sfe_flow '1'" ../config/turboacc >/dev/null; then
|
||||
if find ../../lib/modules -name 'shortcut-fe-cm.ko'; then
|
||||
ln -sf ../init.d/shortcut-fe S99shortcut-fe
|
||||
fi
|
||||
fi
|
||||
)
|
||||
|
||||
# move /etc/config/balance_irq to /etc/balance_irq
|
||||
[ -f "./etc/config/balance_irq" ] && mv ./etc/config/balance_irq ./etc/
|
||||
|
||||
rm -f "./etc/rc.local.orig" "./etc/first_run.sh" "./etc/part_size"
|
||||
|
||||
eval tar czf .reserved/openwrt_config.tar.gz "${BACKUP_LIST}" 2>/dev/null
|
||||
sync
|
||||
|
||||
mv ./etc/rc.local ./etc/rc.local.orig
|
||||
cat >"./etc/rc.local" <<EOF
|
||||
if ! ls /etc/rc.d/S??dockerd >/dev/null 2>&1;then
|
||||
/etc/init.d/dockerd enable
|
||||
/etc/init.d/dockerd start
|
||||
fi
|
||||
if ! ls /etc/rc.d/S??dockerman >/dev/null 2>&1 && [ -f /etc/init.d/dockerman ];then
|
||||
/etc/init.d/dockerman enable
|
||||
/etc/init.d/dockerman start
|
||||
fi
|
||||
mv /etc/rc.local.orig /etc/rc.local
|
||||
chmod 755 /etc/rc.local
|
||||
exec /etc/rc.local
|
||||
exit
|
||||
EOF
|
||||
chmod 755 ./etc/rc.local*
|
||||
|
||||
echo "create the second etc snapshot -> .snapshots/etc-001"
|
||||
btrfs subvolume snapshot -r etc .snapshots/etc-001
|
||||
|
||||
# 2021.04.01添加
|
||||
# 强制锁定fstab,防止用户擅自修改挂载点
|
||||
# 开启了快照功能之后,不再需要锁定fstab
|
||||
#chattr +ia ./etc/config/fstab
|
||||
|
||||
cd ${WORK_DIR}
|
||||
|
||||
echo "Start copy data from ${P2} to /boot ..."
|
||||
cd /boot
|
||||
echo -n "backup armbianEnv.txt ..."
|
||||
cp armbianEnv.txt /tmp/
|
||||
echo -n "backup current dtb file ..."
|
||||
cp -v dtb/rockchip/${CURRENT_FDTFILE} /tmp/
|
||||
echo -n "remove old boot files ..."
|
||||
rm -rf *
|
||||
echo "done"
|
||||
echo -n "copy new boot files ... "
|
||||
(cd ${P1} && tar cf - .) | tar xf -
|
||||
sync
|
||||
echo "done"
|
||||
echo
|
||||
|
||||
echo -n "Update boot args ... "
|
||||
|
||||
if [ -f /tmp/armbianEnv.txt ]; then
|
||||
ORIG_OVERLAYS=$(grep '^overlays=' /tmp/armbianEnv.txt)
|
||||
ORIG_USER_OVERLAYS=$(grep '^user_overlays=' /tmp/armbianEnv.txt)
|
||||
sed -e '/user_overlays=/d' -i armbianEnv.txt
|
||||
sed -e '/overlays=/d' -i armbianEnv.txt
|
||||
echo "$ORIG_OVERLAYS" >>armbianEnv.txt
|
||||
echo "$ORIG_USER_OVERLAYS" >>armbianEnv.txt
|
||||
fi
|
||||
|
||||
sed -e '/fdtfile=/d' -i armbianEnv.txt
|
||||
sed -e '/rootdev=/d' -i armbianEnv.txt
|
||||
sed -e '/rootfstype=/d' -i armbianEnv.txt
|
||||
sed -e '/rootflags=/d' -i armbianEnv.txt
|
||||
case $SOC in
|
||||
l1pro | beikeyun)
|
||||
echo "fdtfile=/dtb/rockchip/${MYDTB_FDTFILE}" >>armbianEnv.txt
|
||||
;;
|
||||
*)
|
||||
echo "fdtfile=rockchip/${MYDTB_FDTFILE}" >>armbianEnv.txt
|
||||
;;
|
||||
esac
|
||||
cat >>armbianEnv.txt <<EOF
|
||||
rootdev=UUID=${NEW_ROOT_UUID}
|
||||
rootfstype=btrfs
|
||||
rootflags=compress=zstd:${ZSTD_LEVEL}
|
||||
EOF
|
||||
|
||||
# Replace the UUID for extlinux/extlinux.conf if it exists
|
||||
[[ -f "extlinux/extlinux.conf" ]] && {
|
||||
sed -i -E "s|UUID=[^ ]*|UUID=${NEW_ROOT_UUID}|" extlinux/extlinux.conf 2>/dev/null
|
||||
}
|
||||
|
||||
# 如果新的dtb文件不存在,则用旧的代替
|
||||
if [ ! -f "dtb/rockchip/${MYDTB_FDTFILE}" ]; then
|
||||
echo "The new dtb file does not exist, replace it with the old one."
|
||||
cp -v /tmp/${CURRENT_FDTFILE} dtb/rockchip/${MYDTB_FDTFILE}
|
||||
fi
|
||||
sync
|
||||
|
||||
echo "done"
|
||||
echo
|
||||
|
||||
cd $WORK_DIR
|
||||
umount -f ${P1} ${P2} 2>/dev/null
|
||||
losetup -D 2>/dev/null
|
||||
rmdir ${P1} ${P2} 2>/dev/null
|
||||
rm -f ${IMG_NAME} 2>/dev/null
|
||||
rm -f sha256sums 2>/dev/null
|
||||
sync
|
||||
|
||||
echo "Successfully updated, automatic restarting..."
|
||||
sleep 3
|
||||
reboot
|
||||
exit 0
|
||||
@@ -0,0 +1,299 @@
|
||||
#!/bin/bash
|
||||
#==================================================================
|
||||
# This file is licensed under the terms of the GNU General Public
|
||||
# License version 2. This program is licensed "as is" without any
|
||||
# warranty of any kind, whether express or implied.
|
||||
#
|
||||
# This file is a part of the luci-app-amlogic plugin
|
||||
# https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Description: Check and update OpenWrt firmware
|
||||
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
|
||||
#==================================================================
|
||||
|
||||
# Set a fixed value
|
||||
check_option="${1}"
|
||||
download_version="${2}"
|
||||
TMP_CHECK_DIR="/tmp/amlogic"
|
||||
AMLOGIC_SOC_FILE="/etc/flippy-openwrt-release"
|
||||
START_LOG="${TMP_CHECK_DIR}/amlogic_check_firmware.log"
|
||||
RUNNING_LOG="${TMP_CHECK_DIR}/amlogic_running_script.log"
|
||||
LOG_FILE="${TMP_CHECK_DIR}/amlogic.log"
|
||||
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
|
||||
LOGTIME="$(date "+%Y-%m-%d %H:%M:%S")"
|
||||
[[ -d ${TMP_CHECK_DIR} ]] || mkdir -p ${TMP_CHECK_DIR}
|
||||
|
||||
# Clean the running log
|
||||
clean_running() {
|
||||
echo -e '' >${RUNNING_LOG} 2>/dev/null && sync
|
||||
}
|
||||
|
||||
# Add log
|
||||
tolog() {
|
||||
echo -e "${1}" >${START_LOG}
|
||||
echo -e "${LOGTIME} ${1}" >>${LOG_FILE}
|
||||
[[ -n "${2}" && "${2}" -eq "1" ]] && clean_running && exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_name}" ]] && tolog "Cannot find the root partition!" "1"
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Check running scripts, prohibit running concurrently
|
||||
this_running_log="3@OpenWrt update in progress, try again later!"
|
||||
running_script="$(cat ${RUNNING_LOG} 2>/dev/null | xargs)"
|
||||
if [[ -n "${running_script}" ]]; then
|
||||
run_num="$(echo "${running_script}" | awk -F "@" '{print $1}')"
|
||||
run_log="$(echo "${running_script}" | awk -F "@" '{print $2}')"
|
||||
fi
|
||||
if [[ -n "${run_log}" && "${run_num}" -ne "3" ]]; then
|
||||
echo -e "${run_log}" >${START_LOG} 2>/dev/null && sync && exit 1
|
||||
else
|
||||
echo -e "${this_running_log}" >${RUNNING_LOG} 2>/dev/null && sync
|
||||
fi
|
||||
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case "${ROOT_PTNAME}" in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')"
|
||||
PARTITION_NAME=""
|
||||
;;
|
||||
nvme?n?p[1-4])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
*)
|
||||
tolog "Unable to recognize the disk type of ${ROOT_PTNAME}!" "1"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Set the default download path
|
||||
FIRMWARE_DOWNLOAD_PATH="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
|
||||
[ -d "${FIRMWARE_DOWNLOAD_PATH}/.luci-app-amlogic" ] || mkdir -p "${FIRMWARE_DOWNLOAD_PATH}/.luci-app-amlogic"
|
||||
|
||||
# Check release file
|
||||
if [[ -s "${AMLOGIC_SOC_FILE}" ]]; then
|
||||
source "${AMLOGIC_SOC_FILE}" 2>/dev/null
|
||||
PLATFORM="${PLATFORM}"
|
||||
BOARD="${BOARD}"
|
||||
else
|
||||
tolog "${AMLOGIC_SOC_FILE} file is missing!" "1"
|
||||
fi
|
||||
if [[ -z "${PLATFORM}" || -z "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" || -z "${BOARD}" ]]; then
|
||||
tolog "Missing [ PLATFORM / BOARD ] value in ${AMLOGIC_SOC_FILE} file." "1"
|
||||
fi
|
||||
|
||||
tolog "PLATFORM: [ ${PLATFORM} ], BOARD: [ ${BOARD} ], Use in [ ${EMMC_NAME} ]"
|
||||
sleep 2
|
||||
|
||||
# 01. Query local version information
|
||||
tolog "01. Query version information..."
|
||||
# 01.01 Query the current version
|
||||
current_kernel_v="$(uname -r 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+')"
|
||||
tolog "01.01 current version: ${current_kernel_v}"
|
||||
sleep 2
|
||||
|
||||
# 01.01 Version comparison
|
||||
main_line_version="$(echo ${current_kernel_v} | awk -F '.' '{print $1"."$2}')"
|
||||
|
||||
# 01.02. Query the selected branch in the settings
|
||||
server_kernel_branch="$(uci get amlogic.config.amlogic_kernel_branch 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}')"
|
||||
if [[ -z "${server_kernel_branch}" ]]; then
|
||||
server_kernel_branch="${main_line_version}"
|
||||
uci set amlogic.config.amlogic_kernel_branch="${main_line_version}" 2>/dev/null
|
||||
uci commit amlogic 2>/dev/null
|
||||
fi
|
||||
if [[ "${server_kernel_branch}" != "${main_line_version}" ]]; then
|
||||
main_line_version="${server_kernel_branch}"
|
||||
tolog "01.02 Select branch: ${main_line_version}"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# 01.03. Download server version documentation
|
||||
server_firmware_url="$(uci get amlogic.config.amlogic_firmware_repo 2>/dev/null)"
|
||||
[[ ! -z "${server_firmware_url}" ]] || tolog "01.03 The custom firmware download repo is invalid." "1"
|
||||
releases_tag_keywords="$(uci get amlogic.config.amlogic_firmware_tag 2>/dev/null)"
|
||||
[[ ! -z "${releases_tag_keywords}" ]] || tolog "01.04 The custom firmware tag keywords is invalid." "1"
|
||||
firmware_suffix="$(uci get amlogic.config.amlogic_firmware_suffix 2>/dev/null)"
|
||||
[[ ! -z "${firmware_suffix}" ]] || tolog "01.05 The custom firmware suffix is invalid." "1"
|
||||
|
||||
if [[ "${server_firmware_url}" == http* ]]; then
|
||||
server_firmware_url="${server_firmware_url#*com\/}"
|
||||
fi
|
||||
|
||||
# 02. Check Updated
|
||||
check_updated() {
|
||||
tolog "02.01 Search for tags in the first 5 pages of releases..."
|
||||
|
||||
# Get the tags list
|
||||
firmware_tags_array=()
|
||||
for i in {1..5}; do
|
||||
while IFS= read -r firmware_tags_name; do
|
||||
firmware_tags_name="$(echo "${firmware_tags_name}" | sed 's/releases\/tag\///g')"
|
||||
if [[ -n "${firmware_tags_name}" ]]; then
|
||||
firmware_tags_array+=("${firmware_tags_name}")
|
||||
fi
|
||||
done < <(
|
||||
curl -fsSL -m 10 \
|
||||
https://github.com/${server_firmware_url}/releases?page=${i} |
|
||||
grep -oE 'releases/tag/([^" ]+)'
|
||||
)
|
||||
done
|
||||
|
||||
if [[ "${#firmware_tags_array[*]}" -eq "0" ]]; then
|
||||
tolog "02.01.01 Unable to retrieve a list of firmware tags." "1"
|
||||
fi
|
||||
|
||||
tolog "02.02 Search for tags containing the keyword..."
|
||||
|
||||
# Search for tags containing the keyword
|
||||
for i in "${firmware_tags_array[@]}"; do
|
||||
if [[ "${i}" == *"${releases_tag_keywords}"* ]]; then
|
||||
firmware_releases_tag="${i}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n "${firmware_releases_tag}" ]]; then
|
||||
tolog "02.02.01 Tags: ${firmware_releases_tag}"
|
||||
sleep 2
|
||||
else
|
||||
tolog "02.02.01 No matching tags found." "1"
|
||||
fi
|
||||
|
||||
tolog "02.03 Start searching for firmware download links..."
|
||||
|
||||
# Retrieve the HTML code of the tags list page
|
||||
html_code="$(
|
||||
curl -fsSL -m 10 \
|
||||
https://github.com/${server_firmware_url}/releases/expanded_assets/${firmware_releases_tag}
|
||||
)"
|
||||
|
||||
# Set the regular expression for the OpenWrt filename
|
||||
op_file_pattern=".*_${BOARD}_.*k${main_line_version}\.[0-9]+.*${firmware_suffix}"
|
||||
# Find the <li> list item where the OpenWrt file is located
|
||||
li_block=$(awk -v pattern="${op_file_pattern}" -v RS='</li>' '$0 ~ pattern { print $0 "</li>"; exit }' <<<"${html_code}")
|
||||
[[ -z "${li_block}" ]] && tolog "02.03.01 No matching download links found." "1"
|
||||
|
||||
# Find the OpenWrt filename
|
||||
latest_url=$(echo "${li_block}" | grep -oE "/[^\"]*_${BOARD}_.*k${main_line_version}\.[0-9]+[^\"]*${firmware_suffix}" | sort -urV | head -n 1 | xargs basename 2>/dev/null)
|
||||
tolog "02.03.02 OpenWrt file: ${latest_url}"
|
||||
|
||||
# Find the date of the latest update
|
||||
latest_updated_at=$(echo "${li_block}" | grep -o 'datetime="[^"]*"' | sed 's/datetime="//; s/"//')
|
||||
tolog "02.03.03 Latest updated at: ${latest_updated_at}"
|
||||
# Format the date for display
|
||||
date_display_format="$(echo ${latest_updated_at} | tr 'T' '(' | tr 'Z' ')')"
|
||||
[[ -z "${latest_url}" || -z "${latest_updated_at}" ]] && tolog "02.03.04 The download URL or date is invalid." "1"
|
||||
|
||||
# Find the firmware sha256 value
|
||||
latest_firmware_sha256="$(echo "${li_block}" | grep -o 'value="sha256:[^"]*' | sed 's/value="sha256://')"
|
||||
tolog "02.03.05 OpenWrt sha256: ${latest_firmware_sha256}"
|
||||
|
||||
# Check the firmware update code
|
||||
down_check_code="${latest_updated_at}.${main_line_version}"
|
||||
op_release_code="${FIRMWARE_DOWNLOAD_PATH}/.luci-app-amlogic/op_release_code"
|
||||
if [[ -s "${op_release_code}" ]]; then
|
||||
update_check_code="$(cat ${op_release_code} | xargs)"
|
||||
if [[ -n "${update_check_code}" && "${update_check_code}" == "${down_check_code}" ]]; then
|
||||
tolog "02.04 Already the latest version, no need to update." "1"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prompt to update
|
||||
if [[ -n "${latest_url}" ]]; then
|
||||
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Download" onclick="return b_check_firmware(this, '"'download_${latest_updated_at}@${firmware_releases_tag}/${latest_url}@${latest_firmware_sha256}'"')"/> Latest updated: '${date_display_format}'' "1"
|
||||
else
|
||||
tolog "02.05 No OpenWrt available, please use another kernel branch." "1"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# 03. Download Openwrt
|
||||
download_firmware() {
|
||||
tolog "03. Start download the Openwrt..."
|
||||
|
||||
# Get the openwrt firmware download path
|
||||
if [[ "${download_version}" == "download_"* ]]; then
|
||||
tolog "03.01 Start downloading..."
|
||||
else
|
||||
tolog "03.01 Invalid parameter." "1"
|
||||
fi
|
||||
|
||||
# Delete other residual firmware files
|
||||
rm -f ${FIRMWARE_DOWNLOAD_PATH}/*${firmware_suffix} 2>/dev/null && sync
|
||||
rm -f ${FIRMWARE_DOWNLOAD_PATH}/*.img 2>/dev/null && sync
|
||||
rm -f ${FIRMWARE_DOWNLOAD_PATH}/sha256sums 2>/dev/null && sync
|
||||
|
||||
# OpenWrt make data
|
||||
latest_updated_at="$(echo ${download_version} | awk -F'@' '{print $1}' | sed -e s'|download_||'g)"
|
||||
down_check_code="${latest_updated_at}.${main_line_version}"
|
||||
|
||||
# Download firmware
|
||||
opfile_path="$(echo ${download_version} | awk -F'@' '{print $2}')"
|
||||
# Restore converted characters in file names(%2B to +)
|
||||
firmware_download_oldname="${opfile_path//%2B/+}"
|
||||
latest_url="https://github.com/${server_firmware_url}/releases/download/${firmware_download_oldname}"
|
||||
|
||||
# Find the firmware sha256 value
|
||||
releases_firmware_sha256sums="$(echo ${download_version} | awk -F'@' '{print $3}')"
|
||||
|
||||
# Download to OpenWrt file
|
||||
firmware_download_name="openwrt_${BOARD}_k${main_line_version}_github${firmware_suffix}"
|
||||
curl -fsSL "${latest_url}" -o "${FIRMWARE_DOWNLOAD_PATH}/${firmware_download_name}"
|
||||
if [[ "$?" -eq "0" && -s "${FIRMWARE_DOWNLOAD_PATH}/${firmware_download_name}" ]]; then
|
||||
tolog "03.02 OpenWrt downloaded successfully."
|
||||
else
|
||||
tolog "03.02 OpenWrt download failed." "1"
|
||||
fi
|
||||
|
||||
# Verify sha256sums if available
|
||||
if [[ -n "${releases_firmware_sha256sums}" ]]; then
|
||||
tolog "03.03 Perform sha256 checksum verification."
|
||||
|
||||
# If there is a sha256sum file, compare it
|
||||
download_firmware_sha256sums="$(sha256sum ${FIRMWARE_DOWNLOAD_PATH}/${firmware_download_name} | awk '{print $1}')"
|
||||
if [[ "${releases_firmware_sha256sums}" != "${download_firmware_sha256sums}" ]]; then
|
||||
tolog "03.03.01 sha256sum verification mismatched." "1"
|
||||
else
|
||||
tolog "03.03.02 sha256sum verification succeeded."
|
||||
fi
|
||||
fi
|
||||
|
||||
sync && sleep 3
|
||||
|
||||
tolog "You can update."
|
||||
|
||||
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Update" onclick="return amlogic_update(this, '"'${firmware_download_name}@${down_check_code}@${FIRMWARE_DOWNLOAD_PATH}'"')"/>' "1"
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
getopts 'cd' opts
|
||||
case "${opts}" in
|
||||
c | check)
|
||||
check_updated
|
||||
;;
|
||||
* | download)
|
||||
download_firmware
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,275 @@
|
||||
#!/bin/bash
|
||||
#==================================================================
|
||||
# This file is licensed under the terms of the GNU General Public
|
||||
# License version 2. This program is licensed "as is" without any
|
||||
# warranty of any kind, whether express or implied.
|
||||
#
|
||||
# This file is a part of the luci-app-amlogic plugin
|
||||
# https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Description: Check and update OpenWrt Kernel
|
||||
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
|
||||
#==================================================================
|
||||
|
||||
# Set a fixed value
|
||||
check_option="${1}"
|
||||
download_version="${2}"
|
||||
TMP_CHECK_DIR="/tmp/amlogic"
|
||||
AMLOGIC_SOC_FILE="/etc/flippy-openwrt-release"
|
||||
START_LOG="${TMP_CHECK_DIR}/amlogic_check_kernel.log"
|
||||
RUNNING_LOG="${TMP_CHECK_DIR}/amlogic_running_script.log"
|
||||
LOG_FILE="${TMP_CHECK_DIR}/amlogic.log"
|
||||
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
|
||||
LOGTIME="$(date "+%Y-%m-%d %H:%M:%S")"
|
||||
[[ -d ${TMP_CHECK_DIR} ]] || mkdir -p ${TMP_CHECK_DIR}
|
||||
|
||||
# Clean the running log
|
||||
clean_running() {
|
||||
echo -e '' >${RUNNING_LOG} 2>/dev/null && sync
|
||||
}
|
||||
|
||||
# Add log
|
||||
tolog() {
|
||||
echo -e "${1}" >${START_LOG}
|
||||
echo -e "${LOGTIME} ${1}" >>${LOG_FILE}
|
||||
[[ -n "${2}" && "${2}" -eq "1" ]] && clean_running && exit 1
|
||||
}
|
||||
|
||||
# Get the partition name of the root file system
|
||||
get_root_partition_name() {
|
||||
local paths=("/" "/overlay" "/rom")
|
||||
local partition_name
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
partition_name=$(df "${path}" | awk 'NR==2 {print $1}' | awk -F '/' '{print $3}')
|
||||
[[ -n "${partition_name}" ]] && break
|
||||
done
|
||||
|
||||
[[ -z "${partition_name}" ]] && tolog "Cannot find the root partition!" "1"
|
||||
echo "${partition_name}"
|
||||
}
|
||||
|
||||
# Check running scripts, prohibit running concurrently
|
||||
this_running_log="2@Kernel update in progress, try again later!"
|
||||
running_script="$(cat ${RUNNING_LOG} 2>/dev/null | xargs)"
|
||||
if [[ -n "${running_script}" ]]; then
|
||||
run_num="$(echo "${running_script}" | awk -F "@" '{print $1}')"
|
||||
run_log="$(echo "${running_script}" | awk -F "@" '{print $2}')"
|
||||
fi
|
||||
if [[ -n "${run_log}" && "${run_num}" -ne "2" ]]; then
|
||||
echo -e "${run_log}" >${START_LOG} 2>/dev/null && sync && exit 1
|
||||
else
|
||||
echo -e "${this_running_log}" >${RUNNING_LOG} 2>/dev/null && sync
|
||||
fi
|
||||
|
||||
# Find the partition where root is located
|
||||
ROOT_PTNAME="$(get_root_partition_name)"
|
||||
|
||||
# Find the disk where the partition is located, only supports mmcblk?p? sd?? hd?? vd?? and other formats
|
||||
case "${ROOT_PTNAME}" in
|
||||
mmcblk?p[1-4])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
[hsv]d[a-z][1-4])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')"
|
||||
PARTITION_NAME=""
|
||||
;;
|
||||
nvme?n?p[1-4])
|
||||
EMMC_NAME="$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')"
|
||||
PARTITION_NAME="p"
|
||||
;;
|
||||
*)
|
||||
tolog "Unable to recognize the disk type of ${ROOT_PTNAME}!" "1"
|
||||
;;
|
||||
esac
|
||||
# Set the default download path
|
||||
KERNEL_DOWNLOAD_PATH="/mnt/${EMMC_NAME}${PARTITION_NAME}4"
|
||||
|
||||
# Check release file
|
||||
if [[ -s "${AMLOGIC_SOC_FILE}" ]]; then
|
||||
source "${AMLOGIC_SOC_FILE}" 2>/dev/null
|
||||
PLATFORM="${PLATFORM}"
|
||||
else
|
||||
tolog "${AMLOGIC_SOC_FILE} file is missing!" "1"
|
||||
fi
|
||||
if [[ -z "${PLATFORM}" || -z "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" ]]; then
|
||||
tolog "Missing [ PLATFORM ] value in ${AMLOGIC_SOC_FILE} file." "1"
|
||||
fi
|
||||
|
||||
tolog "PLATFORM: [ ${PLATFORM} ], Use in [ ${EMMC_NAME} ]"
|
||||
sleep 2
|
||||
|
||||
# Step 1. Set the kernel query api
|
||||
tolog "01. Start checking the kernel repository."
|
||||
firmware_repo="$(uci get amlogic.config.amlogic_firmware_repo 2>/dev/null)"
|
||||
[[ -n "${firmware_repo}" ]] || tolog "01.01 The custom kernel download repo is invalid." "1"
|
||||
kernel_repo="$(uci get amlogic.config.amlogic_kernel_path 2>/dev/null)"
|
||||
[[ -n "${kernel_repo}" ]] || tolog "01.02 The custom kernel download repo is invalid." "1"
|
||||
|
||||
if [[ "${kernel_repo}" == "opt/kernel" ]]; then
|
||||
uci set amlogic.config.amlogic_kernel_path="${firmware_repo}" 2>/dev/null
|
||||
uci commit amlogic 2>/dev/null
|
||||
kernel_repo="${firmware_repo}"
|
||||
fi
|
||||
|
||||
# Convert kernel repo to api format
|
||||
[[ "${kernel_repo}" =~ ^https: ]] && kernel_repo="$(echo ${kernel_repo} | awk -F'/' '{print $4"/"$5}')"
|
||||
kernel_api="https://github.com/${kernel_repo}"
|
||||
tolog "01.03 Kernel repo: ${kernel_repo}"
|
||||
# Get the current kernel uname
|
||||
kernel_uname="$(uname -r 2>/dev/null)"
|
||||
tolog "01.04 Current kernel uname: ${kernel_uname}"
|
||||
|
||||
# Get the kernel tag from uci config
|
||||
op_kernel_tags="$(uci get amlogic.config.amlogic_kernel_tags 2>/dev/null)"
|
||||
# Determine the kernel tag
|
||||
if [[ -n "${op_kernel_tags}" ]]; then
|
||||
kernel_tag="${op_kernel_tags/kernel_/}"
|
||||
else
|
||||
# Determine the kernel tag based on the current kernel uname
|
||||
if [[ "${kernel_uname}" =~ -rk3588 ]]; then
|
||||
kernel_tag="rk3588"
|
||||
elif [[ "${kernel_uname}" =~ -rk35xx ]]; then
|
||||
kernel_tag="rk35xx"
|
||||
elif [[ "${kernel_uname}" =~ -h6|-zicai ]]; then
|
||||
kernel_tag="h6"
|
||||
else
|
||||
kernel_tag="stable"
|
||||
fi
|
||||
|
||||
# Save the kernel tag to uci config
|
||||
uci set amlogic.config.amlogic_kernel_tags="kernel_${kernel_tag}" 2>/dev/null
|
||||
uci commit amlogic 2>/dev/null
|
||||
fi
|
||||
tolog "01.05 Kernel tag: kernel_${kernel_tag}"
|
||||
sleep 2
|
||||
|
||||
# Step 2: Check if there is the latest kernel version
|
||||
check_kernel() {
|
||||
# 02. Query local version information
|
||||
tolog "02. Start checking the kernel version."
|
||||
|
||||
# 02.01 Get current kernel version
|
||||
[[ ! "${kernel_tag}" =~ ^(rk3588|rk35xx)$ ]] && kernel_uname="$(echo "${kernel_uname}" | cut -d'-' -f1)"
|
||||
[[ -n "${kernel_uname}" ]] || tolog "02.01 The current kernel version is not detected." "1"
|
||||
tolog "02.01 current version: ${kernel_uname}"
|
||||
sleep 2
|
||||
|
||||
# 02.02 Version comparison
|
||||
main_line_version="$(echo ${kernel_uname} | awk -F '.' '{print $1"."$2}')"
|
||||
|
||||
# 02.03 Query the selected branch in the settings
|
||||
server_kernel_branch="$(uci get amlogic.config.amlogic_kernel_branch 2>/dev/null | grep -oE '^[1-9].[0-9]{1,3}')"
|
||||
if [[ -z "${server_kernel_branch}" ]]; then
|
||||
server_kernel_branch="${main_line_version}"
|
||||
uci set amlogic.config.amlogic_kernel_branch="${main_line_version}" 2>/dev/null
|
||||
uci commit amlogic 2>/dev/null
|
||||
fi
|
||||
|
||||
if [[ "${server_kernel_branch}" != "${main_line_version}" ]]; then
|
||||
main_line_version="${server_kernel_branch}"
|
||||
main_line_now="0"
|
||||
tolog "02.02 Select branch: ${main_line_version}"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# Check the version on the server
|
||||
latest_version="$(
|
||||
curl -fsSL -m 10 \
|
||||
${kernel_api}/releases/expanded_assets/kernel_${kernel_tag} |
|
||||
grep -oE "${main_line_version}\.[0-9]+[^\"]*\.tar\.gz" | sed 's/.tar.gz//' |
|
||||
sort -urV | head -n 1
|
||||
)"
|
||||
[[ -n "${latest_version}" ]] || tolog "02.03 No kernel available, please use another kernel branch." "1"
|
||||
|
||||
tolog "02.04 current version: ${kernel_uname}, Latest version: ${latest_version}"
|
||||
sleep 2
|
||||
|
||||
# Get the sha256 value of the latest version
|
||||
latest_kernel_sha256="$(
|
||||
curl -fsSL -m 10 \
|
||||
${kernel_api}/releases/expanded_assets/kernel_${kernel_tag} |
|
||||
awk -v pattern="${latest_version}\.tar\.gz" -v RS='</li>' '$0 ~ pattern { print $0 "</li>"; exit }' |
|
||||
grep -o 'value="sha256:[^"]*' | sed 's/value="sha256://'
|
||||
)"
|
||||
[[ -n "${latest_kernel_sha256}" ]] && tolog "02.05 Kernel sha256: ${latest_kernel_sha256}"
|
||||
|
||||
if [[ "${latest_version}" == "${kernel_uname}" ]]; then
|
||||
tolog "02.06 Already the latest version, no need to update." "1"
|
||||
sleep 2
|
||||
else
|
||||
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Download" onclick="return b_check_kernel(this, '"'download_${latest_version}_${latest_kernel_sha256}'"')"/> Latest version: '${latest_version}'' "1"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Step 3: Download the latest kernel version
|
||||
download_kernel() {
|
||||
tolog "03. Start download the kernel file."
|
||||
if [[ "${download_version}" == "download_"* ]]; then
|
||||
tolog "03.01 Start downloading..."
|
||||
else
|
||||
tolog "03.01 Invalid parameter" "1"
|
||||
fi
|
||||
|
||||
# Get the kernel file name
|
||||
kernel_file_name="$(echo "${download_version}" | cut -d '_' -f2)"
|
||||
# Restore converted characters in file names(%2B to +)
|
||||
kernel_file_name="${kernel_file_name//%2B/+}"
|
||||
# Get the sha256 value
|
||||
kernel_file_sha256="$(echo "${download_version}" | cut -d '_' -f3)"
|
||||
|
||||
# Delete other residual kernel files
|
||||
rm -f ${KERNEL_DOWNLOAD_PATH}/*.tar.gz
|
||||
rm -f ${KERNEL_DOWNLOAD_PATH}/sha256sums
|
||||
rm -rf ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}*
|
||||
|
||||
kernel_down_from="https://github.com/${kernel_repo}/releases/download/kernel_${kernel_tag}/${kernel_file_name}.tar.gz"
|
||||
|
||||
curl -fsSL "${kernel_down_from}" -o ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz
|
||||
[[ "${?}" -ne "0" ]] && tolog "03.02 The kernel download failed." "1"
|
||||
|
||||
# Verify sha256
|
||||
if [[ -n "${kernel_file_sha256}" ]]; then
|
||||
tolog "03.03 Perform sha256 checksum verification."
|
||||
|
||||
download_kernel_sha256sums="$(sha256sum ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz | awk '{print $1}')"
|
||||
if [[ "${kernel_file_sha256}" != "${download_kernel_sha256sums}" ]]; then
|
||||
tolog "03.03.01 sha256sum verification mismatched." "1"
|
||||
else
|
||||
tolog "03.03.02 sha256sum verification succeeded."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Decompress the kernel package
|
||||
tolog "03.04 Start decompressing the kernel package..."
|
||||
tar -xf ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz -C ${KERNEL_DOWNLOAD_PATH}
|
||||
[[ "${?}" -ne "0" ]] && tolog "03.05 Kernel decompression failed." "1"
|
||||
mv -f ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}/* ${KERNEL_DOWNLOAD_PATH}/
|
||||
|
||||
sync && sleep 3
|
||||
# Delete the downloaded kernel file
|
||||
rm -f ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}.tar.gz
|
||||
rm -rf ${KERNEL_DOWNLOAD_PATH}/${kernel_file_name}
|
||||
|
||||
tolog "03.06 The kernel is ready, you can update."
|
||||
sleep 2
|
||||
|
||||
#echo '<a href="javascript:;" onclick="return amlogic_kernel(this)">Update</a>' >$START_LOG
|
||||
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Update" onclick="return amlogic_kernel(this)"/>' "1"
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
getopts 'cd' opts
|
||||
case "${opts}" in
|
||||
c | check)
|
||||
check_kernel
|
||||
;;
|
||||
* | download)
|
||||
download_kernel
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/bin/bash
|
||||
#==================================================================
|
||||
# This file is licensed under the terms of the GNU General Public
|
||||
# License version 2. This program is licensed "as is" without any
|
||||
# warranty of any kind, whether express or implied.
|
||||
#
|
||||
# This file is a part of the luci-app-amlogic plugin
|
||||
# https://github.com/ophub/luci-app-amlogic
|
||||
#
|
||||
# Description: Check and update luci-app-amlogic plugin
|
||||
# Copyright (C) 2021- https://github.com/unifreq/openwrt_packit
|
||||
# Copyright (C) 2021- https://github.com/ophub/luci-app-amlogic
|
||||
#==================================================================
|
||||
|
||||
# Set a fixed value
|
||||
TMP_CHECK_DIR="/tmp/amlogic"
|
||||
AMLOGIC_SOC_FILE="/etc/flippy-openwrt-release"
|
||||
START_LOG="${TMP_CHECK_DIR}/amlogic_check_plugin.log"
|
||||
RUNNING_LOG="${TMP_CHECK_DIR}/amlogic_running_script.log"
|
||||
LOG_FILE="${TMP_CHECK_DIR}/amlogic.log"
|
||||
support_platform=("allwinner" "rockchip" "amlogic" "qemu-aarch64")
|
||||
LOGTIME="$(date "+%Y-%m-%d %H:%M:%S")"
|
||||
|
||||
[[ -d ${TMP_CHECK_DIR} ]] || mkdir -p ${TMP_CHECK_DIR}
|
||||
rm -f ${TMP_CHECK_DIR}/*.ipk 2>/dev/null && sync
|
||||
rm -f ${TMP_CHECK_DIR}/sha256sums 2>/dev/null && sync
|
||||
|
||||
# Clean the running log
|
||||
clean_running() {
|
||||
echo -e '' >${RUNNING_LOG} 2>/dev/null && sync
|
||||
}
|
||||
|
||||
# Add log
|
||||
tolog() {
|
||||
echo -e "${1}" >${START_LOG}
|
||||
echo -e "${LOGTIME} ${1}" >>${LOG_FILE}
|
||||
[[ -n "${2}" && "${2}" -eq "1" ]] && clean_running && exit 1
|
||||
}
|
||||
|
||||
# Check running scripts, prohibit running concurrently
|
||||
this_running_log="1@Plugin update in progress, try again later!"
|
||||
running_script="$(cat ${RUNNING_LOG} 2>/dev/null | xargs)"
|
||||
if [[ -n "${running_script}" ]]; then
|
||||
run_num="$(echo "${running_script}" | awk -F "@" '{print $1}')"
|
||||
run_log="$(echo "${running_script}" | awk -F "@" '{print $2}')"
|
||||
fi
|
||||
if [[ -n "${run_log}" && "${run_num}" -ne "1" ]]; then
|
||||
echo -e "${run_log}" >${START_LOG} 2>/dev/null && sync && exit 1
|
||||
else
|
||||
echo -e "${this_running_log}" >${RUNNING_LOG} 2>/dev/null && sync
|
||||
fi
|
||||
|
||||
# Check release file
|
||||
if [[ -s "${AMLOGIC_SOC_FILE}" ]]; then
|
||||
source "${AMLOGIC_SOC_FILE}" 2>/dev/null
|
||||
PLATFORM="${PLATFORM}"
|
||||
else
|
||||
tolog "${AMLOGIC_SOC_FILE} file is missing!" "1"
|
||||
fi
|
||||
if [[ -z "${PLATFORM}" || -z "$(echo "${support_platform[@]}" | grep -w "${PLATFORM}")" ]]; then
|
||||
tolog "Missing [ PLATFORM ] value in ${AMLOGIC_SOC_FILE} file." "1"
|
||||
fi
|
||||
|
||||
tolog "PLATFORM: [ ${PLATFORM} ]"
|
||||
sleep 2
|
||||
|
||||
# 01. Query local version information
|
||||
tolog "01. Query current version information."
|
||||
|
||||
# If neither opkg nor apk found, set package_manager to empty
|
||||
package_manager=""
|
||||
current_plugin_v=""
|
||||
|
||||
if command -v opkg >/dev/null 2>&1; then
|
||||
# System has opkg
|
||||
package_manager="ipk"
|
||||
# Important: Add cut to handle versions like X.Y.Z-r1, ensuring consistent output
|
||||
current_plugin_v="$(opkg list-installed | grep '^luci-app-amlogic' | awk '{print $3}' | cut -d'-' -f1)"
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
# System has apk
|
||||
package_manager="apk"
|
||||
current_plugin_v="$(apk list --installed | grep '^luci-app-amlogic' | awk '{print $1}' | cut -d'-' -f4)"
|
||||
fi
|
||||
|
||||
# Check if we successfully found the plugin
|
||||
if [[ -z "${package_manager}" || -z "${current_plugin_v}" ]]; then
|
||||
tolog "01.01 Plugin 'luci-app-amlogic' not found or package manager unknown." "1"
|
||||
else
|
||||
tolog "01.01 Using [${package_manager}]. Current version: ${current_plugin_v}"
|
||||
fi
|
||||
sleep 2
|
||||
|
||||
# 02. Check the version on the server
|
||||
tolog "02. Start querying plugin version..."
|
||||
|
||||
# Get the latest version
|
||||
latest_version="$(
|
||||
curl -fsSL -m 10 \
|
||||
https://github.com/ophub/luci-app-amlogic/releases |
|
||||
grep -oE 'expanded_assets/[0-9]+.[0-9]+.[0-9]+(-[0-9]+)?' | sed 's|expanded_assets/||g' |
|
||||
sort -urV | head -n 1
|
||||
)"
|
||||
if [[ -z "${latest_version}" ]]; then
|
||||
tolog "02.01 Query failed, please try again." "1"
|
||||
else
|
||||
tolog "02.01 current version: ${current_plugin_v}, Latest version: ${latest_version}"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# Compare the version and download the latest version
|
||||
if [[ "${current_plugin_v}" == "${latest_version}" ]]; then
|
||||
tolog "02.02 Already the latest version, no need to update." "1"
|
||||
else
|
||||
tolog "02.03 New version found. Preparing to download for [${package_manager}]..."
|
||||
download_repo="https://github.com/ophub/luci-app-amlogic/releases/download"
|
||||
|
||||
# Intelligent File Discovery
|
||||
plugin_file_name=""
|
||||
lang_file_list=""
|
||||
|
||||
# Method 1: Use GitHub API if 'jq' is installed (Preferred Method)
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
tolog "Using GitHub API with jq to find package files."
|
||||
api_url="https://api.github.com/repos/ophub/luci-app-amlogic/releases/tags/${latest_version}"
|
||||
|
||||
# Fetch all asset names from the API
|
||||
asset_list="$(curl -fsSL -m 15 "${api_url}" | jq -r '.assets[].name' | xargs)"
|
||||
|
||||
if [[ -n "${asset_list}" ]]; then
|
||||
# Discover exact filenames using regular expressions from the asset list
|
||||
plugin_file_name="$(echo "${asset_list}" | tr ' ' '\n' | grep -oE "^luci-app-amlogic.*${package_manager}$" | head -n 1)"
|
||||
lang_file_list=($(echo "${asset_list}" | tr ' ' '\n' | grep -oE "^luci-i18n-amlogic.*${package_manager}$"))
|
||||
else
|
||||
tolog "Warning: Failed to fetch data from GitHub API." "1"
|
||||
fi
|
||||
else
|
||||
tolog "jq not found, Aborting." "1"
|
||||
fi
|
||||
|
||||
# Validation and Download
|
||||
if [[ -z "${plugin_file_name}" || "${#lang_file_list[@]}" -eq "0" ]]; then
|
||||
tolog "02.03.2 Could not discover plugin(.${package_manager}) in the release. Aborting." "1"
|
||||
fi
|
||||
|
||||
tolog "Found plugin file: ${plugin_file_name}"
|
||||
tolog "Found language file: $(echo ${lang_file_list[@]} | xargs)"
|
||||
|
||||
# Download the main plugin file
|
||||
plugin_full_url="${download_repo}/${latest_version}/${plugin_file_name}"
|
||||
tolog "02.04 Downloading main plugin..."
|
||||
curl -fsSL "${plugin_full_url}" -o "${TMP_CHECK_DIR}/${plugin_file_name}"
|
||||
[[ "${?}" -ne "0" ]] && tolog "02.04 Plugin [ ${plugin_file_name} ] download failed." "1"
|
||||
|
||||
# Download language packs
|
||||
for langfile in "${lang_file_list[@]}"; do
|
||||
lang_full_url="${download_repo}/${latest_version}/${langfile}"
|
||||
tolog "02.05 Downloading language pack [ ${langfile} ]..."
|
||||
curl -fsSL "${lang_full_url}" -o "${TMP_CHECK_DIR}/${langfile}"
|
||||
[[ "${?}" -ne "0" ]] && tolog "02.05 Language pack [ ${langfile} ] download failed." "1"
|
||||
done
|
||||
|
||||
sync && sleep 2
|
||||
fi
|
||||
|
||||
tolog "03. The plug is ready, you can update."
|
||||
sleep 2
|
||||
|
||||
tolog '<input type="button" class="cbi-button cbi-button-reload" value="Update" onclick="return amlogic_plugin(this)"/> Latest version: '${latest_version}'' "1"
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"luci-app-amlogic": {
|
||||
"description": "Grant UCI access for luci-app-amlogic",
|
||||
"read": {
|
||||
"uci": [ "amlogic" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "amlogic" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"config": "amlogic",
|
||||
"init": "amlogic"
|
||||
}
|
||||