From 6b271164d8d38c87ca2b54264e57217df8f1f95f Mon Sep 17 00:00:00 2001 From: Stan Grishin Date: Wed, 21 Jan 2026 03:31:28 +0000 Subject: [PATCH] luci-app-advanced-reboot: bugfix: actual partition switch At some point after r7, when I no longer had the dual boot device readily available for testing, a regression was introduced that the RPCD script would not actually perform the partition switch. Thanks to @bd0426 for report and @Jackie264 for fixing the issue. advanced-reboot.js * simplify partition number validation in handleAlternativeReboot * reformat text copy RPCD script * obtain OpenWrt version from "$OPENWRT_RELEASE" not "$PRETTY_NAME" for the snapshot compatibility * refactor parameter processing for boot_partition function * add logging/better output on error in boot_partition test.sh * introduce a test file for heartbeat check of the RPCD script Signed-off-by: Stan Grishin --- .../luci-app-advanced-reboot/Makefile | 2 +- .../resources/view/system/advanced-reboot.js | 79 ++++++++----------- .../usr/share/rpcd/ucode/luci.advanced-reboot | 73 ++++++++++------- applications/luci-app-advanced-reboot/test.sh | 5 ++ 4 files changed, 85 insertions(+), 74 deletions(-) create mode 100644 applications/luci-app-advanced-reboot/test.sh diff --git a/applications/luci-app-advanced-reboot/Makefile b/applications/luci-app-advanced-reboot/Makefile index 30ac0c145850..606e2d969b28 100644 --- a/applications/luci-app-advanced-reboot/Makefile +++ b/applications/luci-app-advanced-reboot/Makefile @@ -7,7 +7,7 @@ PKG_NAME:=luci-app-advanced-reboot PKG_LICENSE:=AGPL-3.0-or-later PKG_MAINTAINER:=Stan Grishin PKG_VERSION:=1.1.1 -PKG_RELEASE:=9 +PKG_RELEASE:=15 PKG_BUILD_DEPENDS:=jq/host diff --git a/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced-reboot.js b/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced-reboot.js index 51c09af70d31..2351bf15d750 100644 --- a/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced-reboot.js +++ b/applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced-reboot.js @@ -108,8 +108,8 @@ return view.extend({ E( "p", _( - 'WARNING: Power off might result in a reboot on a device which doesn\'t support power off.

\ - Click "Proceed" below to power off your device.' + "WARNING: Power off might result in a reboot on a device which doesn't support power off.

" + + "Click \"Proceed\" below to power off your device." ) ), E("div", { class: "right" }, [ @@ -192,7 +192,9 @@ return view.extend({ "p", { class: "spinning" }, _( - "The system is rebooting to an alternative partition now.
DO NOT POWER OFF THE DEVICE!
Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings." + "The system is rebooting to an alternative partition now.
DO NOT POWER OFF THE DEVICE!
" + + "Wait a few minutes before you try to reconnect." + + " It might be necessary to renew the address of your computer to reach the device again, depending on your settings." ) ), ]); @@ -216,23 +218,10 @@ return view.extend({ ); }, - handleAlternativeReboot: function () { - // accept either (ev, number) or (number, ev) - var pn = null; + handleAlternativeReboot: function (number, ev) { + var pn = Number(number); - for (var i = 0; i < arguments.length; i++) { - var a = arguments[i]; - if (typeof a === "number" && !Number.isNaN(a)) { - pn = a; - break; - } - if (typeof a === "string" && a !== "" && !Number.isNaN(Number(a))) { - pn = Number(a); - break; - } - } - - if (pn == null) { + if (Number.isNaN(pn)) { // fall back / safety ui.addNotification(null, E("p", _("Missing partition number"))); return Promise.resolve(); @@ -247,12 +236,12 @@ return view.extend({ E( "p", _( - 'WARNING: An alternative partition might have its own settings and completely different firmware.

\ -As your network configuration and WiFi SSID/password on alternative partition might be different,\ -you might have to adjust your computer settings to be able to access your device once it reboots.

\ -Please also be aware that alternative partition firmware might not provide an easy way to switch active partition\ -and boot back to the currently active partition.

\ -Click "Proceed" below to reboot device to the selected partition.' + "WARNING: An alternative partition might have its own settings and completely different firmware.

" + + "As your network configuration and WiFi SSID/password on alternative partition might be different," + + " you might have to adjust your computer settings to be able to access your device once it reboots.

" + + "Please also be aware that alternative partition firmware might not provide an easy way to switch active partition" + + " and boot back to the currently active partition.

" + + "Click \"Proceed\" below to reboot device to the selected partition." ) ), E("div", { class: "right" }, [ @@ -283,8 +272,8 @@ Click "Proceed" below to reboot device to the selected partition.' typeof fn === "function" ? fn(a) : _("Unexpected error: %s").format( - String(res.error) - ); + String(res.error) + ); return ui.addNotification(null, E("p", msg)); } @@ -395,18 +384,18 @@ Click "Proceed" below to reboot device to the selected partition.' { class: "alert-message warning" }, _( "Warning: Device (%s) is unknown or isn't a dual-firmware device!" + - "%s" + - "If you are seeing this on an OpenWrt dual-firmware supported device," + - "%s" + - "please refer to " + - "%sHow to add a new device section of the README%s." + "%s" + + "If you are seeing this on an OpenWrt dual-firmware supported device," + + "%s" + + "please refer to " + + "%sHow to add a new device section of the README%s." ).format( warnBoard, "

", "
", '', + pkg.URL + + '#how-to-add-a-new-device" target="_blank">', "" ) ) @@ -474,18 +463,18 @@ Click "Proceed" below to reboot device to the selected partition.' body.appendChild( poweroff_supported ? E( - "button", - { - class: "btn cbi-button cbi-button-apply important", - click: ui.createHandlerFn(this, "handlePowerOff"), - }, - _("Perform power off...") - ) + "button", + { + class: "btn cbi-button cbi-button-apply important", + click: ui.createHandlerFn(this, "handlePowerOff"), + }, + _("Perform power off...") + ) : E( - "p", - { class: "alert-message warning" }, - _("Warning: This system does not support powering off!") - ) + "p", + { class: "alert-message warning" }, + _("Warning: This system does not support powering off!") + ) ); return body; diff --git a/applications/luci-app-advanced-reboot/root/usr/share/rpcd/ucode/luci.advanced-reboot b/applications/luci-app-advanced-reboot/root/usr/share/rpcd/ucode/luci.advanced-reboot index 10673dee6722..5c316ec69b51 100644 --- a/applications/luci-app-advanced-reboot/root/usr/share/rpcd/ucode/luci.advanced-reboot +++ b/applications/luci-app-advanced-reboot/root/usr/share/rpcd/ucode/luci.advanced-reboot @@ -161,17 +161,9 @@ function get_volume_info(path) { let pretty = command( ". " + shellquote(root + "etc/os-release") + - ' 2>/dev/null; echo "$PRETTY_NAME" 2>/dev/null' + ' 2>/dev/null; echo "$OPENWRT_RELEASE" 2>/dev/null' ); if (pretty) label = trim(pretty); - if (label && match(label, /SNAPSHOT/)) { - let rel = command( - 'grep -m1 "^DISTRIB_RELEASE=" ' + - shellquote(root + "etc/openwrt_release") + - " 2>/dev/null | awk -F= '{gsub(/[\"'']/, \"\", $2); print $2}'" - ); - if (rel) label = "OpenWrt " + trim(rel); - } let kver = null; if (root == "/") { @@ -496,18 +488,31 @@ function obtain_device_info() { * Accepts ubus args: { "number": "" }. * Uses the device schema to map partition numbers to env values or dual-flag bytes. * - * @param {{args:{number:String|Number}}} req + * @param {{number:String}} req * @returns {Object} {} on success; {error:..., ...} on failure. * @sideeffects Calls fw_setenv/fw_saveenv or writes to dual-flag MTD. */ function boot_partition(req) { + log("boot_partition req=" + sprintf("%J", req?.args)); /* extract target partition number from RPC args */ let number; - if (req && req.number != null) number = int(req.number); - if (!number) + let val; + + if (type(req) == "array" && length(req) > 0) + val = req[0]?.number; + else if (type(req?.args) == "object") + val = req.args.number; + else if (type(req) == "object") + val = req.number; + + if (val != null) val = "" + val; + if (val != null && match(val, /^[0-9]+$/)) + number = int(val); + + if (number == null) return { error: "INVALID_ARG", - detail: "number is required and must be numeric", + detail: "number is required and must be numeric (got: " + sprintf("%J", req?.args) + ")", }; let board = get_board_name(); @@ -540,23 +545,32 @@ function boot_partition(req) { for (let j = 0; j < length(params); j++) { let param = params[j]; let value = target.param_values ? target.param_values[j] : null; + let rc = "0"; + if (param == null || param == "") continue; if (value == null) continue; - let rc = command( - setcmd + - " " + - shellquote(param) + - " " + - shellquote("" + value) + - " 2>/dev/null; echo $?" - ); - if (rc != "0") - return { - error: "ERR_SET_ENV", - args: [param, "" + value], - rom_board_name: board, - }; - if (savecmd) rc = command(savecmd + " 2>/dev/null; echo $?"); + + if (setcmd) { + let cmd = setcmd + + " " + + shellquote(param) + + " " + + shellquote("" + value) + + " 2>/dev/null; echo $?"; + log("boot_partition running: " + cmd); + rc = command(cmd); + if (rc != "0") + return { + error: "ERR_SET_ENV", + args: [param, "" + value], + rom_board_name: board, + }; + } + if (savecmd) { + let cmd = savecmd + " 2>/dev/null; echo $?"; + log("boot_partition running: " + cmd); + rc = command(cmd); + } if (rc != "0") return { error: "ERR_SAVE_ENV", rom_board_name: board }; } } else { @@ -564,6 +578,9 @@ function boot_partition(req) { if (!df) return { error: "NO_DUAL_FLAG", rom_board_name: board }; if (!file_exists(df)) return { error: "NO_DUAL_FLAG_BLOCK", rom_board_name: board }; + + log("boot_partition setting dual flag: " + df + " to " + target.param_values[0]); + if (!write_dual_flag_value(df, target.param_values[0])) return { error: "ERR_SET_DUAL_FLAG", args: [df], rom_board_name: board }; } diff --git a/applications/luci-app-advanced-reboot/test.sh b/applications/luci-app-advanced-reboot/test.sh new file mode 100644 index 000000000000..273eeb8924ea --- /dev/null +++ b/applications/luci-app-advanced-reboot/test.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +ubus -S call luci.advanced-reboot obtain_device_info | grep 'NO_BOARD_NAME_MATCH' && \ +ubus -S call luci.advanced-reboot boot_partition '{ "number": "1" }' | grep 'NO_BOARD_NAME_MATCH' && \ +ubus -S call luci.advanced-reboot boot_partition '{ "number": "2" }' | grep 'NO_BOARD_NAME_MATCH'