diff options
author | Stan Grishin <stangri@melmac.net> | 2021-01-06 16:56:10 +0000 |
---|---|---|
committer | Stan Grishin <stangri@melmac.net> | 2021-01-07 19:18:58 +0000 |
commit | 1ce1f86a2cdde8d4d55d76935fda90ff7eb89736 (patch) | |
tree | 4491567b0f4e5042dcb8581ba13aed26c3d128e5 /applications/luci-app-advanced-reboot/root/usr/libexec/rpcd | |
parent | e7aeb9b153abc97a77be1e8ef9c8c499a0735895 (diff) |
luci-app-advanced-reboot: rewrite rpcd in shell script + bugfixes
Signed-off-by: Stan Grishin <stangri@melmac.net>
Diffstat (limited to 'applications/luci-app-advanced-reboot/root/usr/libexec/rpcd')
-rwxr-xr-x | applications/luci-app-advanced-reboot/root/usr/libexec/rpcd/luci.advanced_reboot | 712 |
1 files changed, 370 insertions, 342 deletions
diff --git a/applications/luci-app-advanced-reboot/root/usr/libexec/rpcd/luci.advanced_reboot b/applications/luci-app-advanced-reboot/root/usr/libexec/rpcd/luci.advanced_reboot index a6c7c0e540..c78a61d611 100755 --- a/applications/luci-app-advanced-reboot/root/usr/libexec/rpcd/luci.advanced_reboot +++ b/applications/luci-app-advanced-reboot/root/usr/libexec/rpcd/luci.advanced_reboot @@ -1,362 +1,390 @@ -#!/usr/bin/env lua +#!/bin/sh +# Copyright 2017-2020 Stan Grishin (stangri@melmac.net) +# shellcheck disable=SC2039,SC1091 -local json = require "luci.jsonc" -local nixio = require "nixio" -local fs = require "nixio.fs" -local sys = require "luci.sys" -local util = require "luci.util" +readonly devices_dir="/usr/share/advanced-reboot/devices/" -local devices_dir = "/usr/share/advanced-reboot/devices/" +. /lib/functions.sh +. /usr/share/libubox/jshn.sh -local function logger(t) - util.exec("logger -t advanced-reboot '" .. tostring(t) .. "'") -end +logger() { /usr/bin/logger -t advanced-reboot "$1"; } -local function is_alt_mountable(p1_mtd, p2_mtd) - if p1_mtd:sub(1,3) == "mtd" and - p2_mtd:sub(1,3) == "mtd" and - fs.access("/usr/sbin/ubiattach") and - fs.access("/usr/sbin/ubiblock") and - fs.access("/bin/mount") then - return true +is_alt_mountable() { + local p1_mtd="$1" p2_mtd="$2" + if [ "${p1_mtd:0:3}" = "mtd" ] && [ "${p2_mtd:0:3}" = "mtd" ] && \ + [ -x "/usr/sbin/ubiattach" ] && \ + [ -x "/usr/sbin/ubiblock" ] && \ + [ -x "/bin/mount" ]; then + return 0 else - return false - end -end - -local function alt_partition_mount(op_ubi) - local ubi_dev - util.exec('for i in alt_rom alt_overlay firmware; do [ ! -d "$i" ] && mkdir -p "/alt/${i}"; done') - ubi_dev = tostring(util.exec("ubiattach -m " .. tostring(op_ubi))) - _, _, ubi_dev = ubi_dev:find("UBI device number (%d+)") - if not ubi_dev then - util.exec("ubidetach -m " .. tostring(op_ubi)) - return - end - util.exec("ubiblock --create /dev/ubi" .. ubi_dev .. "_0") - util.exec("mount -t squashfs -o ro /dev/ubiblock" .. ubi_dev .. "_0 /alt/alt_rom") - util.exec("mount -t ubifs /dev/ubi" .. ubi_dev .. "_1 /alt/alt_overlay") --- util.exec("mount -t overlay overlay -o noatime,lowerdir=/alt/rom,upperdir=/alt/overlay/upper,workdir=/alt/overlay/work /alt/firmware") -end - -local function alt_partition_unmount(op_ubi) - local i - local mtdCount = tonumber(util.exec("ubinfo | grep 'Present UBI devices' | grep -c ','")) - mtdCount = mtdCount and mtdCount + 1 or 10 --- util.exec("[ -d /alt/firmware ] && umount /alt/firmware") - util.exec("[ -d /alt/alt_overlay ] && umount /alt/alt_overlay") - util.exec("[ -d /alt/alt_rom ] && umount /alt/alt_rom") - for i = 0, mtdCount do - if not fs.access("/sys/devices/virtual/ubi/ubi" .. tostring(i) .. "/mtd_num") then break end - ubi_mtd = tonumber(util.trim(util.exec("cat /sys/devices/virtual/ubi/ubi" .. i .. "/mtd_num"))) - if ubi_mtd and ubi_mtd == op_ubi then - util.exec("ubiblock --remove /dev/ubi" .. tostring(i) .. "_0") - util.exec("ubidetach -m " .. tostring(op_ubi)) - util.exec('rm -rf /alt') - end - end -end - -local function get_partition_os_info(op_ubi) - local cp_info, op_info - if fs.access("/etc/os-release") then - cp_info = util.trim(util.exec('. /etc/os-release && echo "$PRETTY_NAME"')) - if cp_info:find("SNAPSHOT") then - cp_info = util.trim(util.exec('. /etc/os-release && echo "$OPENWRT_RELEASE"')) - end - end - logger(string.format("attempting to mount alternative partition (mtd%s)", tostring(op_ubi))) - alt_partition_unmount(op_ubi) - alt_partition_mount(op_ubi) - if fs.access("/alt/alt_rom/etc/os-release") then - op_info = util.trim(util.exec('. /alt/alt_rom/etc/os-release && echo "$PRETTY_NAME"')) - if op_info:find("SNAPSHOT") then - op_info = util.trim(util.exec('. /alt/alt_rom/etc/os-release && echo "$OPENWRT_RELEASE"')) - end - end - logger(string.format("attempting to unmount alternative partition (mtd%s)", tostring(op_ubi))) - alt_partition_unmount(op_ubi) - return cp_info, op_info -end - -local function find_device_data(romBoardName) - local filename - - for filename in fs.dir(devices_dir) do - local filedata = fs.readfile(devices_dir .. filename) - - local p = json.parse(filedata or {}) - - if p then - local boardName - - if p.boardName then - boardName = p.boardName:gsub('%p','') - if romBoardName:match(boardName) then return p end - end - if p.boardNames then - for i, v in pairs(p.boardNames) do - boardName = v:gsub('%p','') - if romBoardName:match(boardName) then return p end - end - end - end - end - - return nil -end - -local methods = { - obtain_device_info = { - call = function() - - local ret = {} - local romBoardName = fs.readfile('/tmp/sysinfo/board_name') - - if not romBoardName then - ret.error = 'NO_BOARD_NAME' - return ret - end - - romBoardName = romBoardName:gsub('\n','') + return 1 + fi +} - ret.rom_board_name = romBoardName +alt_partition_mount() { + local ubi_dev op_ubi="$1" + for i in alt_rom alt_overlay firmware; do [ ! -d "$i" ] && mkdir -p "/alt/${i}"; done + ubi_dev="$(ubiattach -m "$op_ubi")" + ubi_dev="$(echo "$ubi_dev" | sed -n "s/^UBI device number\s*\(\d*\),.*$/\1/p")" + if [ -z "$ubi_dev" ]; then + ubidetach -m "$op_ubi" + return 1 + fi + ubiblock --create "/dev/ubi${ubi_dev}_0" + mount -t squashfs -o ro "/dev/ubiblock${ubi_dev}_0" /alt/alt_rom + mount -t ubifs "/dev/ubi${ubi_dev}_0" /alt/alt_overlay + # mount -t overlay overlay -o noatime,lowerdir=/alt/rom,upperdir=/alt/overlay/upper,workdir=/alt/overlay/work /alt/firmware +} - romBoardName = romBoardName:gsub('%p','') +alt_partition_unmount() { + local mtdCount i=0 op_ubi="$1" + mtdCount="$(ubinfo | grep 'Present UBI devices' | tr ',' '\n' | grep -c 'ubi')" + [ -z "$mtdCount" ] && mtdCount=10 + # [ -d /alt/firmware ] && umount /alt/firmware + [ -d /alt/alt_overlay ] && umount /alt/alt_overlay + [ -d /alt/alt_rom ] && umount /alt/alt_rom + while [ "$i" -le "$mtdCount" ]; do + if [ ! -e "/sys/devices/virtual/ubi/ubi${i}/mtd_num" ]; then + break + fi + ubi_mtd="$(cat /sys/devices/virtual/ubi/ubi${i}/mtd_num)" + if [ -n "$ubi_mtd" ] && [ "$ubi_mtd" = "$op_ubi" ]; then + ubiblock --remove /dev/ubi${i}_0 + ubidetach -m "$op_ubi" + rm -rf /alt + fi + i=$((i + 1)) + done +} - local p, boardName, n, p1_label, p1_version, p2_label, p2_version, p1_os, p2_os - local current_partition - local op_ubi, cp_info, op_info, zyxelFlagPartition +get_main_partition_os_info(){ + local cp_info + if [ -s "/etc/os-release" ]; then + cp_info="$(. /etc/os-release && echo "$PRETTY_NAME")" + if [ "${cp_info//SNAPSHOT}" != "$cp_info" ]; then + cp_info="$(. /etc/os-release && echo "${OPENWRT_RELEASE%%-*}")" + fi + fi + echo "$cp_info" +} - p = find_device_data(romBoardName) +get_alt_partition_os_info(){ + local op_info op_ubi="$1" + logger "attempting to mount alternative partition (mtd${op_ubi})" + alt_partition_unmount "$op_ubi" + alt_partition_mount "$op_ubi" + if [ -s "/alt/alt_rom/etc/os-release" ]; then + op_info="$(. /alt/alt_rom/etc/os-release && echo "$PRETTY_NAME")" + if [ "${op_info//SNAPSHOT}" != "$op_info" ]; then + op_info="$(. /alt/alt_rom/etc/os-release && echo "${OPENWRT_RELEASE%%-*}")" + fi + fi + logger "attempting to unmount alternative partition (mtd${op_ubi})" + alt_partition_unmount "$op_ubi" + echo "$op_info" +} - if p then - if p.labelOffset then - if p.partition1MTD then - p1_label = util.trim(util.exec("dd if=/dev/" .. p.partition1MTD .. " bs=1 skip=" .. p.labelOffset .. " count=128" .. " 2>/dev/null")) - n, p1_version = p1_label:match('(Linux)-([%d|.]+)') - end +find_device_data(){ + local boardNames filename i romBoardName="$1" + for filename in "${devices_dir}"*.json; do + [ "$filename" = "${devices_dir}*.json" ] && return + json_load_file "$filename" + json_get_values boardNames 'boardNames' + json_cleanup + for i in $boardNames; do + if [ "$i" = "$romBoardName" ]; then + echo "$filename" + return + fi + done + done +} - if p1_label then - if p1_label:find("LEDE") then p1_os = "LEDE" end - if p1_label:find("OpenWrt") then p1_os = "OpenWrt" end - if p.vendorName and p1_label:find(p.vendorName) then p1_os = p.vendorName end - end +print_json() { json_init; json_add_string "$1" "$2"; json_dump; json_cleanup; } - if not p1_os then - p1_os = (p.vendorName and p.vendorName or 'Unknown') .. "/" .. "Unknown" - end - if p1_os and p1_version then p1_os = p1_os .. " (Linux " .. p1_version .. ")" end +obtain_device_info(){ + local romBoardName p zyxelFlagPartition + local vendorName deviceName partition1MTD partition2MTD labelOffset + local bootEnv1 bootEnv1Partition1Value bootEnv1Partition2Value + local bootEnv2 bootEnv2Partition1Value bootEnv2Partition2Value + local p1_label p1_version p2_label p2_version p1_os p2_os + local current_partition op_ubi cp_info op_info - if p.partition2MTD then - p2_label = util.trim(util.exec("dd if=/dev/" .. p.partition2MTD .. " bs=1 skip=" .. p.labelOffset .. " count=128" .. " 2>/dev/null")) - n, p2_version = p2_label:match('(Linux)-([%d|.]+)') - end + romBoardName="$(cat /tmp/sysinfo/board_name)" + if [ -z "$romBoardName" ]; then + print_json 'error' 'NO_BOARD_NAME' + return + fi - if p2_label then - if p2_label:find("LEDE") then p2_os = "LEDE" end - if p2_label:find("OpenWrt") then p2_os = "OpenWrt" end - if p.vendorName and p2_label:find(p.vendorName) then p2_os = p.vendorName end - end + p="$(find_device_data "$romBoardName")" + if [ -z "$p" ] || [ ! -s "$p" ]; then + print_json 'rom_board_name' "$romBoardName" + return + fi + + json_load_file "$p" + for i in vendorName deviceName partition1MTD partition2MTD labelOffset \ + bootEnv1 bootEnv1Partition1Value bootEnv1Partition2Value \ + bootEnv2 bootEnv2Partition1Value bootEnv2Partition2Value; do + json_get_var $i "$i" + done + json_cleanup + + if [ -n "$labelOffset" ]; then + if [ -n "$partition1MTD" ]; then + p1_label="$(dd if="/dev/${partition1MTD}" bs=1 skip="${labelOffset}" count=64 2>/dev/null)" + if [ -n "$p1_label" ]; then + p1_version="$(echo "$p1_label" | sed -n "s/\(.*\)Linux-\([0-9.]\+\).*$/\2/p")" + if [ "${p1_label//LEDE}" != "$p1_label" ]; then p1_os="LEDE"; fi + if [ "${p1_label//OpenWrt}" != "$p1_label" ]; then p1_os="OpenWrt"; fi + if [ -n "$vendorName" ] && [ "${p1_label//$vendorName}" != "$p1_label" ]; then + p1_os="$vendorName" + fi + fi + if [ -z "$p1_os" ]; then + p1_os="${vendorName:-Unknown}/Unknown" + fi + fi + + if [ -n "$partition2MTD" ]; then + p2_label="$(dd if="/dev/${partition2MTD}" bs=1 skip="${labelOffset}" count=64 2>/dev/null)" + if [ -n "$p2_label" ]; then + p2_version="$(echo "$p2_label" | sed -n "s/\(.*\)Linux-\([0-9.]\+\).*$/\2/p")" + if [ "${p2_label//LEDE}" != "$p2_label" ]; then p2_os="LEDE"; fi + if [ "${p2_label//OpenWrt}" != "$p2_label" ]; then p2_os="OpenWrt"; fi + if [ -n "$vendorName" ] && [ "${p2_label//$vendorName}" != "$p2_label" ]; then + p2_os="$vendorName" + fi + fi + if [ -z "$p2_os" ]; then + p2_os="${vendorName:-Unknown}/Unknown" + fi + fi + else + p1_os="${vendorName}/Unknown (Compressed)" + p2_os="${vendorName}/Unknown (Compressed)" + fi + + if [ -n "$bootEnv1" ]; then + if [ -x "/usr/sbin/fw_printenv" ] && [ -x "/usr/sbin/fw_setenv" ]; then + current_partition="$(/usr/sbin/fw_printenv -n "${bootEnv1}")" + fi + else + if [ -z "$zyxelFlagPartition" ]; then + zyxelFlagPartition="$(find_mtd_part 0:DUAL_FLAG 2>/dev/null)" + fi + if [ -n "$zyxelFlagPartition" ]; then + current_partition="$(dd if="${zyxelFlagPartition}" bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 "%d"')" + else + print_json 'error' 'NO_DUAL_FLAG' + logger "Unable to find Dual Boot Environment or Dual Boot Flag Partition." + return + fi + fi + + if is_alt_mountable "$partition1MTD" "$partition2MTD"; then + if [ "$current_partition" = "$bootEnv1Partition1Value" ]; then + op_ubi=$(( ${partition2MTD:3:3} + 1 )) + else + op_ubi=$(( ${partition1MTD:3:3} + 1 )) + fi + cp_info="$(get_main_partition_os_info $op_ubi)" + op_info="$(get_alt_partition_os_info $op_ubi)" + if [ "$current_partition" = "$bootEnv1Partition1Value" ]; then + p1_os="${cp_info:-$p1_os}" + p2_os="${op_info:-$p2_os}" + else + p1_os="${op_info:-$p1_os}" + p2_os="${cp_info:-$p2_os}" + fi + fi + if [ -n "$p1_os" ] && [ -n "$p1_version" ]; then + p1_os="$p1_os (Linux ${p1_version})" + fi + if [ -n "$p2_os" ] && [ -n "$p2_version" ]; then + p2_os="$p2_os (Linux ${p2_version})" + fi + + + json_init + json_add_int 'current_partition' "$current_partition" + json_add_string 'device_name' "$vendorName $deviceName" + json_add_array 'partitions' + json_add_object + if [ "$bootEnv1Partition1Value" = "$current_partition" ]; then + json_add_string 'state' "Current" + else + json_add_string 'state' "Alternative" + fi + json_add_string 'os' "$p1_os" + json_add_int 'number' "$bootEnv1Partition1Value" + json_close_object + json_add_object + if [ "$bootEnv1Partition2Value" = "$current_partition" ]; then + json_add_string 'state' "Current" + else + json_add_string 'state' "Alternative" + fi + json_add_string 'os' "$p2_os" + json_add_int 'number' "$bootEnv1Partition2Value" + json_close_object + json_close_array + json_add_string 'rom_board_name' "$romBoardName" + json_dump; json_cleanup; +} - if not p2_os then - p2_os = (p.vendorName and p.vendorName or 'Unknown') .. "/" .. "Unknown" - end - if p2_os and p2_version then p2_os = p2_os .. " (Linux " .. p2_version .. ")" end - else - p1_os = p.vendorName .. "/" .. "Unknown" .. " (" .. "Compressed" .. ")" - p2_os = p.vendorName .. "/" .. "Unknown" .. " (" .. "Compressed" .. ")" - end +toggle_boot_partition(){ + local zyxelFlagPartition zyxelBootFlag zyxelNewBootFlag curEnvSetting newEnvSetting + local romBoardName p + local bev1 bev2 bev1p1 bev1p2 bev2p1 bev2p2 + local vendorName deviceName partition1MTD partition2MTD labelOffset + local bootEnv1 bootEnv1Partition1Value bootEnv1Partition2Value + local bootEnv2 bootEnv2Partition1Value bootEnv2Partition2Value + + romBoardName="$(cat /tmp/sysinfo/board_name)" + if [ -z "$romBoardName" ]; then + print_json 'error' 'NO_BOARD_NAME' + return + fi - if p.bootEnv1 then - if fs.access("/usr/sbin/fw_printenv") and fs.access("/usr/sbin/fw_setenv") then - current_partition = tonumber(util.trim(util.exec("fw_printenv -n " .. p.bootEnv1))) - end + p="$(find_device_data "$romBoardName")" + if [ -z "$p" ] || [ ! -s "$p" ]; then + print_json 'rom_board_name' "$romBoardName" + return + fi + + json_load_file "$p" + for i in vendorName deviceName partition1MTD partition2MTD labelOffset \ + bootEnv1 bootEnv1Partition1Value bootEnv1Partition2Value \ + bootEnv2 bootEnv2Partition1Value bootEnv2Partition2Value; do + json_get_var $i "$i" + done + json_cleanup + + bev1="$bootEnv1" + bev2="$bootEnv2" + + if [ -n "${bev1}${bev2}" ]; then # Linksys devices + if [ -n "$bev1" ]; then + curEnvSetting="$(fw_printenv -n "${bev1}")" + if [ -z "$curEnvSetting" ]; then + logger "$(printf "Unable to obtain firmware environment variable: %s." "$bev1")" + json_init + json_add_string 'error' 'NO_FIRM_ENV' + json_add_array 'args' + json_add_string "$bev1" + json_close_array + json_add_string 'rom_board_name' "$romBoardName" + json_dump; json_cleanup; + return + else + bev1p1="$bootEnv1Partition1Value" + bev1p2="$bootEnv1Partition2Value" + if [ "$curEnvSetting" = "$bev1p1" ]; then + newEnvSetting="$bev1p2" else - if not zyxelFlagPartition then zyxelFlagPartition = util.trim(util.exec(". /lib/functions.sh; find_mtd_part 0:DUAL_FLAG")) end - if zyxelFlagPartition then - current_partition = tonumber(util.exec("dd if=" .. zyxelFlagPartition .. " bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 \"%d\"'")) - else - ret.error = 'NO_DUAL_FLAG' - logger("Unable to find Dual Boot Flag Partition.") - return ret - end - end - - ret.current_partition = current_partition - - if is_alt_mountable(p.partition1MTD, p.partition2MTD) then - if current_partition == p.bootEnv1Partition1Value then - op_ubi = tonumber(p.partition2MTD:sub(4)) + 1 - else - op_ubi = tonumber(p.partition1MTD:sub(4)) + 1 - end - local cp_info, op_info = get_partition_os_info(op_ubi) - if current_partition == p.bootEnv1Partition1Value then - p1_os = cp_info or p1_os - p2_os = op_info or p2_os - else - p1_os = op_info or p1_os - p2_os = cp_info or p2_os - end - end - - ret.device_name = (p.vendorName and p.vendorName or "") .. " " .. p.deviceName - - ret.partitions = { - { - os = p1_os, - state = p.bootEnv1Partition1Value == current_partition and 'Current' or 'Alternative', - number = p.bootEnv1Partition1Value - }, - { - os = p2_os, - state = p.bootEnv1Partition2Value == current_partition and 'Current' or 'Alternative', - number = p.bootEnv1Partition2Value - } - } - end - - return ret - end - }, - toggle_boot_partition = { - call = function() - local ret = {} - local zyxelFlagPartition, zyxelBootFlag, zyxelNewBootFlag, errorCode, curEnvSetting, newEnvSetting - - local romBoardName = fs.readfile('/tmp/sysinfo/board_name') - - if not romBoardName then - ret.error = 'NO_BOARD_NAME' - return ret - end - - romBoardName = romBoardName:gsub('\n',''):gsub('%p','') - p = find_device_data(romBoardName) - local bev1, bev2 = p.bootEnv1, p.bootEnv2 - - if bev1 or bev2 then -- Linksys devices - if bev1 then - curEnvSetting = tonumber(util.trim(util.exec("fw_printenv -n " .. bev1))) - if not curEnvSetting then - logger(string.format("Unable to obtain firmware environment variable: %s.", bev1)) - ret.error = 'NO_FIRM_ENV' - ret.args = { bev1 } - return ret - else - local bev1p1, bev1p2 = p.bootEnv1Partition1Value, p.bootEnv1Partition2Value - newEnvSetting = curEnvSetting == bev1p1 and bev1p2 or bev1p1 - errorCode = sys.call("fw_setenv " .. bev1 .. " " .. newEnvSetting) - if errorCode ~= 0 then - logger(string.format("Unable to set firmware environment variable: %s to %s.", bev1, newEnvSetting)) - ret.error = 'ERR_SET_ENV' - ret.args = { bev1, newEnvSetting } - return ret - end - end - end - if bev2 then - curEnvSetting = util.trim(util.exec("fw_printenv -n " .. bev2)) - if not curEnvSetting then - logger(string.format("Unable to obtain firmware environment variable: %s.", bev2)) - ret.error = 'NO_FIRM_ENV' - ret.args = { bev2 } - return ret - else - local bev2p1, bev2p2 = p.bootEnv2Partition1Value, p.bootEnv2Partition1Value - newEnvSetting = curEnvSetting == bev2p1 and bev2p2 or bev2p1 - errorCode = sys.call("fw_setenv " .. bev2 .. " '" .. newEnvSetting .. "'") - if errorCode ~= 0 then - logger(string.format("Unable to set firmware environment variable: %s to %s.", bev2, newEnvSetting)) - ret.error = 'ERR_SET_ENV' - ret.args = { bev2, newEnvSetting } - return ret - end - end - end - else -- NetGear device - if not zyxelFlagPartition then zyxelFlagPartition = util.trim(util.exec(". /lib/functions.sh; find_mtd_part 0:DUAL_FLAG")) end - if not zyxelFlagPartition then - logger("Unable to find Dual Boot Flag Partition.") - ret.error = 'NO_DUAL_FLAG' + newEnvSetting="$bev1p1" + fi + if ! fw_setenv "$bev1" "$newEnvSetting"; then + logger "$(printf "Unable to set firmware environment variable: %s to %s." "$bev1" "$newEnvSetting")" + json_init + json_add_string 'error' 'ERR_SET_ENV' + json_add_array 'args' + json_add_string "$bev1" + json_add_string "$newEnvSetting" + json_close_array + json_add_string 'rom_board_name' "$romBoardName" + json_dump; json_cleanup; + return + fi + fi + fi + if [ -n "$bev2" ]; then + curEnvSetting="$(fw_printenv -n "${bev2}")" + if [ -z "$curEnvSetting" ]; then + logger "$(printf "Unable to obtain firmware environment variable: %s." "$bev2")" + json_init + json_add_string 'error' 'NO_FIRM_ENV' + json_add_array 'args' + json_add_string "$bev2" + json_close_array + json_add_string 'rom_board_name' "$romBoardName" + json_dump; json_cleanup; + return + else + bev2p1="$bootEnv2Partition1Value" + bev2p2="$bootEnv2Partition2Value" + if [ "$curEnvSetting" = "$bev2p1" ]; then + newEnvSetting="$bev2p2" else - zyxelBootFlag = tonumber(util.exec("dd if=" .. zyxelFlagPartition .. " bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 \"%d\"'")) - zyxelNewBootFlag = zyxelBootFlag and zyxelBootFlag == 1 and "\\xff" or "\\x01" - if zyxelNewBootFlag then - errorCode = sys.call("printf \"" .. zyxelNewBootFlag .. "\" >" .. zyxelFlagPartition ) - if errorCode ~= 0 then - logger(string.format("Unable to set Dual Boot Flag Partition entry for partition: %s.", zyxelFlagPartition)) - ret.error = 'ERR_SET_DUAL_FLAG' - ret.args = { zyxelFlagPartition } - return ret - end - end - end - end - - return ret - end - } + newEnvSetting="$bev2p1" + fi + if ! fw_setenv "$bev2" "$newEnvSetting"; then + logger "$(printf "Unable to set firmware environment variable: %s to %s." "$bev2" "$newEnvSetting")" + json_init + json_add_string 'error' 'ERR_SET_ENV' + json_add_array 'args' + json_add_string "$bev2" + json_add_string "$newEnvSetting" + json_close_array + json_add_string 'rom_board_name' "$romBoardName" + json_dump; json_cleanup; + return + fi + fi + fi + json_init + json_dump; json_cleanup; + else # NetGear device + if [ -z "$zyxelFlagPartition" ]; then + zyxelFlagPartition="$(find_mtd_part 0:DUAL_FLAG 2>/dev/null)" + fi + if [ -z "$zyxelFlagPartition" ]; then + logger "Unable to find Dual Boot Flag Partition." + print_json 'error' 'NO_DUAL_FLAG' + return + else + zyxelBootFlag="$(dd if="${zyxelFlagPartition}" bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 "%d"')" + if [ "$zyxelBootFlag" = "1" ]; then + zyxelNewBootFlag="\\xff" + else + zyxelNewBootFlag="\\x01" + fi + if [ -n "$zyxelNewBootFlag" ]; then + if ! printf "%b" "$zyxelNewBootFlag" > "$zyxelFlagPartition"; then + logger "$(printf "Unable to set Dual Boot Flag Partition entry for partition: %s." "$zyxelFlagPartition")" + json_init + json_add_string 'error' 'ERR_SET_DUAL_FLAG' + json_add_array 'args' + json_add_string "$zyxelFlagPartition" + json_close_array + json_add_string 'rom_board_name' "$romBoardName" + json_dump; json_cleanup; + return + fi + fi + fi + json_init + json_dump; json_cleanup; + fi } -local function parseInput() - local parse = json.new() - local done, err - - while true do - local chunk = io.read(4096) - if not chunk then - break - elseif not done and not err then - done, err = parse:parse(chunk) - end - end - - if not done then - print(json.stringify({ error = err or "Incomplete input" })) - os.exit(1) - end - - return parse:get() -end - -local function validateArgs(func, uargs) - local method = methods[func] - if not method then - print(json.stringify({ error = "Method not found" })) - os.exit(1) - end - - if type(uargs) ~= "table" then - print(json.stringify({ error = "Invalid arguments" })) - os.exit(1) - end - - uargs.ubus_rpc_session = nil - - local k, v - local margs = method.args or {} - for k, v in pairs(uargs) do - if margs[k] == nil or - (v ~= nil and type(v) ~= type(margs[k])) - then - print(json.stringify({ error = "Invalid arguments" })) - os.exit(1) - end - end - - return method -end - -if arg[1] == "list" then - local _, method, rv = nil, nil, {} - for _, method in pairs(methods) do rv[_] = method.args or {} end - print((json.stringify(rv):gsub(":%[%]", ":{}"))) -elseif arg[1] == "call" then - local args = parseInput() - local method = validateArgs(arg[2], args) - local result, code = method.call(args) - print((json.stringify(result):gsub("^%[%]$", "{}"))) - os.exit(code or 0) -end +case "$1" in + list) + json_init + json_add_object "obtain_device_info" + json_close_object + json_add_object "toggle_boot_partition" + json_close_object + json_dump + json_cleanup + ;; + call) + case "$2" in + obtain_device_info) + obtain_device_info;; + toggle_boot_partition) + toggle_boot_partition;; + esac + ;; +esac |