U-boot integration in the bootloader process of Rasperry Pi CM4

Hello everyone,
I am learning about u-boot and how this works in the Raspberry Pi system. This is what I understood so far:
- The first stage from the RPI cannot or should be modified. In this stage the BootROM simply loads the bootloader from the flash EEPROM. - In the second stage the EEPROM boot loader finds and loads start.elf, whose task is to load the kernel. It first reads* config.txt* which contains a kernel parameter. This is where u-boot is "injected". *kernel=u-boot.bin*
Then u-boot can then in turn load the actual kernel. For a CM4 this would be "*kernel7l.img*".
I would be super satisfied with this knowledge, but in practice I have (possibly) seen other ways of integrating u-boot. I am here referring, for example, to Yocto recipes for the CM4 (meta-raspberrypi / u-boot). The boot directory of such an image contains: *boot.scr*, *uboot.env*, and *uImage*.
The readable part of boot.scr specifies that uImage will be loaded:
*value bootargs /chosen bootargsfatload mmc 0:1 ${kernel_addr_r} uImageif test ! -e mmc 0:1 uboot.env; then saveenv; fi;bootm ${kernel_addr_r} - ${fdt_addr}*
config.txt does not contain a kernel parameter.
*So here my questions:* 1) start.elf cannot be modified since it is proprietary. How can it load u-boot if there is no kernel parameter in config.txt pointing to a binary u-boot? boot.scr is supposed to run before u-boot.bin. Who reads and executes boot.scr? 2) is uImage just another name for u-boot.bin? 3) In this scheme how does u-boot know it should load "*kernel7l.img*"? 4) Are there other ways of integrating u-boot in a RaspberryPi? Is there any documentation which describes these different integration schemes?
Thank you very much for your help!
Best,
Anthony Arrascue

On 07/07/21 10:05, Anthony Arrascue wrote:
Hello everyone,
Hello
I am learning about u-boot and how this works in the Raspberry Pi system. This is what I understood so far:
- The first stage from the RPI cannot or should be modified. In this stage
the BootROM simply loads the bootloader from the flash EEPROM.
- In the second stage the EEPROM boot loader finds and loads start.elf,
whose task is to load the kernel. It first reads* config.txt* which contains a kernel parameter. This is where u-boot is "injected". *kernel=u-boot.bin*
Then u-boot can then in turn load the actual kernel. For a CM4 this would be "*kernel7l.img*".
I would be super satisfied with this knowledge, but in practice I have (possibly) seen other ways of integrating u-boot. I am here referring, for example, to Yocto recipes for the CM4 (meta-raspberrypi / u-boot). The boot directory of such an image contains: *boot.scr*, *uboot.env*, and *uImage*.
The readable part of boot.scr specifies that uImage will be loaded:
*value bootargs /chosen bootargsfatload mmc 0:1 ${kernel_addr_r} uImageif test ! -e mmc 0:1 uboot.env; then saveenv; fi;bootm ${kernel_addr_r} - ${fdt_addr}*
I'm not a RPI expert, but this is what know:
config.txt does not contain a kernel parameter.
It must not contain kernel params: it is used by start.elf, and configurations are relative to the things that start.elf does. Kernel parameters are contained in loaded devicetree, and read from it by u-boot in u-boot.scr with
fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs
command.
*So here my questions:*
- start.elf cannot be modified since it is proprietary. How can it load
u-boot if there is no kernel parameter in config.txt pointing to a binary u-boot? boot.scr is supposed to run before u-boot.bin. Who reads and executes boot.scr?
start.elf loads the binary named kernel7l.img. You need to rename u-boot.bin to kernel7.img, so start.elf loads u-boot instead of the kernel. You can read this post [1] from Andrei Gherzan, one of the meta-raspberrypi authors.
u.boot scr is executed by u-boot, so the execution order is
start.elf -> u-boot.bin -> u.boot.scr
- is uImage just another name for u-boot.bin?
No, it is the kernel image that u-boot loads throug u-boot.scr:
fatload mmc 0:1 ${kernel_addr_r} uImage
- In this scheme how does u-boot know it should load "*kernel7l.img*"?
See above
- Are there other ways of integrating u-boot in a RaspberryPi? Is there
any documentation which describes these different integration schemes?
AFAIK only the one described in [1] and done in meta-raspberrypi
Thank you very much for your help!
[1] https://andrei.gherzan.ro/linux/uboot-on-rpi/

