]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
mvebu: cortexa53: uDPU/eDPU convert to dual firmware (A/B)
authorRobert Marko <robert.marko@sartura.hr>
Mon, 23 Feb 2026 16:41:18 +0000 (17:41 +0100)
committerRobert Marko <robert.marko@sartura.hr>
Tue, 26 May 2026 17:35:42 +0000 (19:35 +0200)
Methode uDPU and eDPU devices are one of the rare ones with a completely
custom image format being used with custom partition table with F2FS.

Instead of converting the boards to dual firmware (A/B style) and further
expand the already convoluted custom scripts, especially considering that
dual firmware conversion is a breaking change anyway, lets convert to using
the generic eMMC sysupgrade based images.

F2FS ZSTD compression is preserved thanks to fstools now supporting its use
on overlays.

Dual firmware support is implemented via U-Boot scripts so no U-Boot
upgrade is required.

Since there is a partition table layout change, eMMC must be wiped and
reflashed with the generated GPT image from OpenWrt initramfs.

Then on each sysupgrade the firmware slot will be altered.

Instructions:
1. Boot into OpenWrt initramfs
2. Copy openwrt-mvebu-cortexa53-methode_edpu-squashfs-emmc-gpt.img.gz to
the device into /tmp
3. Erase eMMC:
dd if=/dev/zero of=/dev/mmcblk0 bs=1M
4. Extract image
gzip -d /tmp/openwrt-mvebu-cortexa53-methode_edpu-squashfs-emmc-gpt.img.gz
5. Flash image
dd if=/tmp/openwrt-mvebu-cortexa53-methode_edpu-squashfs-emmc-gpt.img of=/dev/mmcblk0
6. Reboot

Signed-off-by: Robert Marko <robert.marko@sartura.hr>
target/linux/mvebu/cortexa53/base-files/etc/board.d/05_compat_version [new file with mode: 0644]
target/linux/mvebu/cortexa53/base-files/etc/init.d/bootcount [new file with mode: 0755]
target/linux/mvebu/cortexa53/base-files/lib/preinit/82_uDPU [deleted file]
target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh
target/linux/mvebu/cortexa53/base-files/lib/upgrade/uDPU.sh [deleted file]
target/linux/mvebu/cortexa53/target.mk
target/linux/mvebu/image/Makefile
target/linux/mvebu/image/cortexa53.mk
target/linux/mvebu/image/udpu.bootscript

diff --git a/target/linux/mvebu/cortexa53/base-files/etc/board.d/05_compat_version b/target/linux/mvebu/cortexa53/base-files/etc/board.d/05_compat_version
new file mode 100644 (file)
index 0000000..5a8f31e
--- /dev/null
@@ -0,0 +1,15 @@
+. /lib/functions.sh
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+case "$(board_name)" in
+       methode,udpu|\
+       methode,edpu)
+               ucidef_set_compat_version "2.0"
+       ;;
+esac
+
+board_config_flush
+
+exit 0
diff --git a/target/linux/mvebu/cortexa53/base-files/etc/init.d/bootcount b/target/linux/mvebu/cortexa53/base-files/etc/init.d/bootcount
new file mode 100755 (executable)
index 0000000..6ebf8ed
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+
+boot() {
+       case $(board_name) in
+       methode,udpu|\
+       methode,edpu)
+               fw_setenv bootcount 0
+       ;;
+       esac
+}
diff --git a/target/linux/mvebu/cortexa53/base-files/lib/preinit/82_uDPU b/target/linux/mvebu/cortexa53/base-files/lib/preinit/82_uDPU
deleted file mode 100644 (file)
index 1c72d0f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Copyright (C) 2014-2019 OpenWrt.org
-# Copyright (C) 2016 LEDE-Project.org
-#
-
-preinit_mount_udpu() {
-       . /lib/functions.sh
-       . /lib/upgrade/common.sh
-
-       case $(board_name) in
-       methode,udpu|\
-       methode,edpu)
-               # Check which device is detected
-               [ -b "/dev/mmcblk0" ] && mmcdev="/dev/mmcblk0" || mmcdev="/dev/mmcblk1"
-
-               if [ -b "${mmcdev}p4" ]; then
-                       mkdir /misc
-                       mount -o compress_algorithm=zstd -t f2fs ${mmcdev}p4 /misc
-                       [ -f "/misc/$BACKUP_FILE" ] && {
-                               echo "- Restoring configuration files -"
-                               tar xzf "/misc/$BACKUP_FILE" -C /
-                               rm -f "/misc/$BACKUP_FILE"
-                               sync
-                       }
-                       [ -f "/misc/firmware/recovery.itb" ] && {
-                                       echo "- Updating /recovery partition -"
-                                       mkfs.ext4 -q ${mmcdev}p2 | echo y &> /dev/null
-                                       mkdir -p /tmp/recovery
-                                       mount ${mmcdev}p2 /tmp/recovery
-                                       cp /misc/firmware/recovery.itb /tmp/recovery
-                                       [ -f "/misc/firmware/boot.scr" ] && \
-                                               cp /misc/firmware/boot.scr /tmp/recovery
-                                       sync
-                                       umount /tmp/recovery
-                                       rm -rf /tmp/recovery
-
-                                       # Replace previous backup with the new one
-                                       [ -d "/misc/firmware_old" ] && rm -rf /misc/firmware_old
-                                       [ -d "/misc/firmware" ] && mv /misc/firmware /misc/firmware_old
-                               }
-               fi
-
-               # Legacy support - if rootfs was booted, instruct u-boot to keep the current root dev
-               [ "$(df | grep /dev/root)" ] && fw_setenv root_ok '2'
-       ;;
-       esac
-}
-
-boot_hook_add preinit_main preinit_mount_udpu
index f77f15ecab6c36f54d60582c688a7d345fa51e7d..7ddb516762b0f51683e3d68dceae9bed5dae465b 100755 (executable)
@@ -35,7 +35,37 @@ platform_do_upgrade() {
                ;;
        methode,udpu|\
        methode,edpu)
