Skip to content

rpi-u-boot-scr: load the kernel from the bootflow device - #1635

Open
wonwondogs wants to merge 2 commits into
agherzan:masterfrom
wonwondogs:rpi-u-boot-scr-usb-bootflow-device
Open

wonwondogs wants to merge 2 commits into
agherzan:masterfrom
wonwondogs:rpi-u-boot-scr-usb-bootflow-device

Conversation

@wonwondogs

@wonwondogs wonwondogs commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

- What I did

Fix kernel loading when another USB drive is enumerated before the boot drive. U-Boot can find boot.scr on USB device 1, while the old script loads the kernel from device 0. The script now uses the bootflow device and partition, with the previous BOOT_MEDIA 0:1 behavior as a fallback when bootflow information is unavailable.

- How I did it

Use ${devtype}, ${devnum}, and ${distro_bootpart} for the kernel load when bootflow provides them. Check uboot.env on mmc 0:1, where U-Boot stores it, rather than on the boot device. An existing environment without the rpi_bootscr_env marker may contain stale bootflow variables saved by an older script. On that migration boot, ignore those variables and save the environment once without them and with the marker. Guard the save with mmc dev 0 so USB-only systems do not attempt to save to a missing SD card. Update the boot media documentation to explain the fallback and migration behavior.

- Testing

Built core-image-minimal for raspberrypi4-64 with RPI_USE_U_BOOT=1. On a Pi 4, tested SD-only boot, USB-only boot without an SD card, migration with SD and USB connected, manual source after reloading an environment with stale variables, and two USB drives with the boot drive enumerated as USB 1. The tested paths reached the serial login prompt. In the SD-plus-USB migration test, U-Boot started from SD, boot_targets=usb was set in RAM, the kernel was read from USB, and Linux used the SD root filesystem.

For the two-USB test, root=/dev/sda2 pointed to the other drive, so I set the boot drive's PARTUUID in the FDT in RAM. This test verifies U-Boot's kernel source selection; the PR does not change Linux root selection or claim that Pi firmware chooses the same USB drive when both are present at power-on. git diff --check passed.

@agherzan

Copy link
Copy Markdown
Owner

Thanks for this! This was one of the fixes I had pending. Could clarify how are those uboot flow variables provided/defined?

@agherzan

Copy link
Copy Markdown
Owner

Thanks for this! This was one of the fixes I had pending. Could clarify how are those uboot flow variables provided/defined?

It's auto detected by uboot as the device/part on which bootscr is on.

@wonwondogs

Copy link
Copy Markdown
Contributor Author

It's auto detected by uboot as the device/part on which bootscr is on.

Yes, exactly. In the bootflow path, U-Boot's script bootmeth sets devnum from the block device containing boot.scr (desc->devnum) and distro_bootpart from its partition (bflow->part) before running the script. The assignments are in script_boot().

My Pi 4 image uses bootcmd=bootflow scan. With two USB drives attached, the serial console showed:

devtype=usb
devnum=1
distro_bootpart=1
bootcmd=bootflow scan
U-Boot> fatload ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} uImage
9131832 bytes read in 231 ms (37.7 MiB/s)

@agherzan agherzan left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks once again for looking into this. A couple of small things:

  1. Bootflow also sets ${devtype}, so there's no need for @@BOOT_MEDIA@@ in the fatload.
  2. Could you add a fallback for when the script runs outside bootflow (a manual source, an old custom bootcmd)? Defaulting to @@BOOT_MEDIA@@ and 0:1 would keep the old behaviour.

@agherzan

Copy link
Copy Markdown
Owner

Looking a bit more into this, I think the saveenv part needs fixing too: the check looks at the boot device while the env always lives on mmc 0:1, and the saved env picks up the bootflow variables, which can go stale. Would you be able to look into this as well, or at least open a small issue so we can pick it up later?

@wonwondogs

Copy link
Copy Markdown
Contributor Author

Thanks for catching this! I'll look into the environment location and the stale bootflow variables, and address them in this PR. I'll update the patch after testing the change.

@agherzan agherzan self-assigned this Oct 18, 2026
@wonwondogs

Copy link
Copy Markdown
Contributor Author

Thanks for the review and for catching the saveenv issue. I've pushed a follow-up commit addressing the points you raised.

The script now uses the bootflow device type, number, and partition to load the kernel. When that information is unavailable, it falls back to BOOT_MEDIA 0:1. It checks uboot.env on mmc 0:1, where U-Boot saves the environment. An existing environment without the migration marker may contain stale bootflow variables, so the script ignores them for that boot and saves the environment once without them. It also avoids trying to save when no SD card is present. I updated the boot media documentation accordingly.

I tested SD-only and USB-only boot, manual source after reloading an environment with stale variables, and a two-USB setup where the boot drive was USB 1. I also tested migration with SD and USB connected: U-Boot ran the USB script and read the kernel from USB, while Linux used the SD root filesystem. The following boot did not save the environment again.