Ciao Mauro,
Thanks for the resource! That clarifies quite a bit. - u-boot.bin is renamed as the *kernel7l.img*. In this way *start.elf* loads u-boot instead of the kernel - The actual kernel "*kernel7l.img*" is used to create *uImage *using the tool: *mkimage*.
Now I have only one doubt. Why does u-boot need to convert the kernel image in order to load it (with *bootm*)? Could not *bootz *be used to directly load *kernel7l.img*? as this tutorial describes: https://www.vdoo.com/blog/setting-up-u-boot-to-harden-the-boot-process
BTW I followed the steps from that tutorial, but I didn't manage to boot the kernel in that way. So I guess the extra-step *mkimg -> bootm* is necessary. I am just trying to figure out why.
Best,
Anthony Arrascue
On Wed, Jul 7, 2021 at 2:15 PM Mauro Salvini m.salvini@koansoftware.com wrote:
On 07/07/21 10:05, Anthony Arrascue wrote:
Hello everyone,
Hello
I am learning about u-boot and how this works in the Raspberry Pi system. This is what I understood so far:
- The first stage from the RPI cannot or should be modified. In this
stage
the BootROM simply loads the bootloader from the flash EEPROM.
- In the second stage the EEPROM boot loader finds and loads start.elf,
whose task is to load the kernel. It first reads* config.txt* which contains a kernel parameter. This is where u-boot is "injected". *kernel=u-boot.bin*
Then u-boot can then in turn load the actual kernel. For a CM4 this would be "*kernel7l.img*".
I would be super satisfied with this knowledge, but in practice I have (possibly) seen other ways of integrating u-boot. I am here referring,
for
example, to Yocto recipes for the CM4 (meta-raspberrypi / u-boot). The
boot
directory of such an image contains: *boot.scr*, *uboot.env*, and
*uImage*.
The readable part of boot.scr specifies that uImage will be loaded:
*value bootargs /chosen bootargsfatload mmc 0:1 ${kernel_addr_r} uImageif test ! -e mmc 0:1 uboot.env; then saveenv; fi;bootm ${kernel_addr_r} - ${fdt_addr}*
I'm not a RPI expert, but this is what know:
config.txt does not contain a kernel parameter.
It must not contain kernel params: it is used by start.elf, and configurations are relative to the things that start.elf does. Kernel parameters are contained in loaded devicetree, and read from it by u-boot in u-boot.scr with
fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs
command.
*So here my questions:*
- start.elf cannot be modified since it is proprietary. How can it load
u-boot if there is no kernel parameter in config.txt pointing to a binary u-boot? boot.scr is supposed to run before u-boot.bin. Who reads and executes boot.scr?
start.elf loads the binary named kernel7l.img. You need to rename u-boot.bin to kernel7.img, so start.elf loads u-boot instead of the kernel. You can read this post [1] from Andrei Gherzan, one of the meta-raspberrypi authors.
u.boot scr is executed by u-boot, so the execution order is
start.elf -> u-boot.bin -> u.boot.scr
- is uImage just another name for u-boot.bin?
No, it is the kernel image that u-boot loads throug u-boot.scr:
fatload mmc 0:1 ${kernel_addr_r} uImage
- In this scheme how does u-boot know it should load "*kernel7l.img*"?
See above
- Are there other ways of integrating u-boot in a RaspberryPi? Is there
any documentation which describes these different integration schemes?
AFAIK only the one described in [1] and done in meta-raspberrypi
Thank you very much for your help!
[1] https://andrei.gherzan.ro/linux/uboot-on-rpi/
-- Mauro Salvini | KOAN sas | Bergamo - Italia embedded software engineering Phone: +39 035-255235 http://KoanSoftware.com

On 07/07/21 14:50, Anthony Arrascue wrote:
Ciao Mauro,
Thanks for the resource! That clarifies quite a bit.
- u-boot.bin is renamed as the *kernel7l.img*. In this way *start.elf*
loads u-boot instead of the kernel
- The actual kernel "*kernel7l.img*" is used to create *uImage *using
the tool: *mkimage*.
Now I have only one doubt. Why does u-boot need to convert the kernel image in order to load it (with *bootm*)? Could not *bootz *be used to directly load *kernel7l.img*? as this tutorial describes: https://www.vdoo.com/blog/setting-up-u-boot-to-harden-the-boot-process https://www.vdoo.com/blog/setting-up-u-boot-to-harden-the-boot-process
BTW I followed the steps from that tutorial, but I didn't manage to boot the kernel in that way. So I guess the extra-step *mkimg -> bootm* is necessary. I am just trying to figure out why.
Yes, this is needed because bootm/bootz/booti u-boot commands needs different image formats (image headers, offsets, etc.)
regards
participants (2)
-
Anthony Arrascue
-
Mauro Salvini