RootFS OTA update with A/B redundancy boots with wrong rootfs partition

Hello,

i’m trying to create an OTA rootfs update on a AGX Xavier using A/B partition (JetPack 4.6.1 on a DevKit to start with).

Based on the docs
https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/updating_jetson_and_host.html#

Creating the initial A/B image to flash works fine.
The UUIDs for the rootfs partitions in bootloader/l4t-rootfs-uuid.txt(_b) are

10d78fd3-d2fc-41e2-afff-4fea3cc38e92
956a7876-c537-4c1b-b450-711ae3401547

which matches the PARTUUIDS of the booted system

sudo blkid
...
/dev/mmcblk0p1: UUID="8afa047b-17b9-402e-8533-98a918516b85" TYPE="ext4" PARTLABEL="APP" PARTUUID="10d78fd3-d2fc-41e2-afff-4fea3cc38e92"
/dev/mmcblk0p2: UUID="a20c681f-e538-47dc-8c4f-32fd0a5a1b91" TYPE="ext4" PARTLABEL="APP_b" PARTUUID="956a7876-c537-4c1b-b450-711ae3401547"
...

which also matches the root option in /boot/extlinux/extlinux.conf of both partitions:

APPEND ${cbootargs} quiet root=PARTUUID=10d78fd3-d2fc-41e2-afff-4fea3cc38e92 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4 usbcore.usbfs_memory_mb=2048

APPEND ${cbootargs} quiet root=PARTUUID=956a7876-c537-4c1b-b450-711ae3401547 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4 usbcore.usbfs_memory_mb=2048

and it matches also what the bootloader gives to the kernel at boot:

[0006.656] I> Continue to load from partition ...
[0006.656] I> A/B: bin_type (38) slot 0
[0006.657] I> Loading kernel-dtb from partition
[0006.657] I> Loading partition kernel-dtb at 0x91000000 from device(0x1)
[0006.670] I> Validate kernel-dtb ...
[0006.670] I> T19x: Authenticate kernel-dtb (bin_type: 38), max size 0x400000
[0006.675] I> Encryption fuse is not ON
[0006.677] I> removable_boot_load_kernel_and_dtb: force NVME bdev to close !!!
[0006.683] I> Kernel hdr @0xa0720000
[0006.686] I> Kernel dtb @0x90000000
[0006.689] I> decompressor handler not found
[0006.693] I> Copying kernel image (34484232 bytes) from 0xa0720800 to 0x80080000 ... [0006.706] I> Done
[0006.706] I> Move ramdisk (len: 7238344) from 0xa2804000 to 0x92000000
[0006.711] I> Updated bpmp info to DTB
[0006.713] I> Ramdisk: Base: 0x92000000; Size: 0x6e72c8
[0006.717] I> Updated initrd info to DTB
[0006.721] W> WARN: Fail to override "console=none" in commandline
[0006.727] I> Active rootfs suffix: 
[0006.730] E> tegrabl_linuxboot_add_disp_param, du 0 failed to get display params
[0006.738] E> tegrabl_linuxboot_add_disp_param, du 0 failed to get display params
[0006.745] E> tegrabl_linuxboot_add_disp_param, du 0 failed to get display params
[0006.752] I> Active slot suffix: 
[0006.755] I> add_boot_slot_suffix: slot_suffix = 
[0006.760] I> Linux Cmdline: console=ttyTCU0,115200 root=PARTUUID=10d78fd3-d2fc-41e2-afff-4fea3cc38e92 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4 usbcore.usbfs_memory_mb=2048  video=tegrafb earlycon=tegra_comb_uart,mmio32,0x0c168000 gpt rootfs.slot_suffix= usbcore.old_scheme_first=1 tegraid=19.1.2.0.0 maxcpus=8 boot.slot_suffix= boot.ratchetvalues=0.4.2 vpr_resize sdhci_tegra.en_boot_part_access=1

Up to this point everything is fine.

Also generating and installing the OTA rootfs update package works fine. The update doesn’t change the kernel or the jetpack version, just some files in the rootfs.
Both /boot/extlinux/extlinux.conf are still correct

When rebooting on Slot 1 (B partition) something is wrong, it still mounts rootfs partition A. The bootloader gives /dev/mmcblk0p1 (partition A) instead of the UUID of partition B to the kernel as root option:

