luci-app-advanced-reboot: update to 1.1.1
authorStan Grishin <redacted>
Sun, 24 Aug 2025 02:11:28 +0000 (02:11 +0000)
committerStan Grishin <redacted>
Tue, 6 Jan 2026 23:28:20 +0000 (23:28 +0000)
This is a massive overwrite of the RPCD code from shell scrit to ucode
which in turn brought:
* update to the device json schema, which is now:
  * more structured
  * no weird names/object in json
  * customizable get, set, save commands per device (still need to be
    defined in ACL)
  * single partitions array now holding all data for
    toggling/labels/altMount
  * support for more than 2 bootable partition devices
* a _device_json_transform.jq file to translate schema from old format to
  new one for any WIP devices
* simplification of RPCD script as object can now be returned
* adjustments to the Javascript to parse new error messages and new RPCD
  reply structure
* integrate @systemcrash provided code/suggestions

I have tested both UBI volumes and dd-based information gathering on
alternative partition, I'd still welcome:
* tests on as many Linksys devices for actual partition toggling
  (rebooting to alternative)
* tests for both information gathering and partition toggling on:
  * "d-link,dgs-1210-28"
  * "mercusys,mr90x-v1"
  * "zyxel,nbg6817"

I also gladly welcome any code reviews for both updated javascript and
ucode.

Signed-off-by: Stan Grishin <redacted>
55 files changed:
applications/luci-app-advanced-reboot/Makefile
applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced-reboot.js [moved from applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced_reboot.js with 53% similarity]
applications/luci-app-advanced-reboot/root/usr/libexec/rpcd/luci.advanced_reboot [deleted file]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/linksys-ea9500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/netgear-wac510.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/xiaomi-ax3600.json [new file with mode: 0644]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/xiaomi-ax9000.json [new file with mode: 0644]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.json [new file with mode: 0644]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/_device_json_transform.jq [new file with mode: 0644]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/dlink-fgs1210-28.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-e4200v2-ea4500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-e4200v2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-e7350.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea3500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea4500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea6350v3.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea6350v4.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea7300v1.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea7300v2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea7500v1.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea7500v2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea8100v1.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea8100v2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea8300.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-ea8500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr5500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr7350.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr7500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr8300.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr9000.json [new file with mode: 0644]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx2000.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx4200v1.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx4200v2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx4300.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx5300.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx5500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mx8500.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-spnmx56.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-whw01v1.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-whw03.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-whw03v2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-wrt1200ac.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-wrt1900ac.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-wrt1900acs.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-wrt1900acv2.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-wrt3200acm.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-wrt32x.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/mercusys-mr90xv1.json
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/netgear-gs308t-v1.json [new file with mode: 0644]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/xiaomi-ax3600.json [deleted file]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/xiaomi-ax9000.json [deleted file]
applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/zyxel-nbg6817.json
applications/luci-app-advanced-reboot/root/usr/share/luci/menu.d/luci-app-advanced-reboot.json
applications/luci-app-advanced-reboot/root/usr/share/rpcd/acl.d/luci-app-advanced-reboot.json
applications/luci-app-advanced-reboot/root/usr/share/rpcd/ucode/luci.advanced-reboot [new file with mode: 0644]

index dec193f77d9e6d4b69343d74c9bea1388f640c71..30ac0c145850e071fb72890750c56b907bfd9e8c 100644 (file)
@@ -1,13 +1,15 @@
 # SPDX-License-Identifier: AGPL-3.0-or-later
-# Copyright 2017-2025 MOSSDeF, Stan Grishin (stangri@melmac.ca).
+# Copyright 2017-2026 MOSSDeF, Stan Grishin (stangri@melmac.ca).
 
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=luci-app-advanced-reboot
 PKG_LICENSE:=AGPL-3.0-or-later
 PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
-PKG_VERSION:=1.1.0
-PKG_RELEASE:=1
+PKG_VERSION:=1.1.1
+PKG_RELEASE:=9
+
+PKG_BUILD_DEPENDS:=jq/host
 
 LUCI_TITLE:=Advanced Linksys Reboot Web UI
 LUCI_URL:=https://github.com/stangri/luci-app-advanced-reboot/
@@ -26,4 +28,21 @@ endef
 
 include ../../luci.mk
 
