From 7812d867b467735e2d938e4e51214829fd8882cc Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Fri, 11 Jul 2025 15:58:32 +0000 Subject: [PATCH] realtek: Introduce Plasma Cloud sysupgrade helper Plasma Cloud devices use a dual-firmware regions/slots boot mechanism. On APs, the u-boot is "intelligent" and checks the NOR/NAND partitions (kernel + rootfs) for corruption via "datachk". If validation fails, the bootloader automatically switches to the fallback partition. On Realtek-based switches, this "datachk" helper is not available. However, the bootloader still supports two firmware regions/slots. When flashing a new image, the "inactive" partition is written instead of overwriting the active one. If no "inactive" partition exists but "firmware1" is present, the bootloader always treats "firmware1" as fallback. Only after a successful flash is the `u-boot-env` updated to select the newly written partition. On reboot, the bootloader loads the kernel from the new partition and passes `mtdparts` information as the kernel cmdline. The Plasma Cloud switch device tree does not override this with a `bootargs` property, so the active partition layout is honored from cmdline. Since offsets, sizes, and names of partitions match between the device tree and cmdline (except the inactive slot), properties and nodes such as `nvmem-cells` or `compatible` remain fully usable. This mechanism also allows switching back to the old firmware slot. For example, if `firmware1` is currently active (`/proc/mtd` shows it), it can be switched to slot 2 using: . /lib/upgrade/upgrade_dualboot.sh set_boot_part 2 reboot Firmware upgrades use standard `sysupgrade` tarballs, chosen for compatibility with vendor images. In theory, one can switch between vendor and OpenWrt with: sysupgrade -n /tmp/*-squashfs-sysupgrade.bin Note: configuration files must not be preserved, as they are not compatible with vanilla OpenWrt. Signed-off-by: Harshal Gohel Signed-off-by: Sharadanand Karanjkar Link: https://github.com/openwrt/openwrt/pull/19362 Signed-off-by: Hauke Mehrtens --- .../upgrade/upgrade_dualboot_plasmacloud.sh | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 target/linux/realtek/base-files/lib/upgrade/upgrade_dualboot_plasmacloud.sh diff --git a/target/linux/realtek/base-files/lib/upgrade/upgrade_dualboot_plasmacloud.sh b/target/linux/realtek/base-files/lib/upgrade/upgrade_dualboot_plasmacloud.sh new file mode 100644 index 0000000000..0f379952b3 --- /dev/null +++ b/target/linux/realtek/base-files/lib/upgrade/upgrade_dualboot_plasmacloud.sh @@ -0,0 +1,68 @@ +set_boot_part() { + local part_num="$1" + local setenv_script="/tmp/fw_env_upgrade" + local board=$(board_name) + + case "$board" in + *) + echo "${board} is not supported for dual boot" 1>&2 + return 1 + ;; + esac + + # store u-boot env changes + mkdir -p /var/lock + cat $setenv_script + fw_setenv -s $setenv_script || { + echo "failed to update U-Boot environment" + return 1 + } +} + +platform_do_upgrade_dualboot_plasmacloud() { + local primary_firmware_mtd + local restore_backup + local next_boot_part + local tar_file="$1" + local inactive_mtd + local board_dir + + inactive_mtd="$(find_mtd_index $PART_NAME)" + if [ -z "$inactive_mtd" ]; then + # Handle case when u-boot-env is not correctly written and we + # are running from initramfs. Only install it in the "firmware1" + # partition + PART_NAME=firmware1 + inactive_mtd="$(find_mtd_index $PART_NAME)" + fi + + if [ -z "$inactive_mtd" ]; then + echo "Cannot find \"firmware1\" nor \"${$PART_NAME}\" partition to work with. Abort!" 2>&1 + return 1 + fi + + # identify "inactive" slot id based on the expected partition id + # of the primary ("firmware1") slot + case "$(board_name)" in + *) + echo "failed to detect primary firmware mtd partition for board" 2>&1 + return 1 + ;; + esac + + if [ "$inactive_mtd" = "$primary_firmware_mtd" ]; then + next_boot_part="1" + else + next_boot_part="2" + fi + + [ -n "$UPGRADE_BACKUP" ] && restore_backup="${MTD_CONFIG_ARGS} -j ${UPGRADE_BACKUP}" + + # write selected firmware slot + board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + tar -xf $tar_file ${board_dir}/kernel ${board_dir}/root -O | mtd $restore_backup write - $PART_NAME + + # update u-boot-env to select new firmware slot + set_boot_part "$next_boot_part" +} -- 2.30.2