[0006.659] I> Continue to load from partition ...
[0006.659] I> A/B: bin_type (38) slot 1
[0006.659] I> Loading kernel-dtb_b from partition
[0006.660] I> Loading partition kernel-dtb_b at 0x91000000 from device(0x1)
[0006.673] I> Validate kernel-dtb ...
[0006.673] I> T19x: Authenticate kernel-dtb (bin_type: 38), max size 0x400000
[0006.678] I> Encryption fuse is not ON
[0006.680] I> removable_boot_load_kernel_and_dtb: force NVME bdev to close !!!
[0006.686] I> Kernel hdr @0xa0720000
[0006.689] I> Kernel dtb @0x90000000
[0006.692] I> decompressor handler not found
[0006.696] I> Copying kernel image (34484232 bytes) from 0xa0720800 to 0x80080000 ... [0006.709] I> Done
[0006.709] I> Move ramdisk (len: 7238344) from 0xa2804000 to 0x92000000
[0006.714] I> Updated bpmp info to DTB
[0006.717] I> Ramdisk: Base: 0x92000000; Size: 0x6e72c8
[0006.721] I> Updated initrd info to DTB
[0006.724] W> WARN: Fail to override "console=none" in commandline
[0006.730] I> Active rootfs suffix: _b
[0006.734] E> tegrabl_linuxboot_add_disp_param, du 0 failed to get display params
[0006.741] E> tegrabl_linuxboot_add_disp_param, du 0 failed to get display params
[0006.748] E> tegrabl_linuxboot_add_disp_param, du 0 failed to get display params
[0006.755] I> Active slot suffix: _b
[0006.759] I> add_boot_slot_suffix: slot_suffix = _b
[0006.764] I> Linux Cmdline: console=ttyTCU0,115200 root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4  video=tegrafb earlycon=tegra_comb_uart,mmio32,0x0c168000 gpt rootfs.slot_suffix=_b usbcore.old_scheme_first=1 tegraid=19.1.2.0.0 maxcpus=8 boot.slot_suffix=_b boot.ratchetvalues=0.4.2 vpr_resize sdhci_tegra.en_boot_part_access=1

So after booting the wrong (A) rootfs is mounted. The system still believes that the active slot is 1.

After rollback (setting active slot to 0 again) and rebooting the system boots fine again on slot 0 with the kernel being given the correct UUID as root option as after the initial flash.

So why does the kernel receive a device path instead of an uuid when booting from slot 1 ? And why is it mmcblk0p1 instead of mmcblk0p2 ?

Thanks and best regards

Some additional info.

After initial flashing of my A/B base image using the flash.sh tool, the system boots fine on slot 0.

After doing sudo nvbootctrl set-active-boot-slot 1 and rebooting the system boots fine on slot 1. The bootloader gives the correct uuid of APP_b as root to the kernel and mmcblk2 id mounted at /.
Typing sudo nvbootctrl set-active-boot-slot 0 and rebooting again the same, the correct APP uuid is given to the kernel by the bootloader and mmcblk1 is mounted at /.

So the base image we flash seems ok.

After a sudo ./nv_ota_start.sh ota_payload_package.tar.gz from slot 0 and rebooting, the same error again: bootloader gives /dev/mmcblk0p1 as root to the kernel and the wrong partition is mounted on /. The nv_ota_start.sh tools doesn’t report any problem.

So either i miss a mandatory step when running nv_ota_start.sh or there is a problem with the ota_payload_package.tar.gz we generate.

The ota_payload_package.tar.gz is generated with

sudo ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh -sr -o rootfs_updater.sh -f image.tar.gz jetson-agx-xavier-devkit R32-6

where rootfs_updater.sh is just the one from tools/ota_tools/version_upgrade/nv_ota_rootfs_updater.sh, no modifications made.

Hi,

After doing sudo nvbootctrl set-active-boot-slot 1 and rebooting the system boots fine on slot 1. The bootloader gives the correct uuid of APP_b as root to the kernel and mmcblk2 id mounted at /.
Typing sudo nvbootctrl set-active-boot-slot 0 and rebooting again the same, the correct APP uuid is given to the kernel by the bootloader and mmcblk1 is mounted at /.

So using flash.sh is able to get the rootfs switch between A and B slot without problem?

And now the current issue is after the OTA update, the switch of rootfs between A/B gets failure?

Exactly, after the initial flash with sudo ROOFS_AB=1 ./flash.sh ....i can switch between A and B without problem by setting the active slot.
After ./nv_ota_start.sh there is the issue with the wrong rootfs on the updated slot.