For the two-USB test, I changed the Linux root argument to the boot drive's PARTUUID in the FDT in RAM, because /dev/sda2 pointed to the other drive. That test verifies the U-Boot kernel source; this patch does not change Linux root selection.

Selected serial excerpts follow. With a markerless environment containing stale USB values, a manual source loaded the SD kernel and saved a cleaned environment:

## Error: "rpi_bootscr_env" not defined
devtype=usb
devnum=0
distro_bootpart=1
U-Boot> load mmc 0:1 ${scriptaddr} boot.scr
1060 bytes read in 9 ms (114.3 KiB/s)
U-Boot> source ${scriptaddr}
27118080 bytes read in 5612 ms (4.6 MiB/s)
mmc0 is current device
Saving Environment to FAT... OK

With two USB drives, Dell was device 0 and KIOXIA was device 1; the script bootflow then read the KIOXIA kernel:

Device 0: Vendor: Dell     Rev: 8.07 Prod: Recovery USB
Device 1: Vendor: KIOXIA   Rev: PMAP Prod: TransMemory
** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with script
27777536 bytes read in 696 ms (38.1 MiB/s)

I have retained the full redacted serial logs.

@wonwondogs
wonwondogs requested a review from agherzan October 18, 2026 11:32

@agherzan agherzan left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'm thinking something simpler like:

fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs

if test -n "${devtype}" -a -n "${devnum}" -a -n "${distro_bootpart}"; then
    fatload ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} @@KERNEL_IMAGETYPE@@
else
    fatload @@BOOT_MEDIA@@ 0:1 ${kernel_addr_r} @@KERNEL_IMAGETYPE@@
fi

if test "${devtype}" = mmc -a "${devnum}" = 0 -a "${distro_bootpart}" = 1 -a ! -e mmc 0:1 uboot.env; then
    env delete devtype devnum distro_bootpart prefix
    saveenv
fi

@@KERNEL_BOOTCMD@@ ${kernel_addr_r} - ${fdt_addr}

With some extra nice comments :)
Also, can you squash the commits? Unless there is a food reason to split it in multiple commits - o can't see why though.

When bootflow finds boot.scr on a USB drive other than device 0, the
script still loads the kernel from BOOT_MEDIA 0:1 and can pick the wrong
drive. Use devtype, devnum and distro_bootpart set by bootflow, falling
back to BOOT_MEDIA 0:1 when they are not set, and update the BOOT_MEDIA
documentation to match.

Only create uboot.env when booting from mmc 0:1, where U-Boot keeps it,
so a USB boot does not write to an inserted SD card. Delete the per-boot
bootflow variables before saving.

Tested on a Raspberry Pi 4: SD boot, USB boot, and kernel loading from
the second of two USB drives.

Signed-off-by: Keisuke Tsukuda <tkdkei@outlook.jp>
@wonwondogs
wonwondogs force-pushed the rpi-u-boot-scr-usb-bootflow-device branch from f916a67 to f34d8ae Compare October 18, 2026 16:44
@wonwondogs

Copy link
Copy Markdown
Contributor Author

@agherzan
I switched to your suggested version, with short comments and no marker. The docs change is just the BOOT_MEDIA sentence.

I retested on a Pi 4: two SD boots (env saved once, without bootflow variables), USB-only, USB with an SD card lacking uboot.env (no save), manual source using the fallback, and two USB drives with the boot drive at USB 1 (kernel loaded from USB 1).

Old uboot.env files can still contain stale bootflow variables. Bootflow overwrites them, but manual source or a custom bootcmd may use them. The new script won't save them in new files, but it doesn't migrate existing ones. I left that alone since we dropped the marker. Let me know if you'd like a separate fix! Thanks!

@wonwondogs
wonwondogs requested a review from agherzan October 18, 2026 17:03

@agherzan agherzan left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks good. No need for a separate fix for existing envs: bootflow overwrites those variables on every boot, so they only affect a manual source. There are some things we can improve but I'd leave them for another PR/commit/issue:

  1. The fixed env location
  2. The save is a snapshot of everything including the old env defaults
  3. fw_printenv not working on USB boot
  4. U-Boot reading another image's uboot.env from an inserted SD card

All these existed before and I'd look into them separately as an improvement to the environment setup.

Once again, cheers for this!

@wonwondogs

Copy link
Copy Markdown
Contributor Author

@agherzan
Thanks again for your help with this PR! I'm designing my own CM4 carrier board and spending a lot of time with Yocto at the moment. I'd like to get more involved in the project and contribute where I can!

@agherzan

Copy link
Copy Markdown
Owner

@agherzan Thanks again for your help with this PR! I'm designing my own CM4 carrier board and spending a lot of time with Yocto at the moment. I'd like to get more involved in the project and contribute where I can!

Happy to hear.

BTW, I'm currently refreshing the CI infrastructure a bit, and as soon as that lands, I'll update your branch and kick off the CI for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants