[U-Boot] [PATCH 1/1] efi_loader: use built-in device tree in bootefi command

The bootefi command has two parameters: the address of the executable and the address of the flattened device tree.
When executing the devicetree command in grub this command can only replace an existing device tree. So we always want to pass a device tree.
With the patch the device tree defaults to the internal one. But of cause the user still can supply his one via the second parameter.
One use case is booting via iPXE from an iSCSI drive. As we may be able to choose between different operating systems in the iPXE menu we cannot know the correct device tree when invoking bootefi. The dtb might not even be installed on a local device.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- cmd/bootefi.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 51213c0293..c7f2887df2 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -276,7 +276,7 @@ exit: return ret; }
-static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) +static int do_bootefi_bootmgr_exec(struct fdt_header *fdt_addr) { struct efi_device_path *device_path, *file_path; void *addr; @@ -310,10 +310,34 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) /* Interpreter command to boot an arbitrary EFI image from memory */ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *saddr, *sfdt; - unsigned long addr, fdt_addr = 0; + char *saddr; + unsigned long addr; + struct fdt_header *fdt_addr = NULL; efi_status_t r;
+ /* Set the device tree address */ + if (argc > 2) { + fdt_addr = (struct fdt_header *)simple_strtoul( + argv[2], NULL, 16); + } else { + /* If no device tree is supplied, try using the internal one */ + fdt_addr = (struct fdt_header *)gd->fdt_blob; + if (fdt_addr) + printf("Using built-in device tree\n"); + } + + /* Validate the device tree */ + if (fdt_addr) { + int err = fdt_check_header(fdt_addr); + + if (err < 0) { + printf("The device tree is not valid\n"); + debug("libfdt fdt_check_header(): %s\n", + fdt_strerror(err)); + return CMD_RET_FAILURE; + } + } + if (argc < 2) return CMD_RET_USAGE; #ifdef CONFIG_CMD_BOOTEFI_HELLO @@ -362,21 +386,11 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else #endif if (!strcmp(argv[1], "bootmgr")) { - unsigned long fdt_addr = 0; - - if (argc > 2) - fdt_addr = simple_strtoul(argv[2], NULL, 16); - return do_bootefi_bootmgr_exec(fdt_addr); } else { saddr = argv[1];
addr = simple_strtoul(saddr, NULL, 16); - - if (argc > 2) { - sfdt = argv[2]; - fdt_addr = simple_strtoul(sfdt, NULL, 16); - } }
printf("## Starting EFI application at %08lx ...\n", addr);

On 01/20/2018 01:56 PM, Heinrich Schuchardt wrote:
The bootefi command has two parameters: the address of the executable and the address of the flattened device tree.
When executing the devicetree command in grub this command can only replace an existing device tree. So we always want to pass a device tree.
With the patch the device tree defaults to the internal one. But of cause the user still can supply his one via the second parameter.
One use case is booting via iPXE from an iSCSI drive. As we may be able to choose between different operating systems in the iPXE menu we cannot know the correct device tree when invoking bootefi. The dtb might not even be installed on a local device.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
All of this logic is already implemented in the distro boot script, so if you load your iPXE EFI binary via dhcp boot, from a block device or something similar, it will by default already get $fdtcontroladdr passed in. I'm not sure I'm terribly happy to have additional magic in the bootefi command. If you want to spawn an EFI binary without device tree table, you should be able to do so IMHO.
How do you invoke iPXE?
Alex

On 01/22/2018 02:59 PM, Alexander Graf wrote:
On 01/20/2018 01:56 PM, Heinrich Schuchardt wrote:
The bootefi command has two parameters: the address of the executable and the address of the flattened device tree.
When executing the devicetree command in grub this command can only replace an existing device tree. So we always want to pass a device tree.
With the patch the device tree defaults to the internal one. But of cause the user still can supply his one via the second parameter.
One use case is booting via iPXE from an iSCSI drive. As we may be able to choose between different operating systems in the iPXE menu we cannot know the correct device tree when invoking bootefi. The dtb might not even be installed on a local device.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
All of this logic is already implemented in the distro boot script, so if you load your iPXE EFI binary via dhcp boot, from a block device or something similar, it will by default already get $fdtcontroladdr passed in. I'm not sure I'm terribly happy to have additional magic in the bootefi command. If you want to spawn an EFI binary without device tree table, you should be able to do so IMHO.
Booting via DHCP is most insecure. Neither the client nor the server are authenticated.
My understanding is that ftd address is not set by:
load mmc 0:1 0x13000000 snp.efi bootefi 0x13000000
Where would an fdtadress be determined without loading a dtb?
But giving it a further thought I have to better analyze why Grub fails to correctly execute 'devicetable' if no fdt has been passed to bootefi. Let's keep back the patch until the problem is properly understood.
Regards
Heinrich
How do you invoke iPXE?
Alex

On 22.01.18 19:43, Heinrich Schuchardt wrote:
On 01/22/2018 02:59 PM, Alexander Graf wrote:
On 01/20/2018 01:56 PM, Heinrich Schuchardt wrote:
The bootefi command has two parameters: the address of the executable and the address of the flattened device tree.
When executing the devicetree command in grub this command can only replace an existing device tree. So we always want to pass a device tree.
With the patch the device tree defaults to the internal one. But of cause the user still can supply his one via the second parameter.
One use case is booting via iPXE from an iSCSI drive. As we may be able to choose between different operating systems in the iPXE menu we cannot know the correct device tree when invoking bootefi. The dtb might not even be installed on a local device.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
All of this logic is already implemented in the distro boot script, so if you load your iPXE EFI binary via dhcp boot, from a block device or something similar, it will by default already get $fdtcontroladdr passed in. I'm not sure I'm terribly happy to have additional magic in the bootefi command. If you want to spawn an EFI binary without device tree table, you should be able to do so IMHO.
Booting via DHCP is most insecure. Neither the client nor the server are authenticated.
My understanding is that ftd address is not set by:
load mmc 0:1 0x13000000 snp.efi bootefi 0x13000000
Where would an fdtadress be determined without loading a dtb?
If you instead just use
bootefi 0x13000000 $fdtcontroladdr
you should be all set :)
Alex
participants (2)
-
Alexander Graf
-
Heinrich Schuchardt