Did you run this “l4t_generate_ota_package.sh” tool on your host with 32.6.1 base?

So image based OTA upgrade target and base are both rel-32.6.1 here?

Exact, generated from a 32.6.1 base, in fact the same directory that was used to generate the initially flashed image.j So both, base and target on 32.6.1.

The only customization i might need to add is that the partitioning is not the default one, BMP and BMP_b are removed. But both on the initial flashed image and in the update, so no layout change during the update.

Hi martin.herren,

We tried below steps on r32.6.1/Xavier is working:

  1. Flash the target board with redundant root file systems:
    $ sudo ROOTFS_AB=1 ./flash.sh jetson-xavier mmcblk0p1
  2. After boot-up and switch slot 0/1 are working.
  3. Prepare “ota_payload_package.tar.gz” on host ubuntu machine.
    → Please make sure “TARGET_BSP”, “ToT_BSP” and “BASE_BSP” are set correct.
  4. Copy “ota_payload_package.tar.gz” and “ota_tools_R32.6.1_aarch64.tbz2” to Xavier
  5. Follow below steps on Xavier:
1. Review /boot/extlinux/extlinux.conf:
"INITRD /boot/initrd" is set under the LINUX /boot/Image
"root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4" add into the APPEND line.
2. copy ota_tools_R32.6.1_aarch64.tbz2 and ota_payload_package.tar.gz to Jetson device
3. Set WORKDIR
$ WORKDIR=/home/nvidia/OTA
$ tar xpvf ota_tools_R32.6.1_aarch64.tbz2 -C $WORKDIR
$ sudo mkdir /ota
$ sudo cp ota_payload_package.tar.gz /ota
$ cd ${WORKDIR}/Linux_for_Tegra/tools/ota_tools/version_upgrade
$ sudo ./nv_ota_start.sh /dev/mmcblk0 /ota/ota_payload_package.tar.gz
$ sudo reboot
  1. After boot up and switch slot 0/1 again, check UUID and APP partition are correct.

Please check steps and try again.

Retried every step a few times, still same result.

Even tried to generate the ota_payload_package.tar.gz from the image.bin.raw file generated through ./flash.sh on initial image creation instead of the clone.bin.raw obtained through cloning the image with ./flash.sh from the target device. Evertime the same result.

Noted another strange behavior:

My mmcblk0p1 /boot/extlinux/extlinux.conf contains

      INITRD /boot/initrd
      APPEND ${cbootargs} quiet root=PARTUUID=10d78fd3-d2fc-41e2-afff-4fea3cc38e92 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4 usbcore.usbfs_memory
_mb=2048 

and the one on mmcblk0p2:


      INITRD /boot/initrd
      APPEND ${cbootargs} quiet root=PARTUUID=956a7876-c537-4c1b-b450-711ae3401547 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4 usbcore.usbfs_memory
_mb=2048 

The usbcore.usbfs_memory-mb=2048 was originally given to flash.sh through the -C option. I didn’t modify any extlinux.conf file.

When booting slot 0, kernel options are correctly

[0006.765] I> Active slot suffix: 
[0006.768] I> add_boot_slot_suffix: slot_suffix = 
[0006.773] I> Linux Cmdline: console=ttyTCU0,115200 root=PARTUUID=10d78fd3-d2fc-41e2-afff-4fea3cc38e92 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4 
usbcore.usbfs_memory_mb=2048  video=tegrafb earlycon=tegra_comb_uart,mmio32,0x0c168000 gpt rootfs.slot_suffix= usbcore.old_scheme_first=1 tegraid=19.1.2.0.0 maxcpus=8 boot.slot_suffix= boot.ratchetvalues=0.4.2 v
pr_resize sdhci_tegra.en_boot_part_access=1 

and from slot1 after upgrade:

[0006.756] I> Active slot suffix: _b
[0006.759] I> add_boot_slot_suffix: slot_suffix = _b
[0006.764] I> Linux Cmdline: console=ttyTCU0,115200 root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyTCU0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 rootfstype=ext4  video=tegrafb earlycon=tegra_c
omb_uart,mmio32,0x0c168000 gpt rootfs.slot_suffix=_b usbcore.old_scheme_first=1 tegraid=19.1.2.0.0 maxcpus=8 boot.slot_suffix=_b boot.ratchetvalues=0.4.2 vpr_resize sdhci_tegra.en_boot_part_access=1 

