diff mbox series

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

Message ID 20180120125619.11610-1-xypron.glpk@gmx.de
State Rejected, archived
Delegated to: Alexander Graf
Headers show
Series [U-Boot,1/1] efi_loader: use built-in device tree in bootefi command | expand

Commit Message

Heinrich Schuchardt Jan. 20, 2018, 12:56 p.m. UTC
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(-)

Comments

Alexander Graf Jan. 22, 2018, 1:59 p.m. UTC | #1
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
Heinrich Schuchardt Jan. 22, 2018, 6:43 p.m. UTC | #2
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
> 
>
Alexander Graf Jan. 22, 2018, 9:28 p.m. UTC | #3
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
diff mbox series

Patch

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);