[][OpenWrt Dev][Add support for dual-boot on UBI devices]
[Description]
Add support for dual-boot on UBI devices
Currently supported on mt7986
[Release-log]
N/A
Change-Id: I32e0f744baaacd9bb094c0764ccfdb2048ad798b
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6105794
diff --git a/openwrt_patches-21.02/140-nand-dual-boot-upgrade.patch b/openwrt_patches-21.02/140-nand-dual-boot-upgrade.patch
new file mode 100644
index 0000000..0ecaed8
--- /dev/null
+++ b/openwrt_patches-21.02/140-nand-dual-boot-upgrade.patch
@@ -0,0 +1,163 @@
+diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh
+index e6f58df..ba8c0fc 100644
+--- a/package/base-files/files/lib/upgrade/nand.sh
++++ b/package/base-files/files/lib/upgrade/nand.sh
+@@ -316,3 +316,158 @@ nand_do_platform_check() {
+
+ return 0
+ }
++
++dual_boot_upgrade_prepare_ubi() {
++ local kernel_vol_name="$1"
++ local rootfs_vol_name="$2"
++ local kernel_length="$3"
++ local rootfs_length="$4"
++ local reserve_rootfs_data="$5"
++
++ local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
++ if [ ! "$mtdnum" ]; then
++ echo "cannot find ubi mtd partition $CI_UBIPART"
++ return 1
++ fi
++
++ local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
++ if [ ! "$ubidev" ]; then
++ ubiattach -m "$mtdnum"
++ sync
++ ubidev="$( nand_find_ubi "$CI_UBIPART" )"
++ fi
++
++ if [ ! "$ubidev" ]; then
++ ubiformat /dev/mtd$mtdnum -y
++ ubiattach -m "$mtdnum"
++ sync
++ ubidev="$( nand_find_ubi "$CI_UBIPART" )"
++ ubimkvol /dev/$ubidev -n 0 -N u-boot-env -s 512KiB
++ fi
++
++ local rootfs_data_vol_name=$(cat /sys/module/boot_param/parameters/rootfs_data_part 2>/dev/null)
++
++ local kern_ubivol="$( nand_find_volume $ubidev $kernel_vol_name )"
++ local root_ubivol="$( nand_find_volume $ubidev $rootfs_vol_name )"
++ local data_ubivol="$( nand_find_volume $ubidev $rootfs_data_vol_name )"
++
++ # remove ubiblock device of rootfs
++ local root_ubiblk="ubiblock${root_ubivol:3}"
++ if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then
++ echo "removing $root_ubiblk"
++ if ! ubiblock -r /dev/$root_ubivol; then
++ echo "cannot remove $root_ubiblk"
++ return 1;
++ fi
++ fi
++
++ # kill volumes
++ [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $kernel_vol_name || true
++ [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N $rootfs_vol_name || true
++
++ # update kernel
++ if ! ubimkvol /dev/$ubidev -N $kernel_vol_name -s $kernel_length; then
++ echo "cannot create kernel volume"
++ return 1;
++ fi
++
++ # update rootfs
++ if ! ubimkvol /dev/$ubidev -N $rootfs_vol_name -s $rootfs_length; then
++ echo "cannot create rootfs volume"
++ return 1;
++ fi
++
++ if [ x"${reserve_rootfs_data}" = xY ]; then
++ # Do not touch rootfs_data
++ sync
++ return 0
++ fi
++
++ # 'format' rootfs_data volume
++ [ "$data_ubivol" ] && {
++ local rootfs_data_length=$(cat /sys/class/ubi/$data_ubivol/data_bytes)
++
++ # kill rootfs_data volume
++ ubirmvol /dev/$ubidev -N $rootfs_data_vol_name || true
++
++ # update rootfs_data
++ if ! ubimkvol /dev/$ubidev -N $rootfs_data_vol_name -s $rootfs_data_length; then
++ echo "cannot create $rootfs_data_vol_name volume"
++ fi
++ }
++
++ sync
++ return 0
++}
++
++ubi_dual_boot_upgrade_tar() {
++ local tar_file="$1"
++ local board_dir=$(tar tf ${tar_file} | grep -m 1 '^sysupgrade-.*/$')
++ local reserve_rootfs_data=$(cat /sys/module/boot_param/parameters/reserve_rootfs_data 2>/dev/null)
++ board_dir=${board_dir%/}
++
++ kernel_vol_name=$(cat /sys/module/boot_param/parameters/upgrade_kernel_part 2>/dev/null)
++ [ -z "${kernel_vol_name}" -o $? -ne 0 ] && return 1
++
++ rootfs_vol_name=$(cat /sys/module/boot_param/parameters/upgrade_rootfs_part 2>/dev/null)
++ [ -z "${rootfs_vol_name}" -o $? -ne 0 ] && return 1
++
++ local kernel_length=$( (tar xf ${tar_file} ${board_dir}/kernel -O | wc -c) 2> /dev/null)
++ local rootfs_length=$( (tar xf ${tar_file} ${board_dir}/root -O | wc -c) 2> /dev/null)
++
++ dual_boot_upgrade_prepare_ubi "${kernel_vol_name}" "${rootfs_vol_name}" \
++ "${kernel_length}" "${rootfs_length}" \
++ "${reserve_rootfs_data}"
++
++ local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
++
++ [ "${kernel_length}" != 0 ] && {
++ local kern_ubivol="$(nand_find_volume $ubidev ${kernel_vol_name})"
++ tar xf ${tar_file} ${board_dir}/kernel -O | \
++ ubiupdatevol /dev/${kern_ubivol} -s ${kernel_length} -
++ }
++
++ [ "${rootfs_length}" != 0 ] && {
++ local root_ubivol="$(nand_find_volume $ubidev ${rootfs_vol_name})"
++ tar xf ${tar_file} ${board_dir}/root -O | \
++ ubiupdatevol /dev/${root_ubivol} -s ${rootfs_length} -
++ }
++
++ upgrade_image_slot=$(cat /sys/module/boot_param/parameters/upgrade_image_slot 2>/dev/null)
++ [ -n "${upgrade_image_slot}" ] && {
++ v "Set new boot image slot to ${upgrade_image_slot}"
++ # Force the creation of fw_printenv.lock
++ mkdir -p /var/lock
++ touch /var/lock/fw_printenv.lock
++ fw_setenv "dual_boot.current_slot" "${upgrade_image_slot}"
++ fw_setenv "dual_boot.slot_${upgrade_image_slot}_invalid" "0"
++ }
++
++ if [ x"${reserve_rootfs_data}" != xY ]; then
++ # do normal upgrade flow
++ nand_do_upgrade_success
++ fi
++
++ # Do not touch rootfs_data
++ sync
++
++ echo "sysupgrade successful"
++ umount -a
++ reboot -f
++}
++
++ubi_do_upgrade() {
++ local dual_boot=$(cat /sys/module/boot_param/parameters/dual_boot 2>/dev/null)
++ local file_type=$(identify $1)
++
++ if [ x"${dual_boot}" != xY ]; then
++ nand_do_upgrade "$1"
++ return
++ fi
++
++ case "$file_type" in
++ "ubi") v "Unsupported firmware type: ubinized";;
++ "ubifs") v "Unsupported firmware type: ubifs";;
++ *) ubi_dual_boot_upgrade_tar $1;;
++ esac
++}
diff --git a/target/linux/mediatek/mt7986/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7986/base-files/lib/upgrade/platform.sh
index 0c66f47..bd38b22 100644
--- a/target/linux/mediatek/mt7986/base-files/lib/upgrade/platform.sh
+++ b/target/linux/mediatek/mt7986/base-files/lib/upgrade/platform.sh
@@ -6,7 +6,7 @@
case "$board" in
*snand*)
- nand_do_upgrade "$1"
+ ubi_do_upgrade "$1"
;;
*emmc*)
mtk_mmc_do_upgrade "$1"