So the usbcore.usbfs_memory_mb=2048 option got lost as well during the upgrade even if still present in both extlinux.conf files. Looks like the extlinux.conf file gets ignored after OTA upgrade.

Just want to double confirm that. Do you have ethernet cable connected when running image based OTA?

Yes, ethernet is always connected. I upload the ota_payload_package.tar.gz through scp to the jetson board.

Are you talking about the extlinux.conf in slot 2 still has the correct uuid but the kernel cmdline does not have it?

Could you share the full boot up log with us when this case happens?

And please always attach the full log. This forum can attach files directly.

Exactly. extlinux.conf in slot 1 is correct before the upgrade, still correct after the upgrade but before rebooting, and still correct after rebooting on slot 1, but the kernel cmdline has the wrong options: root=/dev/mmcblk1 instead of APP_b’s PARTUUID and usbcore.usbfs_memory_mb=2048 missing.

Before the upgrade, booting slot 1 has the correct kernel cmdline, as does booting from slot 0.

Full log of nv_ota_start.sh and booting on slot 1 attached. Also for reference a successful boot on slot 0.

nv_ota_start.log (12.1 KB)
boot_slot_1.log (92.5 KB)
boot_slot_0.log (92.7 KB)

I am not sure if this is done by you on purpose or even you didn’t know it.

Do you know that your device is booting from a nvme instead of internal emmc? Does “enabling rootfs A/B on nvme” what you want here?

What @carolyuu tried was all on emmc. We didn’t use nvme to do the test.

There is a nvme present, but it is should just be a data partition. There is no OS or rootfs installed on it. Kernel, DTB, Rootfs are all on the internal emmc.
But boot logs are indeed confusing when it probes first the SD and NVME. Maybe i should configure the boot configuration not to probe SD and NVME ?

Rootfs is on mmcblk0p1 and nvmeon1 is mounted as data:

/dev/mmcblk0p1 on / type ext4 (rw,relatime,data=ordered)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
none on /dev type devtmpfs (rw,relatime,size=7717504k,nr_inodes=1929376,mode=755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/debug type cgroup (rw,nosuid,nodev,noexec,relatime,debug)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=26,pgrp=1,timeout=0,minproto=5,maxproto=5,direct)
sunrpc on /run/rpc_pipefs type rpc_pipefs (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
mqueue on /dev/mqueue type mqueue (rw,relatime)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime)
configfs on /sys/kernel/config type configfs (rw,relatime)
/dev/nvme0n1 on /mnt/erxssd type ext4 (rw,relatime,data=ordered)
/dev/mmcblk0p41 on /data type ext4 (rw,relatime,data=ordered)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=1620436k,mode=700,uid=1000,gid=1000)

By the way mmcblk0p41 is the UDA partition. We don’t have BMP and BMP_b:

