[U-Boot] [PATCH 1/2] Pass through start.elf bootargs on Raspberry Pi

Stephen Warren swarren at wwwdotorg.org
Wed Dec 2 05:14:59 CET 2015


On 11/29/2015 11:40 AM, Marco Schuster wrote:
> On Raspberry Pi, the primary bootloader start.elf uses the options in
> config.txt, as well as options hidden in the firmware itself, to tell
> the Linux kernel e.g. framebuffer sizes, memory regions, MAC addresses
> and more.

Was this patch sent using "git send-email"? I assume not, since it is
corrupted due to wrapping.

I suspect ./scripts/checkpatch.pl also wasn't run, since it would
complain about over-long lines, and multiple other formatting errors.

> Normally, u-boot would not be able to pass through these options to
> the Linux kernel. This patch adds pass-through support via an
> additional env variable "bootargs_orig" which is loaded with the
> original cmdline obtained from ATAG or the FDT.
> 
> In addition, this allows the user to configure DT overlays the "Pi
> way" by enabling them in config.txt, as this patch passes through the
> full FDT if it has been passed one by u-boot.
> 
> Note that, as stated in the comment block, for FDT passthrough to
> work, the u-boot.img must be run through a perl script by the
> Raspberry Pi Foundation, which appends a trailer to the image telling
> start.elf to supply a FDT instead of an ATAG struct.

This feature sounds fine. However, it should be optional. It likely only
makes sense when booting a downstream Pi Foundation kernel, and not when
booting an upstream/mainline kernel with matching DT using the
standardized DT bindings. As such, I think this feature should be
optional (e.g. perhaps en-/dis-abled by an environment variable at
run-time) so that the user gets to choose whether to use the feature.

> diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
> index 6451d1d..d8d0fbb 100644
> --- a/board/raspberrypi/rpi/rpi.c
> +++ b/board/raspberrypi/rpi/rpi.c
> @@ -259,6 +259,72 @@ int misc_init_r(void)
>  #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
>         set_board_info();
>  #endif
> +
> +       /*
> +        * The RPi start.elf passes important system configuration
> +        * like memory sizes and LED GPIO assignments to the kernel
> +        * via kernel command line.
> +        *
> +        * Therefore we have to parse the passed ATAG or FDT to get the

s/have to/may/

> +        * commandline and pass it through to script-land via the env
> +        * variable "bootargs_orig" so it can be passed on.
> +        *
> +        * By default, start.elf assumes a non-DT capable kernel and
> +        * passes the commandline via ATAG; this requires u-boot to
> +        * load the FDT from /boot and pass it on. This works if no
> +        * overlays have been passed through, but once overlays are in
> +        * the mix, stuff gets complicated to do in u-boot.

Ideally, DT overlays would be either implemented in U-Boot, or deferred
until the kernel boots and user-space can load overlays. I suspect the
latter is more inline with the usage model expected by
upstream/mainline, although I haven't checked to see.

> +        *
> +        * To force start.elf to pass a processed, ready-to-go DT,
> +        * you have to use the mkknlimg tool on the u-boot image:
> +        * ./mkknlimg --dtok u-boot.bin /boot/u-boot.bin
> +        *
> +        * mkknlimg can be obtained from
> https://github.com/raspberrypi/tools/blob/master/mkimage/knlinfo
> +        *
> +        * User scripts can check for successful bootargs retrieval
> +        * in the env variable pi_bootmode, which is either fdt, atag
> +        * or unknown in case of an error.
> +        *
> +        * The location 0x100 is hard-coded in start.elf, and it is
> +        * the same as in the default bootscripts, so you only have
> +        * to omit the fatload command loading the raw FDT to get
> +        * going.

"omit the fatload command" from where?

Personally I've been using extlinux.conf on my Pi for a while, so there
is no "fatload" anywhere that I'm aware of.

> +        */
> +
> +       void* ptr = (char*) 0x100;
> +       struct tag_header* atag_ptr = ptr;
> +       setenv("pi_bootmode","unknown");
> +
> +       if(atag_ptr->tag != ATAG_CORE) {
> +               if(atag_ptr->size == be32_to_cpu(FDT_MAGIC)) {
> +                       set_working_fdt_addr((ulong) ptr);

Doesn't that set the address of the DT that U-Boot uses to configure
itself, not the DT that U-Boot will pass to the kernel? The two are
certainly separate concepts. This code should set $fdt_addr/$fdt_addr_r
if the DT is detected, so that scripts can affect whether this DT is used.

> +                       int nodeoffset = fdt_path_offset(working_fdt,
> "/chosen");
> +                       int len;
> +                       const void* nodep = fdt_getprop(working_fdt,
> nodeoffset, "bootargs", &len);
> +                       if(len==0) {
> +                               printf("WARNING: Could not determine
> bootargs from FDT!\n");
> +                       } else {
> +                               printf("Set bootargs_orig from FDT\n");

debug() seems more appropriate than printf(), except for errors.

> +                               setenv("bootargs_orig", (char*) nodep);
> +                               setenv("pi_bootmode","fdt");
> +                       }
> +               } else {
> +                       printf("Warning: start.elf did not pass ATAG
> or FDT parameters\n");
> +               }
> +       } else {
> +               while(atag_ptr->tag != ATAG_NONE) {
> +                       printf("at %p, have %x (len
> %x)\n",atag_ptr,atag_ptr->tag, atag_ptr->size);
> +                       if(atag_ptr->tag == ATAG_CMDLINE) {
> +                               char* old_cmdline = ptr + 8;
> +                               printf("Set bootargs_orig from ATAG\n");
> +                               setenv("bootargs_orig", old_cmdline);
> +                               setenv("pi_bootmode", "atag");
> +                       }
> +                       ptr = ptr + (atag_ptr->size * 4);
> +                       atag_ptr=ptr;
> +               }
> +       }
> +
>         return 0;
>  }




More information about the U-Boot mailing list