-               platform_do_upgrade_uDPU "$1"
+               [ "$(rootfs_type)" = "tmpfs" ] && {
+                       local firmware_active="$(fw_printenv -n bootactive)"
+                       case "$firmware_active" in
+                       1)
+                               CI_KERNPART="kernel_2"
+                               CI_ROOTPART="rootfs_2"
+                               fw_setenv bootactive 2
+                               ;;
+                       2)
+                               CI_KERNPART="kernel_1"
+                               CI_ROOTPART="rootfs_1"
+                               fw_setenv bootactive 1
+                               ;;
+                       esac
+               }
+
+               local root="$(cmdline_get_var root)"
+               case "$root" in
+               /dev/mmcblk*p2)
+                       CI_KERNPART="kernel_2"
+                       CI_ROOTPART="rootfs_2"
+                       fw_setenv bootactive 2
+                       ;;
+               /dev/mmcblk*p4)
+                       CI_KERNPART="kernel_1"
+                       CI_ROOTPART="rootfs_1"
+                       fw_setenv bootactive 1
+                       ;;
+               esac
+
+               emmc_do_upgrade "$1"
                ;;
        *)
                default_do_upgrade "$1"
@@ -54,7 +84,7 @@ platform_copy_config() {
                ;;
        methode,udpu|\
        methode,edpu)
-               platform_copy_config_uDPU
+               emmc_copy_config
                ;;
        esac
 }