ls -l /dev/disk/by-partlabel/
total 0
lrwxrwxrwx 1 root root 16 Nov  2 11:16 adsp-fw -> ../../mmcblk0p23
lrwxrwxrwx 1 root root 16 Nov  2 11:16 adsp-fw_b -> ../../mmcblk0p24
lrwxrwxrwx 1 root root 15 Nov  2 11:16 APP -> ../../mmcblk0p1
lrwxrwxrwx 1 root root 15 Nov  2 11:16 APP_b -> ../../mmcblk0p2
lrwxrwxrwx 1 root root 15 Nov  2 11:16 bootloader-dtb -> ../../mmcblk0p9
lrwxrwxrwx 1 root root 16 Nov  2 11:16 bootloader-dtb_b -> ../../mmcblk0p10
lrwxrwxrwx 1 root root 16 Nov  2 11:16 bpmp-fw -> ../../mmcblk0p15
lrwxrwxrwx 1 root root 16 Nov  2 11:16 bpmp-fw_b -> ../../mmcblk0p16
lrwxrwxrwx 1 root root 16 Nov  2 11:16 bpmp-fw-dtb -> ../../mmcblk0p17
lrwxrwxrwx 1 root root 16 Nov  2 11:16 bpmp-fw-dtb_b -> ../../mmcblk0p18
lrwxrwxrwx 1 root root 16 Nov  2 11:16 CPUBL-CFG -> ../../mmcblk0p37
lrwxrwxrwx 1 root root 15 Nov  2 11:16 cpu-bootloader -> ../../mmcblk0p7
lrwxrwxrwx 1 root root 15 Nov  2 11:16 cpu-bootloader_b -> ../../mmcblk0p8
lrwxrwxrwx 1 root root 16 Nov  2 11:16 eks -> ../../mmcblk0p13
lrwxrwxrwx 1 root root 16 Nov  2 11:16 eks_b -> ../../mmcblk0p14
lrwxrwxrwx 1 root root 16 Nov  2 11:16 kernel -> ../../mmcblk0p33
lrwxrwxrwx 1 root root 16 Nov  2 11:16 kernel_b -> ../../mmcblk0p34
lrwxrwxrwx 1 root root 16 Nov  2 11:16 kernel-bootctrl -> ../../mmcblk0p31
lrwxrwxrwx 1 root root 16 Nov  2 11:16 kernel-bootctrl_b -> ../../mmcblk0p32
lrwxrwxrwx 1 root root 16 Nov  2 11:16 kernel-dtb -> ../../mmcblk0p35
lrwxrwxrwx 1 root root 16 Nov  2 11:16 kernel-dtb_b -> ../../mmcblk0p36
lrwxrwxrwx 1 root root 15 Nov  2 11:16 mts-mce -> ../../mmcblk0p3
lrwxrwxrwx 1 root root 15 Nov  2 11:16 mts-mce_b -> ../../mmcblk0p4
lrwxrwxrwx 1 root root 15 Nov  2 11:16 mts-proper -> ../../mmcblk0p5
lrwxrwxrwx 1 root root 15 Nov  2 11:16 mts-proper_b -> ../../mmcblk0p6
lrwxrwxrwx 1 root root 16 Nov  2 11:16 rce-fw -> ../../mmcblk0p21
lrwxrwxrwx 1 root root 16 Nov  2 11:16 rce-fw_b -> ../../mmcblk0p22
lrwxrwxrwx 1 root root 16 Nov  2 11:16 recovery -> ../../mmcblk0p29
lrwxrwxrwx 1 root root 16 Nov  2 11:16 recovery-dtb -> ../../mmcblk0p30
lrwxrwxrwx 1 root root 16 Nov  2 11:16 RECROOTFS -> ../../mmcblk0p40
lrwxrwxrwx 1 root root 16 Nov  2 11:16 RP1 -> ../../mmcblk0p38
lrwxrwxrwx 1 root root 16 Nov  2 11:16 RP2 -> ../../mmcblk0p39
lrwxrwxrwx 1 root root 16 Nov  2 11:16 sc7 -> ../../mmcblk0p27
lrwxrwxrwx 1 root root 16 Nov  2 11:16 sc7_b -> ../../mmcblk0p28
lrwxrwxrwx 1 root root 16 Nov  2 11:16 sce-fw -> ../../mmcblk0p25
lrwxrwxrwx 1 root root 16 Nov  2 11:16 sce-fw_b -> ../../mmcblk0p26
lrwxrwxrwx 1 root root 16 Nov  2 11:16 secure-os -> ../../mmcblk0p11
lrwxrwxrwx 1 root root 16 Nov  2 11:16 secure-os_b -> ../../mmcblk0p12
lrwxrwxrwx 1 root root 16 Nov  2 11:16 UDA -> ../../mmcblk0p41
lrwxrwxrwx 1 root root 16 Nov  2 11:16 xusb-fw -> ../../mmcblk0p19
lrwxrwxrwx 1 root root 16 Nov  2 11:16 xusb-fw_b -> ../../mmcblk0p20

Please remove the nvme and see what will happen first.

Ok, first i reflashed the board (with the NVME still present) with the initial image to reset a clean state.
Then i removed the NVME and the system booted fine in slot 0. I changed to slot 1 and it rebooted fine from there as well.
What changed:

  • no root option given to the kernel anymore, only rootfs.slot_suffix
  • usbcore.usbfs_memory_mb=2048 missing from kernel options also

But in both cases it boots fine with the correct root partition mounted.

So something seems to be put in NVME as already without OTA upgrade we have a different behavior on kernel cmdline.

Both logs attached.
boot_0.log (37.3 KB)
boot_1.log (37.3 KB)

Next test, before retrying an update, i can reflash it with the same image without the NVME from start to see if something changes.

No difference is seen when doing the initial flash without NVME. (Same image flashed, using -r option on flash.sh).

In the logs still no root option given nor usbcore.usbfs_memory_mb, but the values end up correct.

Please also share the boot log.

Here it is
boot_0.log (37.3 KB)