+# Prune individual device JSON directories from the package image.
+# The default LuCI install logic from luci.mk copies everything under
+# htdocs/, root/, etc. We let it run, then remove folders we keep only
+# in source control.
+define Package/$(PKG_NAME)/install
+       $(call Package/$(PKG_NAME)/install/default,$(1))
+       @mkdir -p $(1)/usr/share/advanced-reboot
+       @if [ -d $(1)/usr/share/advanced-reboot/devices ] \
+               && ls $(1)/usr/share/advanced-reboot/devices/*.json >/dev/null 2>&1; then \
+                       $(STAGING_DIR_HOST)/bin/jq -s '.' $(1)/usr/share/advanced-reboot/devices/*.json \
+                               > $(1)/usr/share/advanced-reboot/devices.json; \
+       fi
+       @if [ -s $(1)/usr/share/advanced-reboot/devices.json ]; then \
+               $(RM) -r $(1)/usr/share/advanced-reboot/devices $(1)/usr/share/advanced-reboot/devices.disabled || true; \
+       fi
+endef
+
 # call BuildPackage - OpenWrt buildroot signature
similarity index 53%
rename from applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced_reboot.js
rename to applications/luci-app-advanced-reboot/htdocs/luci-static/resources/view/system/advanced-reboot.js
index 20c6fccac8fa13530e31ae84a8fe05ece5368cf2..51c09af70d317a01a98d0d6c4d5d34172ca98d39 100644 (file)
@@ -43,6 +43,31 @@ return view.extend({
                                args[1]
                        );
                },
+               BOARD_NAME_MATCH_FILE_READ: function (args) {
+                       var b = args && args[0] ? args[0] : "";
+                       return _("Error accessing the device definition for board: %s").format(b);
+               },
+               NO_BOARD_NAME_MATCH: function (args) {
+                       var b = args && args[0] ? args[0] : "";
+                       /* This entry is unused in generic error banner; we render a dedicated warning below. */
+                       return _("Unknown or unsupported dual-partition device: %s").format(b);
+               },
+               INVALID_ARG: function (args) {
+                       var d = args && args[0] ? args[0] : _("invalid argument");
+                       return _("Invalid request: %s.").format(d);
+               },
+               PARTITION_NOT_FOUND: function (args) {
+                       var n = args && args[0] ? args[0] : "?";
+                       return _("Partition %s was not found in the device definition.").format(
+                               n
+                       );
+               },
+               ERR_SAVE_ENV: function (args) {
+                       return _("Unable to save environment changes.");
+               },
+               NO_TARGET_FLAG: function (args) {
+                       return _("Target partition flag is not defined for this device.");
+               },
        },
 
        callReboot: rpc.declare({
@@ -52,14 +77,15 @@ return view.extend({
        }),
 
        callObtainDeviceInfo: rpc.declare({
-               object: "luci.advanced_reboot",
+               object: "luci.advanced-reboot",
                method: "obtain_device_info",
                expect: {},
        }),
 
-       callTogglePartition: rpc.declare({
-               object: "luci.advanced_reboot",
-               method: "toggle_boot_partition",
+       callBootPartition: rpc.declare({
+               object: "luci.advanced-reboot",
+               method: "boot_partition",
+               params: ["number"],
                expect: {},
        }),
 
@@ -190,31 +216,43 @@ return view.extend({
                );
        },
 
-       handleAlternativeReboot: function (ev) {
-               return Promise.all([
-                       L.resolveDefault(fs.stat("/usr/sbin/fw_printenv"), null),
-                       L.resolveDefault(fs.stat("/usr/sbin/fw_setenv"), null),
-               ]).then(
-                       L.bind(function (data) {
-                               if (!data[0] || !data[1]) {
-                                       return ui.addNotification(
-                                               null,
-                                               E("p", _("No access to fw_printenv or fw_printenv!"))
-                                       );
-                               }
+       handleAlternativeReboot: function () {
+               // accept either (ev, number) or (number, ev)
+               var pn = null;
+
+               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) {
+                       // fall back / safety
+                       ui.addNotification(null, E("p", _("Missing partition number")));
+                       return Promise.resolve();
+               }
+               return Promise.all([]).then(
+                       L.bind(function (data) {
                                ui.showModal(
-                                       _("Reboot Device to an Alternative Partition") + " - " + _("Confirm"),
+                                       _("Reboot Device to Partition: %s").format(
+                                               String(pn).padStart(2, "0")
+                                       ),
                                        [
                                                E(
                                                        "p",
                                                        _(
                                                                'WARNING: An alternative partition might have its own settings and completely different firmware.<br /><br />\
-                               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.<br /><br />\
-                               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.<br /><br />\
-                               Click "Proceed" below to reboot device to an alternative partition.'
+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.<br /><br />\
+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.<br /><br />\
+Click "Proceed" below to reboot device to the selected partition.'
                                                        )
                                                ),
                                                E("div", { class: "right" }, [
@@ -231,7 +269,32 @@ return view.extend({
                                                                "button",
                                                                {
                                                                        class: "btn cbi-button cbi-button-positive important",
-                                                                       click: L.bind(this.handleTogglePartition, this),
+                                                                       click: L.bind(function () {
+                                                                               this.callBootPartition(String(pn))
+                                                                                       .then(
+                                                                                               L.bind(function (res) {
+                                                                                                       ui.hideModal();
+                                                                                                       if (res && res.error) {
+                                                                                                               var fn = this.translateTable[res.error];
+                                                                                                               var a = Array.isArray(res.args) ? res.args : [];
+                                                                                                               if (res.detail) a = [res.detail].concat(a);
+
+                                                                                                               var msg =
+                                                                                                                       typeof fn === "function"
+                                                                                                                               ? fn(a)
+                                                                                                                               : _("Unexpected error: %s").format(
+                                                                                                                                               String(res.error)
+                                                                                                                                 );
+
+                                                                                                               return ui.addNotification(null, E("p", msg));
+                                                                                                       }
+                                                                                                       return this.handleReboot();
+                                                                                               }, this)
+                                                                                       )
+                                                                                       .catch(function (e) {
+                                                                                               ui.addNotification(null, E("p", e.message));
+                                                                                       });
+                                                                       }, this),
                                                                },
                                                                _("Proceed")
                                                        ),
@@ -242,32 +305,39 @@ return view.extend({
                );
        },
 
-       parsePartitions: function (partitions) {
+       parsePartitions: function (partitions, activeNumber) {
                var res = [];
+               var active = activeNumber != null ? String(Number(activeNumber)) : null;
 
-               partitions.forEach(
+               (partitions || []).forEach(
                        L.bind(function (partition) {
-                               var func, text;
-
-                               if (partition.state == "Current") {
-                                       func = "handleReboot";
-                                       text = _("Reboot to current partition");
-                               } else {
-                                       func = "handleAlternativeReboot";
-                                       text = _("Reboot to alternative partition...");
-                               }
+                               var isActive =
+                                       active != null && String(Number(partition.number)) === active;
+                               var func = isActive ? "handleReboot" : "handleAlternativeReboot";
+                               var status = isActive ? _("Current") : _("Alternative");
+                               var text = isActive
+                                       ? _("Reboot to current partition")
+                                       : _("Reboot to this partition...");
+
+                               var fwLabel = partition.label || _("Unknown");
+                               fwLabel +=
+                                       partition.os && partition.os != ""
+                                               ? " (Linux " + partition.os + ")"
+                                               : "";
 
                                res.push([
-                                       (partition.number + 0x100).toString(16).substr(-2).toUpperCase(),
-                                       _(partition.state),
-                                       partition.os
-                                               .replace("Unknown", _("Unknown"))
-                                               .replace("Compressed", _("Compressed")),
+                                       String(Number(partition.number || 0)).padStart(2, "0"),
+                                       status,
+                                       fwLabel,
                                        E(
                                                "button",
                                                {
                                                        class: "btn cbi-button cbi-button-apply important",
-                                                       click: ui.createHandlerFn(this, func),
+                                                       click: ui.createHandlerFn(
+                                                               this,
+                                                               func,
+                                                               String(Number(partition.number))
+                                                       ),
                                                },
                                                text
                                        ),
@@ -293,6 +363,17 @@ return view.extend({
 
                var body = E([E("h2", _("Advanced Reboot"))]);
 
+               var device_name = "";
+               var active_num = null;
+               var partitions = [];
+               if (device_info && device_info.device && device_info.partitions) {
+                       var d = device_info.device;
+                       device_name = [d.vendor || "", d.model || ""].filter(Boolean).join(" ");
+                       active_num =
+                               d.partition_active != null ? String(d.partition_active) : null;
+                       partitions = device_info.partitions || [];
+               }
+
                for (var config in changes || {}) {
                        body.appendChild(
                                E(
@@ -304,19 +385,65 @@ return view.extend({
                        break;
                }
 
-               if (device_info.error)
-                       body.appendChild(
-                               E(
-                                       "p",
-                                       { class: "alert-message warning" },
-                                       _("ERROR: ") + this.translateTable[device_info.error]()
-                               )
-                       );
+               /* Error handling */
+               if (device_info && device_info.error) {
+                       if (device_info.error === "NO_BOARD_NAME_MATCH") {
+                               var warnBoard = device_info.rom_board_name || "";
+                               body.appendChild(
+                                       E(
+                                               "p",
+                                               { 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."
+                                               ).format(
+                                                       warnBoard,
+                                                       "<br /><br />",
+                                                       "<br />",
+                                                       '<a href="' +
+                                                               pkg.URL +
+                                                               '#how-to-add-a-new-device" target="_blank">',
+                                                       "</a>"
+                                               )
+                                       )
+                               );
+                       } else {
+                               var err = device_info.error;
+                               var fn = this.translateTable[err];
+                               var args = [];
+                               if (device_info.detail) args = [device_info.detail];
+                               else if (device_info.rom_board_name)
+                                       args = [device_info.rom_board_name];
+
+                               if (typeof fn === "function") {
+                                       body.appendChild(
+                                               E("p", { class: "alert-message warning" }, _("ERROR: ") + fn(args))
+                                       );
+                               } else {
+                                       body.appendChild(
+                                               E(
+                                                       "p",
+                                                       { class: "alert-message warning" },
+                                                       _("ERROR: %s").format(err)
+                                               )
+                                       );
+                               }
+                       }
+               }
 
-               body.appendChild(
-                       E("h3", (device_info.device_name || "") + _(" Partitions"))
-               );
-               if (device_info.device_name) {
+               body.appendChild(E("h3", (device_name || "") + _(" Partitions")));
+
+               if (
+                       device_info &&
+                       device_info.device &&
+                       Array.isArray(partitions) &&
+                       partitions.length
+               ) {
+                       /* render table as before */
                        var partitions_table = E("table", { class: "table" }, [
                                E("tr", { class: "tr table-titles" }, [
                                        E("th", { class: "th" }, [_("Partition")]),
@@ -328,33 +455,17 @@ return view.extend({
 
                        cbi_update_table(
                                partitions_table,
-                               this.parsePartitions(device_info.partitions)
+                               this.parsePartitions(partitions, active_num)
                        );
 
                        body.appendChild(partitions_table);
-               } else {
+               } else if (!device_info || !device_info.error) {
+                       /* no partitions and no explicit error */
                        body.appendChild(
                                E(
                                        "p",
                                        { class: "alert-message warning" },
-                                       device_info.rom_board_name
-                                               ? _(
-                                                               "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."
-                                                 ).format(
-                                                               device_info.rom_board_name,
-                                                               "<br /><br />",
-                                                               "<br />",
-                                                               '<a href="' +
-                                                                       pkg.URL +
-                                                                       '#how-to-add-a-new-device" target="_blank">',
-                                                               "</a>"
-                                                 )
-                                               : _("Warning: Unable to obtain device information!")
+                                       _("Warning: Unable to obtain device information!")
                                )
                        );
                }
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
deleted file mode 100755 (executable)
index af9dd81..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
-#!/bin/sh
-# Copyright 2017-2025 Stan Grishin (stangri@melmac.ca)
-# shellcheck disable=SC2039,SC1091,SC3043,SC3057,SC3060
-
-
-# TechRef: https://openwrt.org/docs/techref/rpcd
-# TESTS
-# ubus -v list luci.advanced_reboot
-# ubus -S call luci.advanced_reboot obtain_device_info '{"name": "advanced-reboot" }'
-# ubus -S call luci.advanced_reboot toggle_boot_partition '{"name": "advanced-reboot" }'
-
-readonly devices_dir="/usr/share/advanced-reboot/devices/"
-
-. /lib/functions.sh
-. /usr/share/libubox/jshn.sh
-
-packageName='advanced-reboot'
-debug() { local i j; for i in "$@"; do eval "j=\$$i"; logger "${packageName:+-t $packageName}" "${i}: ${j} "; done; }
-
-logger() { /usr/bin/logger -t advanced-reboot "$*"; }
-is_present() { command -v "$1" >/dev/null 2>&1; }
-
-is_alt_mountable() {
-       local p1_mtd="$1" p2_mtd="$2"
-       if [ "${p1_mtd:0:3}" = "mtd" ] && [ "${p2_mtd:0:3}" = "mtd" ] && \
-               is_present 'ubiattach' && \
-               is_present 'ubiblock' && \
-               is_present 'mount'; then
-               return 0
-       else
-               return 1
-       fi
-}
-
-alt_partition_mount() {
-       local ubi_dev op_ubi="$1" ubi_vol="${2:-0}"
-       mkdir -p /var/alt_rom
-       ubi_dev="$(ubiattach -m "$op_ubi" 2>/dev/null)"
-       ubi_dev="$(echo "$ubi_dev" | sed -n "s/^UBI device number\s*\(\d*\),.*$/\1/p")"
-       if [ -z "$ubi_dev" ]; then 
-               ubidetach -m "$op_ubi" >/dev/null 2>&1
-               return 1
-       fi
-       ubiblock --create "/dev/ubi${ubi_dev}_${ubi_vol}" >/dev/null 2>&1 && \
-       mount -t squashfs -r "/dev/ubiblock${ubi_dev}_${ubi_vol}" /var/alt_rom >/dev/null 2>&1
-}
-
-alt_partition_unmount() {
-       local mtdCount i=0 op_ubi="$1" ubi_vol="${2:-0}"
-       mtdCount="$(ubinfo | grep 'Present UBI devices' | tr ',' '\n' | grep -c 'ubi')"
-       [ -z "$mtdCount" ] && mtdCount=10
-       grep -qs '/var/alt_rom ' /proc/mounts && umount /var/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}_${ubi_vol}" >/dev/null 2>&1
-                       ubidetach -m "$op_ubi" >/dev/null 2>&1
-                       rm -rf /var/alt_rom
-               fi
-               i=$((i + 1))
-       done
-}
-
-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"
-}
-
-get_alt_partition_os_info(){
-       local op_info op_ubi="$1" vendor_name="$2" ubi_vol="$3"
-       logger "attempting to mount alternative partition (mtd${op_ubi})"
-       alt_partition_unmount "$op_ubi" "$ubi_vol"
-       alt_partition_mount "$op_ubi" "$ubi_vol"
-       if [ -s "/var/alt_rom/etc/os-release" ]; then
-# shellcheck disable=SC2031
-               op_info="$(. /var/alt_rom/etc/os-release && echo "$PRETTY_NAME")"
-               if [ "${op_info//SNAPSHOT}" != "$op_info" ]; then
-                       op_info="$(. /var/alt_rom/etc/os-release && echo "${OPENWRT_RELEASE%%-*}")"
-               fi
-       fi
-       if [ -s "/var/alt_rom/etc/partition_config/soft-version" ]; then
-               op_info="${vendor_name:+$vendor_name }$(awk -F: '$1=="soft_ver" { print $2 ;}' /var/alt_rom/etc/partition_config/soft-version)"
-       fi
-       logger "attempting to unmount alternative partition (mtd${op_ubi})"
-       alt_partition_unmount "$op_ubi" "$ubi_vol"
-       echo "$op_info"
-}
-
-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
-}
-
-print_json() { json_init; json_add_string "$1" "$2"; json_dump; json_cleanup; }
-
-obtain_device_info(){
-       local romBoardName p zyxelFlagPartition i
-       local vendorName deviceName partition1MTD partition2MTD labelOffset
-       local opOffset ubiVolume
-       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
-
-       romBoardName="$(cat /tmp/sysinfo/board_name)"
-       if [ -z "$romBoardName" ]; then
-               print_json 'error' 'NO_BOARD_NAME'
-               return
-       fi
-
-       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 \
-               opOffset ubiVolume; 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 | tr -d '\0')"
-                       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 | tr -d '\0')"
-                       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
-               for i in '0:dual_flag' '0:DUAL_FLAG'; do
-                       zyxelFlagPartition="$(find_mtd_part "$i" 2>/dev/null)"
-                       [ -n "$zyxelFlagPartition" ] && break
-               done
-               if [ -z "$zyxelFlagPartition" ]; then
-                       print_json 'error' 'NO_DUAL_FLAG'
-                       logger "Unable to find Dual Boot Environment or Dual Boot Flag Partition."
-                       return
-               elif [ ! -b "$zyxelFlagPartition" ]; then
-                       print_json 'error' 'NO_DUAL_FLAG_BLOCK'
-                       logger "The Dual Boot Flag Partition: $zyxelFlagPartition is not block device."
-                       return
-               else
-                       current_partition="$(dd if="${zyxelFlagPartition}" bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 "%d"')"
-               fi
-       fi
-
-       if is_alt_mountable "$partition1MTD" "$partition2MTD"; then
-               opOffset="${opOffset:-1}"
-               ubiVolume="${ubiVolume:-0}"
-               # Robustly extract numeric MTD indices (handles mtd2, mtd22, mtd22ro, etc.)
-               local p1num p2num
-               p1num="${partition1MTD#mtd}"; p1num="${p1num%%[^0-9]*}"
-               p2num="${partition2MTD#mtd}"; p2num="${p2num%%[^0-9]*}"
-               [ -n "$p1num" ] || p1num=0
-               [ -n "$p2num" ] || p2num=0
-               if [ "$current_partition" = "$bootEnv1Partition1Value" ]; then
-                       op_ubi=$(( p2num + opOffset ))
-               else
-                       op_ubi=$(( p1num + opOffset ))
-               fi
-               cp_info="$(get_main_partition_os_info "$op_ubi")"
-               op_info="$(get_alt_partition_os_info "$op_ubi" "$vendorName" "$ubiVolume")"
-               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;
-}
-
-toggle_boot_partition(){
-       local zyxelFlagPartition i 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
-
-       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
-                                       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
-                                       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 >&4; json_cleanup;
-                                       return
-                               fi
-                       fi
-               fi
-               json_init
-               json_dump; json_cleanup;
-       else # NetGear device
-               for i in '0:dual_flag' '0:DUAL_FLAG'; do
-                       zyxelFlagPartition="$(find_mtd_part "$i" 2>/dev/null)"
-                       [ -n "$zyxelFlagPartition" ] && break
-               done
-               if [ -z "$zyxelFlagPartition" ]; then
-                       print_json 'error' 'NO_DUAL_FLAG'
-                       logger "Unable to find Dual Boot Environment or Dual Boot Flag Partition."
-                       return
-               elif [ ! -b "$zyxelFlagPartition" ]; then
-                       print_json 'error' 'NO_DUAL_FLAG_BLOCK'
-                       logger "The Dual Boot Flag Partition: $zyxelFlagPartition is not block device."
-                       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 >&4; json_cleanup;
-       fi
-}
-
-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
index 7c84413e74f44bee979da572e938da2513324955..f952abecf256153850e8bc5c88c154e3410e24dd 100644 (file)
@@ -1,14 +1,29 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA9500",
-       "boardName": "linksys-panamera",
-       "partition1MTD": "mtd3",
-       "partition2MTD": "mtd6",
-       "labelOffset": 28,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
-}
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA9500",
+               "board": []
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [1],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": 28
+               },
+               {
+                       "number": 2,
+                       "param_values": [2],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": 28
+               }
+       ]
+}
\ No newline at end of file
index b9067c4d4b3b1a04a3417ddf03325f84ba65bb2c..e8792aaafe8c0a293c945e8c9ddeb725085f2ad2 100644 (file)
@@ -1,14 +1,32 @@
 {
-       "vendorName": "Netgear",
-       "deviceName": "WAC510",
-       "boardNames": [ "netgear,wac510" ],
-       "partition1MTD": "mtd9",
-       "partition2MTD": "mtd10",
-       "labelOffset": null,
-       "bootEnv1": "primary",
-       "bootEnv1Partition1Value": 0,
-       "bootEnv1Partition2Value": 3800000,
-       "bootEnv2": "secondary",
-       "bootEnv2Partition1Value": 3800000,
-       "bootEnv2Partition2Value": 0
+       "device": {
+               "vendor": "Netgear",
+               "model": "WAC510",
+               "board": [
+                       "netgear,wac510"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "primary",
+                       "secondary"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [0, 3800000],
+                       "mtd": "mtd9",
+                       "labelOffsetBytes": null
+               },
+               {
+                       "number": 2,
+                       "param_values": [3800000, 0],
+                       "mtd": "mtd10",
+                       "labelOffsetBytes": null
+               }
+       ]
 }
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/xiaomi-ax3600.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/xiaomi-ax3600.json
new file mode 100644 (file)
index 0000000..70bbbaf
--- /dev/null
@@ -0,0 +1,38 @@
+{
+       "device": {
+               "vendor": "Xiaomi",
+               "model": "AX3600",
+               "board": [
+                       "xiaomi,ax3600"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "flag_boot_rootfs",
+                       "flag_last_success"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               0,
+                               0
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 266432
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               1,
+                               1
+                       ],
+                       "mtd": "mtd13",
+                       "labelOffsetBytes": 266432
+               }
+       ]
+}
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/xiaomi-ax9000.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.disabled/xiaomi-ax9000.json
new file mode 100644 (file)
index 0000000..285bf13
--- /dev/null
@@ -0,0 +1,38 @@
+{
+       "device": {
+               "vendor": "Xiaomi",
+               "model": "AX9000",
+               "board": [
+                       "xiaomi,ax9000"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "flag_boot_rootfs",
+                       "flag_last_success"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               0,
+                               0
+                       ],
+                       "mtd": "mtd20",
+                       "labelOffsetBytes": 266432
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               1,
+                               1
+                       ],
+                       "mtd": "mtd21",
+                       "labelOffsetBytes": 266432
+               }
+       ]
+}
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices.json
new file mode 100644 (file)
index 0000000..4a73edd
--- /dev/null
@@ -0,0 +1,1506 @@
+[
+  {
+    "device": {
+      "vendor": "D-Link",
+      "model": "DGS-1210-28",
+      "board": [
+        "d-link,dgs-1210-28"
+      ]
+    },
+    "commands": {
+      "params": [
+        "bootcmd",
+        "image"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [],
+        "mtd": "mtd5",
+        "labelOffsetBytes": null
+      },
+      {
+        "number": 2,
+        "param_values": [
+          "run addargs\\; bootm 0xb4e80000",
+          "/dev/mtdblock7"
+        ],
+        "mtd": "mtd9",
+        "labelOffsetBytes": null
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "E4200v2/EA4500",
+      "board": [
+        "linksys-viper",
+        "linksys,viper"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd3",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "E4200v2",
+      "board": [
+        "linksys-e4200v2",
+        "linksys,e4200-v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd3",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "E7350",
+      "board": [
+        "linksys,e7350"
+      ]
+    },
+    "commands": {
+      "params": [
+        "bootimage"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd3",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd6",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA3500",
+      "board": [
+        "linksys-audi",
+        "linksys,audi",
+        "linksys-ea3500",
+        "linksys,ea3500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd3",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA4500",
+      "board": [
+        "linksys-ea4500",
+        "linksys,ea4500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd3",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA6350v3",
+      "board": [
+        "linksys-ea6350v3",
+        "linksys,ea6350v3"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd10",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA6350v4",
+      "board": [
+        "linksys,ea6350-v4"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA7300v1",
+      "board": [
+        "linksys,ea7300-v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA7300v2",
+      "board": [
+        "linksys,ea7300-v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA7500v1",
+      "board": [
+        "linksys,ea7500-v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd13",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd15",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA7500v2",
+      "board": [
+        "linksys,ea7500-v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA8100v1",
+      "board": [
+        "linksys,ea8100-v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA8100v2",
+      "board": [
+        "linksys,ea8100-v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA8300",
+      "board": [
+        "linksys-ea8300",
+        "linksys,ea8300"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd10",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "EA8500",
+      "board": [
+        "linksys-ea8500",
+        "linksys,ea8500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd13",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd15",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MR5500",
+      "board": [
+        "linksys,mr5500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd14",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MR7350",
+      "board": [
+        "linksys,mr7350"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd14",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd16",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MR7500",
+      "board": [
+        "linksys,mr7500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd13",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd15",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MR8300",
+      "board": [
+        "linksys-mr8300",
+        "linksys,mr8300"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd10",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MR9000 (Dallas)",
+      "board": [
+        "linksys,mr9000"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd10",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX2000",
+      "board": [
+        "linksys,mx2000"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd14",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX4200v1",
+      "board": [
+        "linksys,mx4200v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd21",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd23",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX4200v2",
+      "board": [
+        "linksys,mx4200v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd21",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd23",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX4300",
+      "board": [
+        "linksys,mx4300"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd21",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd23",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX5300",
+      "board": [
+        "linksys,mx5300"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd21",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd23",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX5500",
+      "board": [
+        "linksys,mx5500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd14",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "MX8500",
+      "board": [
+        "linksys,mx8500"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd21",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd23",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "SPNMX56",
+      "board": [
+        "linksys,spnmx56"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd12",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd14",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WHW01 V1 (Velop)",
+      "board": [
+        "linksys,whw01"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd9",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd11",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WHW03 (Velop)",
+      "board": [
+        "linksys,whw03"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mmcblk0p14",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mmcblk0p16",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WHW03 V2 (Velop)",
+      "board": [
+        "linksys-whw03v2",
+        "linksys,whw03v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd9",
+        "labelOffsetBytes": 192
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2
+        ],
+        "mtd": "mtd11",
+        "labelOffsetBytes": 192
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WRT1200AC",
+      "board": [
+        "linksys-caiman",
+        "linksys,caiman",
+        "linksys,wrt1200ac"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd4",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd6",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WRT1900ACv1",
+      "board": [
+        "linksys-mamba",
+        "linksys,mamba",
+        "linksys,wrt1900ac-v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd4",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd6",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WRT1900ACS",
+      "board": [
+        "linksys-shelby",
+        "linksys,shelby",
+        "linksys,wrt1900acs"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd4",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd6",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WRT1900ACv2",
+      "board": [
+        "linksys-cobra",
+        "linksys,cobra",
+        "linksys,wrt1900ac-v2"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd4",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd6",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WRT3200ACM",
+      "board": [
+        "linksys-rango",
+        "linksys,rango",
+        "linksys,wrt3200acm"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Linksys",
+      "model": "WRT32X",
+      "board": [
+        "linksys-venom",
+        "linksys,venom",
+        "linksys,wrt32x"
+      ]
+    },
+    "commands": {
+      "params": [
+        "boot_part",
+        "bootcmd"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          1,
+          "run nandboot"
+        ],
+        "mtd": "mtd5",
+        "labelOffsetBytes": null
+      },
+      {
+        "number": 2,
+        "param_values": [
+          2,
+          "run altnandboot"
+        ],
+        "mtd": "mtd7",
+        "labelOffsetBytes": null
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "MERCUSYS",
+      "model": "MR90X v1",
+      "board": [
+        "mercusys,mr90x-v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "tp_boot_idx"
+      ],
+      "get": "fw_printenv",
+      "set": "fw_setenv",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          0
+        ],
+        "mtd": "mtd2",
+        "labelOffsetBytes": null,
+        "altMountOptions": {
+          "mtdOffset": 0,
+          "ubiVolume": 2
+        }
+      },
+      {
+        "number": 2,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd3",
+        "labelOffsetBytes": null,
+        "altMountOptions": {
+          "mtdOffset": 0,
+          "ubiVolume": 2
+        }
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "Netgear",
+      "model": "GS308T v1",
+      "board": [
+        "netgear,gs308t-v1"
+      ]
+    },
+    "commands": {
+      "params": [
+        "bootpartition"
+      ],
+      "get": "fw_printsys",
+      "set": "fw_setsys",
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          0
+        ],
+        "mtd": "mtd6",
+        "labelOffsetBytes": null
+      },
+      {
+        "number": 2,
+        "param_values": [
+          1
+        ],
+        "mtd": "mtd9",
+        "labelOffsetBytes": null
+      }
+    ]
+  },
+  {
+    "device": {
+      "vendor": "ZyXEL",
+      "model": "NBG6817",
+      "board": [
+        "nbg6817",
+        "zyxel,nbg6817"
+      ]
+    },
+    "commands": {
+      "params": [],
+      "get": null,
+      "set": null,
+      "save": null
+    },
+    "partitions": [
+      {
+        "number": 1,
+        "param_values": [
+          "ff"
+        ],
+        "mtd": "mmcblk0p4",
+        "labelOffsetBytes": 32
+      },
+      {
+        "number": 2,
+        "param_values": [
+          "01"
+        ],
+        "mtd": "mmcblk0p7",
+        "labelOffsetBytes": 32
+      }
+    ]
+  }
+]
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/_device_json_transform.jq b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/_device_json_transform.jq
new file mode 100644 (file)
index 0000000..23eb440
--- /dev/null
@@ -0,0 +1,88 @@
+# Tabs only for indentation, spaces ok in comments.
+
+# jq -f _device_json_transform.jq old.json
+# Transform from the old schema:
+# {
+#      "vendorName": "...",
+#      "deviceName": "...",
+#      "boardNames": ["..."],
+#      "partition1MTD": "mtdX",
+#      "partition2MTD": "mtdY",
+#      "labelOffset": 32,
+#      "bootEnv1": "boot_part",
+#      "bootEnv1Partition1Value": 1,
+#      "bootEnv1Partition2Value": 2,
+#      "bootEnv2": "bootcmd",
+#      "bootEnv2Partition1Value": "run nandboot",
+#      "bootEnv2Partition2Value": "run altnandboot",
+#      "opOffset": 0,
+#      "ubiVolume": 2
+# }
+#
+# â€¦to the new schema:
+# {
+#      "device": { "vendor": "...", "model": "...", "board": ["..."] },
+#      "commands": { "params": [...], "get": "fw_printenv", "set": "fw_setenv", "save": null },
+#      "partitions": [
+#              { "number": 1, "param_values": [...], "mtd": "mtdX", "labelOffsetBytes": <int|null>, "altMountOptions": {...|null} },
+#              { "number": 2, "param_values": [...], "mtd": "mtdY", "labelOffsetBytes": <int|null>, "altMountOptions": {...|null} }
+#      ]
+# }
+
+. as $in
+| ([$in.bootEnv1, $in.bootEnv2] | map(select(. != null))) as $params
+| {
+       device: {
+               vendor: $in.vendorName,
+               model: $in.deviceName,
+               board: (if ($in.boardNames | type) == "array" then $in.boardNames else [$in.boardNames] end)
+       },
+       commands: {
+               params: $params,
+               get: "fw_printenv",
+               set: "fw_setenv",
+               save: null
+       },
+       partitions: [
+               (if $in.partition1MTD != null then
+                       {
+                               number: 1,
+                               param_values: (
+                                       # Align to commands.params: value for param[0], param[1], ...
+                                       # Only include entries that exist (skip nulls)
+                                       [
+                                               (if ($params | length) > 0 then $in.bootEnv1Partition1Value else empty end),
+                                               (if ($params | length) > 1 then $in.bootEnv2Partition1Value else empty end)
+                                       ] | map(select(. != null))
+                               ),
+                               mtd: $in.partition1MTD,
+                               labelOffsetBytes: ($in.labelOffset // null)
+                       } + (
+                               if ($in.opOffset != null or $in.ubiVolume != null) then
+                                       { altMountOptions: { mtdOffset: ($in.opOffset // null), ubiVolume: ($in.ubiVolume // null) } }
+                               else
+                                       {}
+                               end
+                       )
+               else empty end),
+               (if $in.partition2MTD != null then
+                       {
+                               number: 2,
+                               param_values: (
+                                       [
+                                               (if ($params | length) > 0 then $in.bootEnv1Partition2Value else empty end),
+                                               (if ($params | length) > 1 then $in.bootEnv2Partition2Value else empty end)
+                                       ] | map(select(. != null))
+                               ),
+                               mtd: $in.partition2MTD,
+                               labelOffsetBytes: ($in.labelOffset // null)
+                       } + (
+                               if ($in.opOffset != null or $in.ubiVolume != null) then
+                                       { altMountOptions: { mtdOffset: ($in.opOffset // null), ubiVolume: ($in.ubiVolume // null) } }
+                               else
+                                       {}
+                               end
+                       )
+               else empty end)
+       ]
+}
index d5e468215a1d8555cfdeef1a7e8d3874b781bf09..8584916c202a0f4620be57e233c362fcc1e2448a 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "D-Link",
-       "deviceName": "DGS-1210-28",
-       "boardNames": [ "d-link,dgs-1210-28" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd9",
-       "labelOffset": null,
-       "bootEnv1": "bootcmd",
-       "bootEnv1Partition1Value": null,
-       "bootEnv1Partition2Value": "run addargs\\; bootm 0xb4e80000",
-       "bootEnv2": "image",
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": "/dev/mtdblock7"
+       "device": {
+               "vendor": "D-Link",
+               "model": "DGS-1210-28",
+               "board": [
+                       "d-link,dgs-1210-28"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "bootcmd",
+                       "image"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": null
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               "run addargs\\; bootm 0xb4e80000",
+                               "/dev/mtdblock7"
+                       ],
+                       "mtd": "mtd9",
+                       "labelOffsetBytes": null
+               }
+       ]
 }
index be749a999579b091403a244aa2cb080e9b876bf5..361e18338974febba5c26ab3ca83e0911b9bc3ad 100644 (file)
@@ -1,14 +1,39 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "E4200v2/EA4500",
-       "boardNames": [ "linksys-viper", "linksys,viper" ],
-       "partition1MTD": "mtd3",
-       "partition2MTD": "mtd5",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "E4200v2/EA4500",
+               "board": [
+                       "linksys-viper",
+                       "linksys,viper"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index d42319e2ce818647b934419157e1a6779447ca8d..dc11ac3b6b16f4307b7b431088bf8066f7e4890f 100644 (file)
@@ -1,17 +1,39 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "E4200v2",
-       "boardNames": [
-               "linksys-e4200v2",
-               "linksys,e4200-v2"
-       ],
-       "partition1MTD": "mtd3",
-       "partition2MTD": "mtd5",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "E4200v2",
+               "board": [
+                       "linksys-e4200v2",
+                       "linksys,e4200-v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index 9d320c0ca6125603d394018a4b9123e6e04d5564..bd072c21ed215eab9dae65d1370f77e790eac45b 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "E7350",
-       "boardNames": [ "linksys,e7350" ],
-       "partition1MTD": "mtd3",
-       "partition2MTD": "mtd6",
-       "labelOffset": 192,
-       "bootEnv1": "bootimage",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "E7350",
+               "board": [
+                       "linksys,e7350"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "bootimage"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 6cdc726431e981e32587df9a66f3a3387786eef2..2db56154524dd2e01a714db7423613478cf0fc56 100644 (file)
@@ -1,15 +1,41 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA3500",
-       "boardNames": [ "linksys-audi", "linksys,audi", "linksys-ea3500", "linksys,ea3500" ],
-       "partition1MTD": "mtd3",
-       "partition2MTD": "mtd5",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA3500",
+               "board": [
+                       "linksys-audi",
+                       "linksys,audi",
+                       "linksys-ea3500",
+                       "linksys,ea3500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
-
index c77cde33f2fbf1a54158e9191d560097365d491c..f5b8d0318ab58269aedb89acf9d7070289ff9510 100644 (file)
@@ -1,14 +1,39 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA4500",
-       "boardNames": [ "linksys-ea4500", "linksys,ea4500" ],
-       "partition1MTD": "mtd3",
-       "partition2MTD": "mtd5",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA4500",
+               "board": [
+                       "linksys-ea4500",
+                       "linksys,ea4500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index f5fc476c107688af59a944110f3694e491575508..32f6cd108a91980ecfe9f255672423c01ae403ec 100644 (file)
@@ -1,14 +1,36 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA6350v3",
-       "boardNames": [ "linksys-ea6350v3", "linksys,ea6350v3" ],
-       "partition1MTD": "mtd10",
-       "partition2MTD": "mtd12",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA6350v3",
+               "board": [
+                       "linksys-ea6350v3",
+                       "linksys,ea6350v3"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd10",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 104229861af0ecc03ae9098404a85278d17302fe..74694d5e952ecc288821f54e23dca862ca974b60 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA6350v4",
-       "boardNames": [ "linksys,ea6350-v4" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA6350v4",
+               "board": [
+                       "linksys,ea6350-v4"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index 22f1a8c01a8d8670420a3bb10bae686bc91c84df..580a3f55b858e2980540fd04a8452ab163def9d8 100644 (file)
@@ -1,15 +1,38 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA7300v1",
-       "boardNames": [ "linksys,ea7300-v1" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA7300v1",
+               "board": [
+                       "linksys,ea7300-v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
-
index 9f463758c83d9deb43ed2619fcae9b747a927801..5513a7a6c8b1658c7bb9774c1d0865f460c498e0 100644 (file)
@@ -1,15 +1,38 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA7300v2",
-       "boardNames": [ "linksys,ea7300-v2" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA7300v2",
+               "board": [
+                       "linksys,ea7300-v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
-
index 4c68639fd385832ec3f6995582e7c06822a25b61..9012333d832e004b0113768f22480e2d83c9e70f 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA7500v1",
-       "boardNames": [ "linksys,ea7500-v1" ],
-       "partition1MTD": "mtd13",
-       "partition2MTD": "mtd15",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA7500v1",
+               "board": [
+                       "linksys,ea7500-v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd13",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd15",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index b061c658653bc2d372baeed7d920ae04e925abcf..8a7dcae18019235e45e58a8fd2176808f58503fc 100644 (file)
@@ -1,14 +1,38 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA7500v2",
-       "boardNames": [ "linksys,ea7500-v2" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA7500v2",
+               "board": [
+                       "linksys,ea7500-v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index e50941921d94a13b292a043cbb9a215b32cfabae..f2f0489e41570b43f54c58a6b1f557a659526158 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA8100v1",
-       "boardNames": [ "linksys,ea8100-v1" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA8100v1",
+               "board": [
+                       "linksys,ea8100-v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index d62843cc1b52d3e8882221f0d331338de9ea9729..cbed6e1cb510f9ba365d8d9e5967973088c00f74 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA8100v2",
-       "boardNames": [ "linksys,ea8100-v2" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA8100v2",
+               "board": [
+                       "linksys,ea8100-v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index d4a47886a5725bb358c6a7f67728c77ccf2f10c3..80518db673a5b007a205e7fe4b7aa547eb0faec8 100644 (file)
@@ -1,14 +1,36 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA8300",
-       "boardNames": [ "linksys-ea8300", "linksys,ea8300" ],
-       "partition1MTD": "mtd10",
-       "partition2MTD": "mtd12",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA8300",
+               "board": [
+                       "linksys-ea8300",
+                       "linksys,ea8300"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd10",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index cafa573fb41d69b57370fd905475b167cf8c74cf..e2f7ccc5088064e20d258f0eaeccd00b20e57832 100644 (file)
@@ -1,14 +1,36 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "EA8500",
-       "boardNames": [ "linksys-ea8500", "linksys,ea8500" ],
-       "partition1MTD": "mtd13",
-       "partition2MTD": "mtd15",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "EA8500",
+               "board": [
+                       "linksys-ea8500",
+                       "linksys,ea8500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd13",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd15",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index fb13e8ea6ce061a67f6b51908ece87a042461644..13ff2d2f799323d6ce7b87cfbf5b5f57526ff44f 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MR5500",
-       "boardNames": [ "linksys,mr5500" ],
-       "partition1MTD": "mtd12",
-       "partition2MTD": "mtd14",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MR5500",
+               "board": [
+                       "linksys,mr5500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd14",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 1d1fc862b1b12931ea220d5b59f57c123e65c73a..68bff35efdc8085e132fc0cdd18b1e86a468e7b6 100644 (file)
@@ -1,14 +1,35 @@
 {
-        "vendorName": "Linksys",
-        "deviceName": "MR7350",
-        "boardNames": [ "linksys,mr7350" ],
-        "partition1MTD": "mtd14",
-        "partition2MTD": "mtd16",
-        "labelOffset": 192,
-        "bootEnv1": "boot_part",
-        "bootEnv1Partition1Value": 1,
-        "bootEnv1Partition2Value": 2,
-        "bootEnv2": null,
-        "bootEnv2Partition1Value": null,
-        "bootEnv2Partition2Value": null
-}
\ No newline at end of file
+       "device": {
+               "vendor": "Linksys",
+               "model": "MR7350",
+               "board": [
+                       "linksys,mr7350"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd14",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd16",
+                       "labelOffsetBytes": 192
+               }
+       ]
+}
index 55cad93096ba93ce5f3ccef04a5e97d315e1b5ea..4dc7309d73157bbcabf9ab084c3670f0c0d65e0a 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MR7500",
-       "boardNames": [ "linksys,mr7500" ],
-       "partition1MTD": "mtd13",
-       "partition2MTD": "mtd15",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MR7500",
+               "board": [
+                       "linksys,mr7500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd13",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd15",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 644f1712f3d685c5f069d0a81c0a3ff599003495..625ab0fc755edd04132088b5a8d4f2cec9a48ffc 100644 (file)
@@ -1,14 +1,36 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MR8300",
-       "boardNames": [ "linksys-mr8300", "linksys,mr8300" ],
-       "partition1MTD": "mtd10",
-       "partition2MTD": "mtd12",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MR8300",
+               "board": [
+                       "linksys-mr8300",
+                       "linksys,mr8300"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd10",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr9000.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/linksys-mr9000.json
new file mode 100644 (file)
index 0000000..763692b
--- /dev/null
@@ -0,0 +1,35 @@
+{
+       "device": {
+               "vendor": "Linksys",
+               "model": "MR9000 (Dallas)",
+               "board": [
+                       "linksys,mr9000"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd10",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               }
+       ]
+}
index 93d59200654cc5292d0ed73905d220803a077848..c10f8a989124ced8da90064d6672682d6f0c6494 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX2000",
-       "boardNames": [ "linksys,mx2000" ],
-       "partition1MTD": "mtd12",
-       "partition2MTD": "mtd14",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX2000",
+               "board": [
+                       "linksys,mx2000"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd14",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 01213849aa67ec35b9da759fa2e1d855e2b8c23e..735798e6c31de078ef03e6aa1b9a73e0f4ffa967 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX4200v1",
-       "boardNames": [ "linksys,mx4200v1" ],
-       "partition1MTD": "mtd21",
-       "partition2MTD": "mtd23",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX4200v1",
+               "board": [
+                       "linksys,mx4200v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd21",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd23",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 44e8d3c80dae218e84a0eaa10761af62490dfcbd..906aa8414cc2d25fdf44467b2902eb8d4b1f24c0 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX4200v2",
-       "boardNames": [ "linksys,mx4200v2" ],
-       "partition1MTD": "mtd21",
-       "partition2MTD": "mtd23",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX4200v2",
+               "board": [
+                       "linksys,mx4200v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd21",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd23",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 8692c6d2b28bcfa72667b95727682f4040bf6033..0c494969d3de6cb2e2a58e85c7e017cb502fe76f 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX4300",
-       "boardNames": [ "linksys,mx4300" ],
-       "partition1MTD": "mtd21",
-       "partition2MTD": "mtd23",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX4300",
+               "board": [
+                       "linksys,mx4300"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd21",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd23",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 2f4807a4d00e0bafeb96e45ec060d05bf58c8f69..d904eeea89652bd05332dbfc978fe26c7d733df6 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX5300",
-       "boardNames": [ "linksys,mx5300" ],
-       "partition1MTD": "mtd21",
-       "partition2MTD": "mtd23",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX5300",
+               "board": [
+                       "linksys,mx5300"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd21",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd23",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index f9345b11e011f990baab91abc66c3d4617c4d992..35407fc774424416bd379e54130c030544f91eb6 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX5500",
-       "boardNames": [ "linksys,mx5500" ],
-       "partition1MTD": "mtd12",
-       "partition2MTD": "mtd14",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX5500",
+               "board": [
+                       "linksys,mx5500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd14",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 72dd673696ab5397b393e3c01b8278b24117a710..e9ab606179938eab893ce695eed3d4e7a26cfdfd 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "MX8500",
-       "boardNames": [ "linksys,mx8500" ],
-       "partition1MTD": "mtd21",
-       "partition2MTD": "mtd23",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "MX8500",
+               "board": [
+                       "linksys,mx8500"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd21",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd23",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 15e9db60156d896d94b7e73d4471513abe8940e2..09bc2a2f782fb2e2a187d6c6de3e74abba5acc44 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "SPNMX56",
-       "boardNames": [ "linksys,spnmx56" ],
-       "partition1MTD": "mtd12",
-       "partition2MTD": "mtd14",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "SPNMX56",
+               "board": [
+                       "linksys,spnmx56"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd12",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd14",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 82238f3548005c92da21c61f47ae743af0adbb76..f1b73d38e065b9bd1ca8b8707111b3dac17a4e41 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WHW01 V1 (Velop)",
-       "boardNames": [ "linksys,whw01" ],
-       "partition1MTD": "mtd9",
-       "partition2MTD": "mtd11",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "WHW01 V1 (Velop)",
+               "board": [
+                       "linksys,whw01"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd9",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd11",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 76eb0bd4c4823cb28ec5617c8dbd45bdded3f43c..26b16e8a6133b489143e2310e030dd9750f9fb7e 100644 (file)
@@ -1,14 +1,35 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WHW03 (Velop)",
-       "boardNames": [ "linksys,whw03" ],
-       "partition1MTD": "mmcblk0p14",
-       "partition2MTD": "mmcblk0p16",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "WHW03 (Velop)",
+               "board": [
+                       "linksys,whw03"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mmcblk0p14",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mmcblk0p16",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index d7ab710c822d7d73324e9addcaa9b24be55e3cca..3bd967476c17c2f42f825bb40ff627b4f6c9cf58 100644 (file)
@@ -1,14 +1,36 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WHW03 V2 (Velop)",
-       "boardNames": [ "linksys-whw03v2", "linksys,whw03v2" ],
-       "partition1MTD": "mtd9",
-       "partition2MTD": "mtd11",
-       "labelOffset": 192,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "Linksys",
+               "model": "WHW03 V2 (Velop)",
+               "board": [
+                       "linksys-whw03v2",
+                       "linksys,whw03v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd9",
+                       "labelOffsetBytes": 192
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2
+                       ],
+                       "mtd": "mtd11",
+                       "labelOffsetBytes": 192
+               }
+       ]
 }
index 3d1b19a921487705595e9a9641eaafa5fadc007c..346891ae67b8eb48079ebf3e1932e0d9cac714bf 100644 (file)
@@ -1,14 +1,40 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WRT1200AC",
-       "boardNames": [ "linksys-caiman", "linksys,caiman", "linksys,wrt1200ac" ],
-       "partition1MTD": "mtd4",
-       "partition2MTD": "mtd6",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "WRT1200AC",
+               "board": [
+                       "linksys-caiman",
+                       "linksys,caiman",
+                       "linksys,wrt1200ac"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd4",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index d088e9a2ed36c5205134355a22f6f8f7a3926765..8ccb6c7500e512952d7bb122c86f0dfc628d262c 100644 (file)
@@ -1,14 +1,40 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WRT1900ACv1",
-       "boardNames": [ "linksys-mamba", "linksys,mamba", "linksys,wrt1900ac-v1" ],
-       "partition1MTD": "mtd4",
-       "partition2MTD": "mtd6",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "WRT1900ACv1",
+               "board": [
+                       "linksys-mamba",
+                       "linksys,mamba",
+                       "linksys,wrt1900ac-v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd4",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index a30b3dcab3bf25741fc4edeb3ae5e267f2b91fad..42bb14b7630f80ae6d2e7ac8a0faeeab821c9776 100644 (file)
@@ -1,14 +1,40 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WRT1900ACS",
-       "boardNames": [ "linksys-shelby", "linksys,shelby", "linksys,wrt1900acs" ],
-       "partition1MTD": "mtd4",
-       "partition2MTD": "mtd6",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "WRT1900ACS",
+               "board": [
+                       "linksys-shelby",
+                       "linksys,shelby",
+                       "linksys,wrt1900acs"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd4",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index 361b434b310aba05a43ff681d10e842e9b4046b2..f585a542a431067bed2fdac7d6d51c545252b921 100644 (file)
@@ -1,14 +1,40 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WRT1900ACv2",
-       "boardNames": [ "linksys-cobra", "linksys,cobra", "linksys,wrt1900ac-v2" ],
-       "partition1MTD": "mtd4",
-       "partition2MTD": "mtd6",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "WRT1900ACv2",
+               "board": [
+                       "linksys-cobra",
+                       "linksys,cobra",
+                       "linksys,wrt1900ac-v2"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd4",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index 09fcf96c2b56f6cd9278fd18768b237f0cb8d0b8..f7dc5e59cc15ae92c8918cbec989cf8d2854b73f 100644 (file)
@@ -1,14 +1,40 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WRT3200ACM",
-       "boardNames": [ "linksys-rango", "linksys,rango", "linksys,wrt3200acm" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": 32,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "WRT3200ACM",
+               "board": [
+                       "linksys-rango",
+                       "linksys,rango",
+                       "linksys,wrt3200acm"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index 47e94ab876f29950b3d05834114f18dced3b69cf..5ef1ccf7f69d6e90e11d8e8f6af721c352a1dbc3 100644 (file)
@@ -1,14 +1,40 @@
 {
-       "vendorName": "Linksys",
-       "deviceName": "WRT32X",
-       "boardNames": [ "linksys-venom", "linksys,venom", "linksys,wrt32x" ],
-       "partition1MTD": "mtd5",
-       "partition2MTD": "mtd7",
-       "labelOffset": null,
-       "bootEnv1": "boot_part",
-       "bootEnv1Partition1Value": 1,
-       "bootEnv1Partition2Value": 2,
-       "bootEnv2": "bootcmd",
-       "bootEnv2Partition1Value": "run nandboot",
-       "bootEnv2Partition2Value": "run altnandboot"
+       "device": {
+               "vendor": "Linksys",
+               "model": "WRT32X",
+               "board": [
+                       "linksys-venom",
+                       "linksys,venom",
+                       "linksys,wrt32x"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "boot_part",
+                       "bootcmd"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               1,
+                               "run nandboot"
+                       ],
+                       "mtd": "mtd5",
+                       "labelOffsetBytes": null
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               2,
+                               "run altnandboot"
+                       ],
+                       "mtd": "mtd7",
+                       "labelOffsetBytes": null
+               }
+       ]
 }
index 02be54345af658e981f76001ecb658a0e7446725..96a4b3d250b73c23bc2ae194017ad4243f069401 100644 (file)
@@ -1,16 +1,43 @@
 {
-    "vendorName": "MERCUSYS",
-    "deviceName": "MR90X v1",
-    "boardNames": [ "mercusys,mr90x-v1" ],
-    "partition1MTD": "mtd2",
-    "partition2MTD": "mtd3",
-    "opOffset": 0,
-    "ubiVolume": 2,
-    "labelOffset": null,
-    "bootEnv1": "tp_boot_idx",
-    "bootEnv1Partition1Value": 0,
-    "bootEnv1Partition2Value": 1,
-    "bootEnv2": null,
-    "bootEnv2Partition1Value": null,
-    "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "MERCUSYS",
+               "model": "MR90X v1",
+               "board": [
+                       "mercusys,mr90x-v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "tp_boot_idx"
+               ],
+               "get": "fw_printenv",
+               "set": "fw_setenv",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               0
+                       ],
+                       "mtd": "mtd2",
+                       "labelOffsetBytes": null,
+                       "altMountOptions": {
+                               "mtdOffset": 0,
+                               "ubiVolume": 2
+                       }
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd3",
+                       "labelOffsetBytes": null,
+                       "altMountOptions": {
+                               "mtdOffset": 0,
+                               "ubiVolume": 2
+                       }
+               }
+       ]
 }
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/netgear-gs308t-v1.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/netgear-gs308t-v1.json
new file mode 100644 (file)
index 0000000..b1143d3
--- /dev/null
@@ -0,0 +1,35 @@
+{
+       "device": {
+               "vendor": "Netgear",
+               "model": "GS308T v1",
+               "board": [
+                       "netgear,gs308t-v1"
+               ]
+       },
+       "commands": {
+               "params": [
+                       "bootpartition"
+               ],
+               "get": "fw_printsys",
+               "set": "fw_setsys",
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               0
+                       ],
+                       "mtd": "mtd6",
+                       "labelOffsetBytes": null
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               1
+                       ],
+                       "mtd": "mtd9",
+                       "labelOffsetBytes": null
+               }
+       ]
+}
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/xiaomi-ax3600.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/xiaomi-ax3600.json
deleted file mode 100644 (file)
index 6189113..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "vendorName": "Xiaomi",
-       "deviceName": "AX3600",
-       "boardNames": [ "xiaomi,ax3600" ],
-       "partition1MTD": "mtd12",
-       "partition2MTD": "mtd13",
-       "labelOffset": 266432,
-       "bootEnv1": "flag_boot_rootfs",
-       "bootEnv1Partition1Value": 0,
-       "bootEnv1Partition2Value": 1,
-       "bootEnv2": "flag_last_success",
-       "bootEnv2Partition1Value": 0,
-       "bootEnv2Partition2Value": 1
-}
diff --git a/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/xiaomi-ax9000.json b/applications/luci-app-advanced-reboot/root/usr/share/advanced-reboot/devices/xiaomi-ax9000.json
deleted file mode 100644 (file)
index 09435b8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-       "vendorName": "Xiaomi",
-       "deviceName": "AX9000",
-       "boardNames": [ "xiaomi,ax9000" ],
-       "partition1MTD": "mtd20",
-       "partition2MTD": "mtd21",
-       "labelOffset": 266432,
-       "bootEnv1": "flag_boot_rootfs",
-       "bootEnv1Partition1Value": 0,
-       "bootEnv1Partition2Value": 1,
-       "bootEnv2": "flag_last_success",
-       "bootEnv2Partition1Value": 0,
-       "bootEnv2Partition2Value": 1
-}
index 85e764879a54e3b14b5785b3143a9da1cd60e1a2..966945d26521065842c88dfefdf8860925bc34d2 100644 (file)
@@ -1,14 +1,34 @@
 {
-       "vendorName": "ZyXEL",
-       "deviceName": "NBG6817",
-       "boardNames": [ "nbg6817", "zyxel,nbg6817" ],
-       "partition1MTD": "mmcblk0p4",
-       "partition2MTD": "mmcblk0p7",
-       "labelOffset": 32,
-       "bootEnv1": null,
-       "bootEnv1Partition1Value": 255,
-       "bootEnv1Partition2Value": 1,
-       "bootEnv2": null,
-       "bootEnv2Partition1Value": null,
-       "bootEnv2Partition2Value": null
+       "device": {
+               "vendor": "ZyXEL",
+               "model": "NBG6817",
+               "board": [
+                       "nbg6817",
+                       "zyxel,nbg6817"
+               ]
+       },
+       "commands": {
+               "params": [],
+               "get": null,
+               "set": null,
+               "save": null
+       },
+       "partitions": [
+               {
+                       "number": 1,
+                       "param_values": [
+                               "ff"
+                       ],
+                       "mtd": "mmcblk0p4",
+                       "labelOffsetBytes": 32
+               },
+               {
+                       "number": 2,
+                       "param_values": [
+                               "01"
+                       ],
+                       "mtd": "mmcblk0p7",
+                       "labelOffsetBytes": 32
+               }
+       ]
 }
index e377fa9362faf63cf4982b54bbbe6b4090598b99..d3e865832216ec6d00dad3bd45f645f74e555aa2 100644 (file)
@@ -1,10 +1,10 @@
 {
-       "admin/system/advanced_reboot": {
+       "admin/system/advanced-reboot": {
                "title": "Advanced Reboot",
                "order": 90,
                "action": {
                        "type": "view",
-                       "path": "system/advanced_reboot"
+                       "path": "system/advanced-reboot"
                },
                "depends": {
                        "acl": [ "luci-app-advanced-reboot" ]
index 48f43a2756fb6e1e032385eb683f67addf62f3da..ed0b5d1bff110538d7e197ec36809ad81ee973ac 100644 (file)
@@ -1,15 +1,36 @@
 {
        "luci-app-advanced-reboot": {
-               "description": "Grant UCI and file access for luci-app-advanced-reboot",
+               "description": "Grant file access for luci-app-advanced-reboot",
                "read": {
                        "ubus": {
-                               "luci.advanced_reboot": [ "obtain_device_info", "toggle_boot_partition" ],
+                               "luci.advanced-reboot": [ "obtain_device_info", "boot_partition" ],
                                "system": [ "reboot" ]
                        },
                        "file": {
-                               "/usr/sbin/fw_printenv": [ "list" ],
-                               "/usr/sbin/fw_setenv": [ "list" ],
-                               "/sbin/poweroff": [ "list", "exec" ]
+                               "/bin/dd": [ "list", "exec" ],
+                               "/bin/grep": [ "list", "exec" ],
+                               "/bin/mount": [ "list", "exec" ],
+                               "/bin/sed": [ "list", "exec" ],
+                               "/bin/sh": [ "list", "exec" ],
+                               "/bin/umount": [ "list", "exec" ],
+                               "/bin/uname": [ "list", "exec" ],
+                               "/etc/os-release": [ "read" ],
+                               "/lib/functions.sh": [ "read" ],
+                               "/proc/mounts": [ "read" ],
+                               "/proc/version": [ "read" ],
+                               "/sbin/poweroff": [ "list", "exec" ],
+                               "/tmp/sysinfo/board_name": [ "read" ],
+                               "/usr/bin/hexdump": [ "list", "exec" ],
+                               "/usr/bin/logger": [ "list", "exec" ],
+                               "/usr/bin/printf": [ "list", "exec" ],
+                               "/usr/bin/tr": [ "list", "exec" ],
+                               "/usr/sbin/fw_printenv": [ "list", "exec" ],
+                               "/usr/sbin/fw_printsys": [ "list", "exec" ],
+                               "/usr/sbin/fw_setenv": [ "list", "exec" ],
+                               "/usr/sbin/fw_setsys": [ "list", "exec" ],
+                               "/usr/sbin/ubiblock": [ "list", "exec" ],
+                               "/usr/sbin/ubiattach": [ "list", "exec" ],
+                               "/usr/sbin/ubidetach": [ "list", "exec" ]
                        }
                }
        }
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
new file mode 100644 (file)
index 0000000..10673de
--- /dev/null
@@ -0,0 +1,578 @@
+/* luci.advanced-reboot.uc â€” ucode port of luci.advanced-reboot
+ * Copyright 2025-2026 MOSSDeF, Stan Grishin (stangri@melmac.ca)
+ *
+ * Exposes ubus object: luci.advanced-reboot
+ * Methods:
+ *   - obtain_device_info
+ *   - boot_partition
+ * Tests:
+ * ubus -v list luci.advanced-reboot
+ * ubus -S call luci.advanced-reboot obtain_device_info
+ * ubus -S call luci.advanced-reboot boot_partition '{ "number": "1" }'
+ * ubus -S call luci.advanced-reboot boot_partition '{ "number": "2" }'
+ *
+ * Schema for device JSON files (new):
+ * {
+ *     "device": { "vendor": "Vendor", "model": "Model", "board": ["vendor,model"] },
+ *     "commands": {
+ *             "params": ["<env1>", "<env2>"],
+ *             "get": "fw_printenv",
+ *             "set": "fw_setenv",
+ *             "save": null
+ *     },
+ *     "partitions": [
+ *             { "number": 1, "param_values": [v1, w1], "mtd": "mtdX", "labelOffsetBytes": <int|null>, "altMountOptions": { "mtdOffset": <int>, "ubiVolume": <int> } },
+ *             { "number": 2, "param_values": [v2, w2], "mtd": "mtdY", "labelOffsetBytes": <int|null> }
+ *     ]
+ * }
+ *
+ * Notes:
+ * - `altMountOptions` is optional; when absent, defaults are mtdOffset=1, ubiVolume=0.
+ * - `param_values[i]` aligns with `commands.params[i]`.
+ */
+
+"use strict";
+
+import * as fs from "fs";
+let DEVICES_DIR = "/usr/share/advanced-reboot/devices/";
+let DEVICES_JSON = "/usr/share/advanced-reboot/devices.json";
+
+function file_exists(p) {
+       try {
+               return fs.stat(p) != null;
+       } catch (e) {
+               return false;
+       }
+}
+
+function shellquote(s) {
+       return `'${replace(s ?? "", "'", "'\\''")}'`;
+}
+
+function command(cmd) {
+       return trim(fs.popen(cmd)?.read?.("all"));
+}
+
+function log(msg) {
+       command("logger -t advanced-reboot -- " + shellquote("" + msg));
+}
+
+/* Check whether an executable is available on PATH.
+ *
+ * @param {String} name  Program name (e.g., "ubus").
+ * @returns {Boolean} true if found (exit 0), false otherwise.
+ */
+function has_cmd(name) {
+       let r = command("command -v " + name + " >/dev/null 2>&1; echo $?");
+       return r == "0";
+}
+
+/* Read the current board identifier.
+ *
+ * Source: /tmp/sysinfo/board_name produced by procd.
+ *
+ * @returns {String|null} Board name (e.g., "linksys,mx4200") or null if missing.
+ */
+function get_board_name() {
+       return trim(fs.readfile("/tmp/sysinfo/board_name"));
+}
+
+/* Locate the device descriptor matching a given board name.
+ *
+ * Tries the consolidated devices.json first, then falls back to per-file *.json
+ * in /usr/share/advanced-reboot/devices/.
+ *
+ * @param {String} romBoardName  Value from /tmp/sysinfo/board_name.
+ * @returns {Object|null} Device object with {device, commands, partitions} or null.
+ */
+function find_device_info(romBoardName) {
+       let rb = trim(romBoardName ?? "");
+
+       // Read one big JSON file instead of many small ones
+       let txt = fs.readfile(DEVICES_JSON);
+       if (!txt) return null;
+
+       // devices.json : [ { device: {...} }, { device: {...} }, ... ]
+       let arr = json(txt);
+       if (!arr || type(arr) != "array") return null;
+
+       // Loop over each object in the array
+       for (let obj in arr) {
+               if (!obj || !obj.device) continue;
+
+               let boards = obj.device.board;
+               if (!boards) continue;
+
+               // normalise to array
+               if (type(boards) != "array") boards = ["" + boards];
+
+               for (let i = 0; i < length(boards); i++) {
+                       let s = "" + boards[i];
+                       if (s == rb) return obj;
+               }
+       }
+       // Fallback: old schema with many small files
+       let list = fs.glob(DEVICES_DIR + "*.json");
+       for (let f in list) {
+               let ftxt = fs.readfile(f);
+               if (!ftxt) continue;
+               let obj = json(ftxt);
+               if (!obj || !obj.device) continue;
+               let boards = obj.device.board;
+               if (!boards) continue;
+               if (type(boards) != "array") boards = ["" + boards];
+               for (let i = 0; i < length(boards); i++) {
+                       let s = "" + boards[i];
+                       if (s == rb) return obj;
+               }
+       }
+       return null;
+}
+
+/* Convert an mtd name like "mtd5" to its numeric index (5).
+ *
+ * @param {String} mtdName
+ * @returns {Number|null} Parsed index or null for invalid input.
+ */
+function mtd_index(mtdName) {
+       let m = match("" + mtdName, /^mtd([0-9]+)/);
+       if (m && m[1]) {
+               let n = int(m[1]);
+               return n == n ? n : null;
+       }
+       return null;
+}
+
+/* Read OS label and (optionally) kernel version from a root path.
+ *
+ * Reads PRETTY_NAME from etc/os-release; normalizes snapshot labels using
+ * /etc/openwrt_release if present. When path=="/", also extracts kernel
+ * version from /proc/version (or uname -r).
+ *
+ * @param {String} path  Root of the filesystem to inspect ("/" or mount point).
+ * @returns {{label:String|null, os:String|null}}
+ */
+function get_volume_info(path) {
+       let root = path ?? "/";
+       /* ensure trailing slash exactly once */
+       if (!match(root, /\/$/)) root = root + "/";
+
+       let label;
+       let pretty = command(
+               ". " +
+               shellquote(root + "etc/os-release") +
+               ' 2>/dev/null; echo "$PRETTY_NAME" 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 == "/") {
+               let pv = fs.readfile("/proc/version");
+               if (pv) {
+                       let m = match(pv, /^Linux version ([^ ]+)/);
+                       if (m && m[1]) kver = m[1];
+               }
+               if (!kver) {
+                       let r = command("uname -r 2>/dev/null");
+                       if (r) kver = r;
+               }
+       }
+       return { label: label == "" ? null : label, os: kver };
+}
+
+/* Convenience wrapper to get volume info for the current rootfs.
+ *
+ * @returns {{label:String|null, os:String|null}}
+ */
+function get_partition_info_current() {
+       return get_volume_info("/");
+}
+
+/* Determine if an alternate partition can be mounted.
+ *
+ * Requires: ubiattach, ubiblock, and mount commands available.
+ * Expects the `partitions` arg to be an array of mtd names (e.g., ["mtd5"]).
+ *
+ * @param {Array} partitions
+ * @returns {Boolean} true if tooling is present and input looks like mtd names.
+ */
+function is_alt_mountable(partitions) {
+       if (!partitions || type(partitions) != "array") return false;
+       for (let i = 0; i < length(partitions); i++) {
+               if (!match("" + partitions[i], /^mtd/)) return false;
+       }
+       return has_cmd("ubiattach") && has_cmd("ubiblock") && has_cmd("mount");
+}
+
+/* Attach a UBI MTD device and mount an alternative root read-only.
+ *
+ * Mount point: /var/alt_rom
+ *
+ * @param {Number|String} op_ubi   UBI mtd index to attach (e.g., 6).
+ * @param {Number|String} ubi_vol  UBI volume index (default 0).
+ * @returns {Boolean} true if mounted successfully, false otherwise.
+ * @sideeffects  Creates/removes /var/alt_rom; calls ubiattach/ubiblock/mount.
+ */
+function alt_partition_mount(op_ubi, ubi_vol) {
+       log(
+               "attempting to mount alternative partition: UBI=" +
+               op_ubi +
+               ", Volume=" +
+               ubi_vol
+       );
+       log("ignore kernel messages below");
+       command("mkdir -p /var/alt_rom");
+       command("umount /var/alt_rom");
+       command("ubidetach -m " + op_ubi + " >/dev/null 2>&1");
+       let out = command(
+               "ubiattach -m " +
+               op_ubi +
+               " 2>/dev/null | sed -n 's/^UBI device number\\s*\\([0-9]*\\),.*$/\\1/p'"
+       );
+       log("mounted alternative partition UBI device number: " + out);
+       let dev = out && length(out) ? int(out) : null;
+       if (dev == null) {
+               command("ubidetach -m " + op_ubi + " >/dev/null 2>&1");
+               return false;
+       }
+       let vol = ubi_vol == null ? 0 : int(ubi_vol);
+       let blk = "/dev/ubiblock" + dev + "_" + vol;
+       command("ubiblock --create /dev/ubi" + dev + "_" + vol + " >/dev/null 2>&1");
+       let rc = command(
+               "mount -t squashfs -r " + blk + " /var/alt_rom >/dev/null 2>&1; echo $?"
+       );
+       return rc == "0";
+}
+
+/* Unmount and detach any UBI devices associated with a given MTD index.
+ *
+ * Also removes possible ubiblock nodes for the device.
+ *
+ * @param {Number|String} op_ubi   UBI mtd index previously attached.
+ * @param {Number|String} ubi_vol  UBI volume index (ignored during cleanup).
+ * @returns {void}
+ * @sideeffects  umounts /var/alt_rom, ubidetach, removes ubiblock nodes.
+ */
+function alt_partition_unmount(op_ubi, ubi_vol) {
+       let mtdCount = command(
+               'ubinfo | grep "Present UBI devices" | tr "," "\\n" | grep -c "ubi"'
+       );
+       mtdCount = int(mtdCount) || 10;
+       command("umount /var/alt_rom");
+       for (let i = 0; i <= mtdCount; i++) {
+               let mtd = fs.readfile("/sys/devices/virtual/ubi/ubi" + i + "/mtd_num");
+               if (!mtd) break;
+               mtd = trim(mtd);
+               if (mtd == "" + op_ubi) {
+                       /* remove any ubiblock nodes on this ubi dev */
+                       for (let vid = 0; vid < 16; vid++)
+                               command(
+                                       "ubiblock --remove /dev/ubi" + i + "_" + vid + " >/dev/null 2>&1"
+                               );
+                       command("ubidetach -m " + op_ubi + " >/dev/null 2>&1");
+                       command("rm -rf /var/alt_rom");
+               }
+       }
+}
+
+/* Get label/OS info from an alternative partition, using UBI mount flow.
+ *
+ * Falls back to {label:null, os:null} if mount fails.
+ *
+ * @param {Number|String} op_ubi       UBI mtd index to attach.
+ * @param {String|null}   vendor_name  Vendor string (currently unused here).
+ * @param {Number|String} ubi_vol      UBI volume index (default 0).
+ * @returns {{label:String|null, os:String|null}}
+ */
+function get_partition_info_alt(op_ubi, vendor_name, ubi_vol) {
+       let mounted = alt_partition_mount(op_ubi, ubi_vol);
+       if (mounted) {
+               /* Read info from mounted alt root */
+               let info = get_volume_info("/var/alt_rom/");
+               alt_partition_unmount(op_ubi, ubi_vol);
+               return info ?? { label: null, os: null };
+       } else {
+               alt_partition_unmount(op_ubi, ubi_vol);
+       }
+       return { label: null, os: null };
+}
+
+/* Fallback: probe an MTD partition directly for label/kernel hints.
+ *
+ * Uses `dd` to read bytes at labelOffset and inspects for OpenWrt/vendor tokens
+ * and kernel version strings.
+ *
+ * @param {String} mtd     MTD name (e.g., "mtd9").
+ * @param {Number} offset  Byte offset of label within the partition.
+ * @param {String|null} vendor  Vendor label to look for.
+ * @returns {{label:String|null, os:String|null}}
+ */
+function get_partition_info_fallback(mtd, offset, vendor) {
+       let label;
+       let os;
+       let tag = command("dd if=/dev/" + mtd + " bs=1 skip=" + offset + " count=64");
+       if (tag) {
+               let m1 = match(tag, /Linux version ([^ \n]+)/);
+               if (m1 && m1[1]) os = m1[1];
+               else {
+                       let m2 = match(tag, /Linux-([0-9.]+)/);
+                       if (m2 && m2[1]) os = m2[1];
+               }
+               if (match(tag, /OpenWrt/)) {
+                       label = "OpenWrt";
+               } else if (vendor && vendor != "" && match(tag, regexp(vendor))) {
+                       label = vendor;
+               } else {
+                       label = "Unknown";
+               }
+       } else {
+               label = vendor ? vendor + " (Compressed)" : "Unknown (Compressed)";
+       }
+       return { label: label, os: os };
+}
+
+function read_dual_flag_mtd() {
+       for (let name in ["0:dual_flag", "0:DUAL_FLAG"]) {
+               let dev = command(". /lib/functions.sh; find_mtd_part " + shellquote(name));
+               if (dev) return dev;
+       }
+       return null;
+}
+
+/* Read the single-byte dual-boot flag value from a block device.
+ *
+ * @param {String} dev  Path to the block (e.g., /dev/mtdX) returned by find_mtd_part.
+ * @returns {String|null} Lowercase hex byte (e.g., "00", "01") or null on error.
+ */
+function read_dual_flag_value(dev) {
+       if (!dev || dev == "" || !file_exists(dev)) return null;
+       let r = command(
+               "dd if=" +
+               shellquote(dev) +
+               " bs=1 count=1 2>/dev/null | hexdump -n 1 -e '" +
+               '1/1 "%02x"' +
+               "'"
+       );
+       return r || null;
+}
+
+/* Write a single-byte dual-boot flag value to a block device.
+ *
+ * @param {String} dev  Device path (e.g., /dev/mtdX).
+ * @param {String} cur  Hex byte without prefix (e.g., "01"); will be written as \\x01.
+ * @returns {Boolean} true if write succeeded, false otherwise.
+ * @sideeffects  Overwrites one byte on the target device.
+ */
+function write_dual_flag_value(dev, cur) {
+       cur = "\\x" + cur;
+       let rc = command(
+               "printf %b " +
+               shellquote(cur) +
+               " > " +
+               shellquote(dev) +
+               " 2>/dev/null; echo $?"
+       );
+       return rc == "0";
+}
+
+/* Gather device and partition information for UI/RPC.
+ *
+ * Detects active partition, attempts to label both current and alternate
+ * partitions via UBI mount (if supported) with a raw-label fallback.
+ *
+ * @returns {{
+ *   device:{vendor:String, model:String, board:String, partition_active:String|null},
+ *   partitions:Array<{number:String,label:String|null,os:String|null,mtd:String|null}>
+ * }} or {error:String,...} on failure.
+ */
+function obtain_device_info() {
+       let board = get_board_name();
+       if (!board) return { error: "NO_BOARD_NAME" };
+
+       let d = find_device_info(board);
+       if (!d) return { error: "NO_BOARD_NAME_MATCH", rom_board_name: board };
+
+       /* parse new-schema device object */
+       let dev = d.device ?? {};
+       let cmds = d.commands ?? {};
+       let parts = d.partitions && type(d.partitions) == "array" ? d.partitions : [];
+       let getcmd = cmds.get ?? "fw_printenv";
+       let active_num = null;
+
+       /* read current values for all params */
+       let curvals = [];
+
+       if (cmds.params && type(cmds.params) == "array" && length(cmds.params) > 0) {
+               for (let i = 0; i < length(cmds.params); i++) {
+                       let p = cmds.params[i];
+                       let v = null;
+                       if (p)
+                               v = command(getcmd + " -n " + shellquote(p) + " 2>/dev/null") || null;
+                       push(curvals, v);
+               }
+       } else {
+               let df = read_dual_flag_mtd();
+               let v = null;
+               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 };
+               v = read_dual_flag_value(df);
+               push(curvals, v);
+       }
+
+       let out_parts = [];
+       for (let i = 0; i < length(parts); i++) {
+               let p = parts[i] ?? {};
+               let num = p.number != null ? p.number : i;
+               let mtd = p.mtd ?? null;
+               let info = {};
+               let v;
+
+               if ("" + curvals[0] == "" + p.param_values[0]) {
+                       /* current partition */
+                       active_num = num;
+                       info = get_partition_info_current();
+               } else if (mtd && is_alt_mountable([mtd])) {
+                       /* attempt alt mount if we have mount options (or defaults) and tools */
+                       let amo = p.altMountOptions ?? {};
+                       let mtdOff = amo.mtdOffset == null ? 1 : int(amo.mtdOffset);
+                       let ubiVol = amo.ubiVolume == null ? 0 : int(amo.ubiVolume);
+                       let idx = mtd_index(mtd);
+                       if (idx != null) {
+                               let op_ubi = idx + mtdOff;
+                               info = get_partition_info_alt(op_ubi, dev.vendor ?? null, ubiVol);
+                               if (info && info.label == null && info.os == null) info = {};
+                       }
+               }
+               /* raw-label fallback if needed */
+               if (mtd && p.labelOffsetBytes != null) {
+                       if (!info?.label || !info?.os) {
+                               let fb = get_partition_info_fallback(
+                                       mtd,
+                                       p.labelOffsetBytes,
+                                       dev.vendor
+                               );
+                               if (!info) {
+                                       info = fb;
+                               } else {
+                                       if (fb && fb.label && (info.label == null || info.label == "")) {
+                                               info.label = fb.label;
+                                       }
+                                       if (fb && fb.os && (info.os == null || info.os == "")) {
+                                               info.os = fb.os;
+                                       }
+                               }
+                       }
+               }
+               push(out_parts, {
+                       number: "" + num,
+                       label: info ? info.label : null,
+                       os: info ? info.os : null,
+                       mtd: mtd,
+               });
+       }
+
+       return {
+               device: {
+                       vendor: dev.vendor ?? "",
+                       model: dev.model ?? "",
+                       board: board ?? "",
+                       partition_active: active_num != null ? "" + active_num : null,
+               },
+               partitions: out_parts,
+       };
+}
+
+/* Switch active boot partition by updating bootloader env or dual-flag.
+ *
+ * Accepts ubus args: { "number": "<partition-number>" }.
+ * Uses the device schema to map partition numbers to env values or dual-flag bytes.
+ *
+ * @param {{args:{number:String|Number}}} req
+ * @returns {Object} {} on success; {error:..., ...} on failure.
+ * @sideeffects  Calls fw_setenv/fw_saveenv or writes to dual-flag MTD.
+ */
+function boot_partition(req) {
+       /* extract target partition number from RPC args */
+       let number;
+       if (req && req.number != null) number = int(req.number);
+       if (!number)
+               return {
+                       error: "INVALID_ARG",
+                       detail: "number is required and must be numeric",
+               };
+
+       let board = get_board_name();
+       if (!board) return { error: "NO_BOARD_NAME" };
+
+       let d = find_device_info(board);
+       if (!d) return { error: "NO_BOARD_NAME_MATCH", rom_board_name: board };
+
+       let dev = d.device ?? {};
+       let cmds = d.commands ?? {};
+       let parts = d.partitions && type(d.partitions) == "array" ? d.partitions : [];
+       let params = cmds.params && type(cmds.params) == "array" ? cmds.params : [];
+       let setcmd = cmds.set ?? "fw_setenv";
+       let savecmd = cmds.save ?? null;
+       let target = null;
+
+       for (let i = 0; i < length(parts); i++) {
+               let p = parts[i] ?? {};
+               let num = p.number != null ? p.number : i;
+               if (num == number) {
+                       target = p;
+                       break;
+               }
+       }
+
+       if (!target) return { error: "PARTITION_NOT_FOUND", args: ["" + number] };
+
+       /* Set this partition active */
+       if (length(params) > 0) {
+               for (let j = 0; j < length(params); j++) {
+                       let param = params[j];
+                       let value = target.param_values ? target.param_values[j] : null;
+                       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 (rc != "0") return { error: "ERR_SAVE_ENV", rom_board_name: board };
+               }
+       } else {
+               let df = read_dual_flag_mtd();
+               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 };
+               if (!write_dual_flag_value(df, target.param_values[0]))
+                       return { error: "ERR_SET_DUAL_FLAG", args: [df], rom_board_name: board };
+       }
+       return {};
+}
+
+const methods = {
+       obtain_device_info: { call: obtain_device_info },
+       boot_partition: { args: { number: "String" }, call: boot_partition },
+};
+
+return { "luci.advanced-reboot": methods };
git clone https://git.99rst.org/PROJECT