diff --git a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/uDPU.sh b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/uDPU.sh
deleted file mode 100644 (file)
index a8d803f..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-udpu_check_emmc() {
-# uDPU uses combined ext4 and f2fs partitions.
-# partition layout:
-#      1. boot (ext4)
-#      2. recovery  (ext4)
-#      3. rootfs (f2fs)
-#      4. misc (f2fs)
-
-       # Check which device is available, depending on the board revision
-       if [ -b "/dev/mmcblk1" ]; then
-               emmc_dev=/dev/mmcblk1
-       elif [ -b "/dev/mmcblk0" ]; then
-               emmc_dev=/dev/mmcblk0
-       else
-               echo "Cannot detect eMMC flash, aborting.."
-               exit 1
-       fi
-}
-
-udpu_part_prep() {
-        if grep -q "$1" /proc/mounts; then
-               mounted_part="$(grep -m 1 $1 /proc/mounts | awk '{print $2}')"
-               umount "$mounted_part"
-               grep -woq "$mounted_part" /proc/mounts && umount -l "$mounted_part"
-       fi
-}
-
-udpu_do_part_check() {
-       local emmc_parts="1 2 3 4"
-       local part_valid="1"
-
-       # Check if the block devices exist
-       for num in ${emmc_parts}; do
-               [ ! -b ${emmc_dev}p${num} ] && part_valid="0"
-       done
-
-       # If partitions are missing create a new partition table
-       if [ "$part_valid" != "1" ]; then
-               printf "Invalid partition table, creating a new one\n"
-               printf "o\nn\np\n1\n\n+256M\nn\np\n2\n\n+256M\nn\np\n3\n\n+1536M\nn\np\n\n\nw\n" | fdisk -W always $emmc_dev  > /dev/null 2>&1
-
-               # Format the /misc part right away as we will need it for the firmware
-               printf "Formating /misc partition, this make take a while..\n"
-               udpu_part_prep ${emmc_dev}p4
-               if mkfs.f2fs -q -l misc -O extra_attr,compression ${emmc_dev}p4; then
-                       printf "/misc partition formated successfully\n"
-               else
-                       printf "/misc partition formatting failed\n"
-               fi
-
-               udpu_do_initial_setup
-       else
-               printf "Partition table looks ok\n"
-       fi
-}
-
-udpu_do_misc_prep() {
-       if ! grep -woq /misc /proc/mounts; then
-               mkdir -p /misc
-
-               # If the mount fails, try to reformat partition
-               # Leaving possiblity for multiple iterations
-               if ! mount ${emmc_dev}p4 /misc; then
-                       printf "Error while mounting /misc, trying to reformat..\n"
-
-                       format_count=0
-                       while [ "$format_count" -lt "1" ]; do
-                               udpu_part_prep ${emmc_dev}p4
-                               mkfs.f2fs -q -l misc -O extra_attr,compression ${emmc_dev}p4
-                               if ! mount ${emmc_dev}p4 /misc; then
-                                       umount -l /misc
-                                       printf "Failed while mounting /misc\n"
-                                       format_count=$((format_count +1))
-                               else
-                                       printf "Mounted /misc successfully\n"
-                                       break
-                               fi
-                       done
-               fi
-       fi
-}
-
-udpu_do_initial_setup() {
-       # Prepare /recovery parition
-       udpu_part_prep ${emmc_dev}p2
-       mkfs.ext4 -qF ${emmc_dev}p2 2>&1 /dev/null
-
-       # Prepare /boot partition
-       udpu_part_prep ${emmc_dev}p1
-       mkfs.ext4 -qF ${emmc_dev}p1 2>&1 /dev/null
-
-       # Prepare /root partition
-       printf "Formating /root partition, this may take a while..\n"
-       udpu_part_prep ${emmc_dev}p3
-       mkfs.f2fs -q -l rootfs -O extra_attr,compression ${emmc_dev}p3 && printf "/root partition reformated\n"
-}
-
-udpu_do_regular_upgrade() {
-       # Clean /boot partition - mfks.ext4 is not available in chroot
-       grep -woq /boot /proc/mounts && umount /boot
-       mkdir -p /tmp/boot
-       mount ${emmc_dev}p1 /tmp/boot
-       rm -rf /tmp/boot/*
-
-       # Clean /root partition - mkfs.f2fs is not available in chroot
-       grep -woq /dev/root /proc/mounts && umount /
-       mkdir -p /tmp/rootpart
-       mount ${emmc_dev}p3 /tmp/rootpart
-       rm -rf /tmp/rootpart/*
-}
-
-platform_do_upgrade_uDPU() {
-       udpu_check_emmc
-
-       # Prepare and extract firmware on /misc partition
-       udpu_do_misc_prep
-
-       [ -f "/misc/firmware" ] && rm -r /misc/firmware
-       mkdir -p /misc/firmware
-       tar xzf "$1" -C /misc/firmware/
-
-       udpu_do_regular_upgrade
-
-       printf "Updating /boot partition\n"
-       if tar xzf /misc/firmware/boot.tgz -C /tmp/boot; then
-               printf "/boot partition updated successfully\n"
-       else
-               printf "/boot partition update failed\n"
-       fi
-       sync
-
-       printf "Updating /root partition\n"
-       if tar xzf /misc/firmware/rootfs.tgz -C /tmp/rootpart; then
-               printf "/root partition updated successfully\n"
-       else
-               printf "/root partition update failed\n"
-       fi
-       sync
-
-       # Saving configuration files over sysupgrade
-       platform_copy_config_uDPU
-
-       # Remove tmp mounts
-       tmp_parts=$(grep "${emmc_dev}" /proc/mounts | awk '{print $2}')
-       for part in ${tmp_parts}; do
-               umount "$part"
-               # Force umount is necessary
-               grep -q "${part}" /proc/mounts && umount -l "$part"
-       done
-
-       # Sysupgrade complains about /tmp and /dev, so we can detach them here
-       umount -l /tmp
-       umount -l /dev
-}
-
-platform_copy_config_uDPU() {
-       # Config is saved on the /misc partition and copied on the rootfs after the reboot
-       if [ -f "$UPGRADE_BACKUP" ]; then
-               cp -f "$UPGRADE_BACKUP" "/misc/$BACKUP_FILE"
-               sync
-       fi
-}
index fcf658c3983b0d140eaa0ff6ac7267a70f8d131c..48c8b7f0211d18e66fb778b7a381b66089147f5b 100644 (file)
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
 ARCH:=aarch64
 BOARDNAME:=Marvell Armada 3700LP (ARM64)
 CPU_TYPE:=cortex-a53
-FEATURES+=ext4
+FEATURES+=ext4 emmc
 DEFAULT_PACKAGES+=e2fsprogs ethtool mkf2fs partx-utils
 
 KERNELNAME:=Image dtbs
index 46b18fc524f0ff1d115c61ce066049bd0867c5c0..8f1dd4b5c7c132c75da0fbeac06717c5f22dc60a 100644 (file)
@@ -136,19 +136,6 @@ define Build/sdcard-img-ext4
                83 $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS)
 endef
 
-define Build/uDPU-firmware
-       (rm -fR $@-fw; mkdir -p $@-fw)
-       $(CP) $(BIN_DIR)/$(KERNEL_INITRAMFS_IMAGE) $@-fw/recovery.itb
-       $(CP) $(IMAGE_ROOTFS) $@-fw/rootfs.tgz
-       $(CP) $@-boot.scr $@-fw/boot.scr
-       $(TAR) -czp --numeric-owner --owner=0 --group=0 --sort=name \
-               $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
-               -f $@-fw/boot.tgz -C $@.boot .
-       $(TAR) -czp --numeric-owner --owner=0 --group=0 --sort=name \
-               $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
-               -f $(KDIR_TMP)/$(DEVICE_IMG_PREFIX)-firmware.tgz -C $@-fw .
-endef
-
 define Device/FitImage
   KERNEL_SUFFIX := -uImage.itb
   KERNEL = kernel-bin | libdeflate-gzip | fit gzip $$(KDIR)/image-$$(DEVICE_DTS).dtb
index e0f749a34ade2f9361e4d869164a1f78e8ce8e82..54823002fd308ccac8303c9ca6aa83036f04018c 100644 (file)
@@ -97,19 +97,46 @@ define Device/marvell_armada-3720-db
 endef
 TARGET_DEVICES += marvell_armada-3720-db
 
+define Build/methode-gpt-emmc
+  cp $@ $@.tmp 2>/dev/null || true
+  ptgen -g -o $@.tmp -l 1024 \
+      -t 0x2e -N kernel_1 -r -B -p 32M@1M \
+      -t 0x2e -N rootfs_1 -r -p 1536M@33M \
+      -t 0x2e -N kernel_2 -r -B -p 32M@1569M \
+      -t 0x2e -N rootfs_2 -r -p 1536M@1601M
+  cat $@.tmp >> $@
+  rm $@.tmp
+endef
+
+define Build/append-boot-part
+  dd if=$@.bootimg bs=32M conv=sync >> $@
+endef
+
+define Device/eMMC-methode
+  DEVICE_DTS_DIR := $(DTS_DIR)/marvell
+  KERNEL_NAME := Image
+  KERNEL := kernel-bin
+  KERNEL_LOADADDR := 0x00800000
+  DEVICE_PACKAGES += kmod-i2c-pxa kmod-hwmon-lm75 kmod-dsa-mv88e6xxx
+  DEVICE_COMPAT_VERSION := 2.0
+  DEVICE_COMPAT_MESSAGE := Partition layout and image format was changed. \
+  Upgrade requires reinstallation from initramfs.
+  FILESYSTEMS := squashfs
+  IMAGES := sysupgrade.bin emmc-gpt.img.gz
+  IMAGE/sysupgrade.bin := boot-scr | boot-img-ext4 | sysupgrade-tar kernel=$$$$@.bootimg | append-metadata
+  IMAGE/emmc-gpt.img.gz := methode-gpt-emmc |\
+    pad-to 1M  | boot-scr | boot-img-ext4 | append-boot-part |\
+    pad-to 33M | append-rootfs |\
+    gzip
+  BOOT_SCRIPT := udpu
+endef
+
 define Device/methode_udpu
-  $(call Device/Default-arm64)
+  $(call Device/eMMC-methode)
   $(call Device/FitImage)
   DEVICE_VENDOR := Methode
   DEVICE_MODEL := micro-DPU (uDPU)
   DEVICE_DTS := armada-3720-uDPU
-  KERNEL_LOADADDR := 0x00800000
-  DEVICE_PACKAGES += f2fs-tools fdisk kmod-i2c-pxa kmod-hwmon-lm75 kmod-dsa-mv88e6xxx
-  DEVICE_IMG_NAME = $$(DEVICE_IMG_PREFIX)-$$(2)
-  FILESYSTEMS := targz
-  IMAGES := firmware.tgz
-  IMAGE/firmware.tgz := boot-scr | boot-img-ext4 | uDPU-firmware | append-metadata
-  BOOT_SCRIPT := udpu
 endef
 TARGET_DEVICES += methode_udpu
 
index 741254e460bcc5946d936b9222677227c3602f6f..51eab7e381921a22d7bdf1b8808b9766950d43a1 100644 (file)
@@ -8,26 +8,67 @@ gpio clear 12; gpio clear 40; gpio clear 45;
 # Find eMMC device,
 if mmc dev 0; then
        setenv mmcdev 0
-       setenv rootdev 'root=/dev/mmcblk0p3'
 elif mmc dev 1; then
        setenv mmcdev 1
-       setenv rootdev 'root=/dev/mmcblk1p3'
 fi
 
+# Check if bootactive variable exists and if not, default to 1
+if test -z "${bootactive}"; then
+       setenv bootactive 1
+fi
+
+# Check if bootcount variable exists and if not, default to 0
+if test -z "${bootcount}"; then
+       setenv bootcount 0
+fi
+
+if itest ${bootcount} > 2; then
+       if itest ${bootactive} == 2; then
+               setenv bootactive 1
+       else
+               setenv bootactive 2
+       fi
+
+       setenv bootcount 0
+fi
+
+# Find A/B firmware to boot
+if itest ${bootactive} == 2; then
+       setenv kernelpart 3
+       setenv rootfspart 4
+else
+       setenv kernelpart 1
+       setenv rootfspart 2
+fi
+
+setenv rootdev 'root=/dev/mmcblk'${mmcdev}'p'${rootfspart}
+
 # Set the variables if necessary
 if test ${kernel_addr_r}; then
        setenv kernel_addr_r 0x5000000
 fi
 
-setenv console 'rootfs_mount_options.compress_algorithm=zstd'
-setenv bootargs ${console} $rootdev rw rootwait
+echo 'Booting firmware:' ${bootactive}
 
-load mmc ${mmcdev}:1 ${kernel_addr_r} Image
+if itest ${bootcount} == 0; then
+       setenv bootcount 1
+elif itest ${bootcount} == 1; then
+       setenv bootcount 2
+elif itest ${bootcount} == 2; then
+       setenv bootcount 3
+else
+       setenv bootcount 4
+fi
 
-bootm ${kernel_addr_r}
+env save
+
+setenv bootargs $rootdev rootwait fstools_overlay_compression_type=zstd
+
+load mmc ${mmcdev}:${kernelpart} ${kernel_addr_r} Image
 
-# If the boot command fails, fallback to recovery image
-echo '-- Boot failed, falling back to the recovery image --'
-setenv bootargs $console
-load mmc ${mmcdev}:2 ${kernel_addr_r} recovery.itb
 bootm ${kernel_addr_r}
+
+# If booting fails before kernel is loaded then reboot
+# so the bootcount can trigger a slot switch.
+echo 'Booting firmware:' ${bootactive} 'failed, rebooting'
+reset