efi: make efi and bootmgr more usable
v2 cover efi: make efi and bootmgr more usable
This patch set is a collection of patches to enhance efi user interfaces /commands. It will help improve user experience on efi boot and make it more usable *without* edk2's shell utility.
Let's see how it works:
=> efishell boot add 1 SHELL mmc 0:1 /Shell.efi "" => efishell boot add 2 HELLO mmc 0:1 /hello.efi "" => efishell boot dump
Boot0001:
attributes: A-- (0x00000001) label: SHELL file_path: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/HD(1,MBR,0x086246ba,0x800,0x40000)/\\Shell.efi data: Boot0002: attributes: A-- (0x00000001) label: HELLO file_path: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/HD(1,MBR,0x086246ba,0x800,0x40000)/\\hello.efi data:
=> efishell boot order 1 2
=> efishell boot order
1: Boot0001: SHELL
2: Boot0002: HELLO
=> run -e Boot0002 (or bootefi bootmgr - 2) ; '-' means no dtb specified
WARNING: booting without device tree
Booting: HELLO
## Starting EFI application at 000000007db8b040 ... Hello, world!
## Application terminated, r = 0
=> env set -e PlatformLang en ; important!
(or you can do "efishell setvar PlatformLang en")
=> env print -e
Boot0001: {boot,run}(blob)
00000000: 01 00 00 00 68 00 53 00 ....h.S.
00000010: 48 00 45 00 4c 00 4c 00 H.E.L.L.
00000020: 00 00 01 04 14 00 b9 73 .......s
00000030: 1d e6 84 a3 cc 4a ae ab .....J..
00000040: 82 e8 28 f3 62 8b 03 1a ..(.b...
00000050: 05 00 00 03 1a 05 00 00 ........
00000060: 04 01 2a 00 01 00 00 00 ..*.....
00000070: 00 08 00 00 00 00 00 00 ........
00000080: 00 00 04 00 00 00 00 00 ........
00000090: ba 46 62 08 00 00 00 00 .Fb.....
000000a0: 00 00 00 00 00 00 00 00 ........
000000b0: 01 01 04 04 1c 00 5c 00 ......\.
000000c0: 5c 00 53 00 68 00 65 00 \.S.h.e.
000000d0: 6c 00 6c 00 2e 00 65 00 l.l...e.
000000e0: 66 00 69 00 00 00 7f ff f.i....
000000f0: 04 00 00 ...
Boot0002: {boot,run}(blob)
00000000: 01 00 00 00 68 00 48 00 ....h.H.
00000010: 45 00 4c 00 4c 00 4f 00 E.L.L.O.
00000020: 00 00 01 04 14 00 b9 73 .......s
00000030: 1d e6 84 a3 cc 4a ae ab .....J..
00000040: 82 e8 28 f3 62 8b 03 1a ..(.b...
00000050: 05 00 00 03 1a 05 00 00 ........
00000060: 04 01 2a 00 01 00 00 00 ..*.....
00000070: 00 08 00 00 00 00 00 00 ........
00000080: 00 00 04 00 00 00 00 00 ........
00000090: ba 46 62 08 00 00 00 00 .Fb.....
000000a0: 00 00 00 00 00 00 00 00 ........
000000b0: 01 01 04 04 1c 00 5c 00 ......\.
000000c0: 5c 00 68 00 65 00 6c 00 \.h.e.l.
000000d0: 6c 00 6f 00 2e 00 65 00 l.o...e.
000000e0: 66 00 69 00 00 00 7f ff f.i....
000000f0: 04 00 00 ...BootOrder: {boot,run}(blob)
00000000: 01 00 02 00 ....
OsIndicationsSupported: {ro,boot}(blob) 00000000: 00 00 00 00 00 00 00 00 ........
PlatformLang: {boot,run}(blob)
00000000: 65 6e en
=> run -e Boot0001 or bootefi bootmgr
(shell ...)
"setvar" command now supports efi shell-like syntax:
=> env set -e foo =S\"akashi\" =0x012345 =Habcdef => env print -e foo
foo: {boot,run}(blob)
00000000: 61 6b 61 73 68 69 45 23 akashiE# 00000010: 01 00 ab cd ef .....
Other useful sub commands are:
=> efishell devices ; print uefi devices
=> efishell drivers ; print uefi drivers
=> efishell images ; print loaded images
=> efishell dh ; print uefi handles
=> efishell memmap ; dump uefi memory map
# I admit there is some room to improve the output from those commands.
Enjoy!
-Takahiro Akashi
Changes in v2 (Nov 5, 2018)
* modify efi_dp_from_name() for use in efishell
* rename efi_marshal_load_option() to efi_serialize_load_option(), taking a "struct efi_load_option" as an argument
* improve a format in dumping uefi variables
* enhance a setvar syntax as efi's shell does
* change a syntax from "bootefi bootmgr -2" to "bootefi bootmgr - 2"
* add -e option to run command
* add -e option to env command
* add more sub-commands
AKASHI Takahiro (14):
efi_loader: allow device == NULL in efi_dp_from_name()
efi_loader: bootmgr: add load option helper functions
efi_loader: bootmgr: allow for running a given load option
cmd: add efishell command
cmd: efishell: add devices command
cmd: efishell: add drivers command
cmd: efishell: add images command
cmd: efishell: add memmap command
cmd: efishell: add dh command
cmd: bootefi: carve out fdt parameter handling
cmd: bootefi: run an EFI application of a specific load option
cmd: run: add "-e" option to run an EFI application
cmd: efishell: export uefi variable helper functions
cmd: env: add "-e" option for handling UEFI variables
cmd/Makefile | 2 +- cmd/bootefi.c | 71 ++- cmd/efishell.c | 970 +++++++++++++++++++++++++++++++ cmd/efishell.h | 6 + cmd/nvedit.c | 63 +- common/cli.c | 30 + include/command.h | 5 + include/efi_loader.h | 26 +- lib/efi_loader/efi_bootmgr.c | 101 ++-- lib/efi_loader/efi_device_path.c | 11 +- 10 files changed, 1223 insertions(+), 62 deletions(-) create mode 100644 cmd/efishell.c create mode 100644 cmd/efishell.h
Signature · 1 line
2.19.0
PATCH v2 1/14 efi_loader: allow device == NULL in efi_dp_from_name()
This is a preparatory patch for use in efi_serialize_load_option() as a load option's file_path should have both a device path and a file path.
--- lib/efi_loader/efi_device_path.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
lib/efi_loader/efi_device_path.c +7 -4
@@ -955,7 +955,7 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,char filename[32 ] = {0 };/* dp->str is u16[32] long */ char *s; -if (!device || (path && !file)) +if (path && !file)return EFI_INVALID_PARAMETER ; is_net = !strcmp (dev,"Net" );
@@ -965,10 +965,12 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,if (part <0 )return EFI_INVALID_PARAMETER ; - *device =efi_dp_from_part (desc, part); +if (device) + *device =efi_dp_from_part (desc, part); }else {#ifdef CONFIG_NET - *device =efi_dp_from_eth (); +if (device) + *device =efi_dp_from_eth ();#endif }
@@ -985,7 +987,8 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, s = filename;while ((s =strchr (s,'/' ))) *s++ ='\\' ; - *file =efi_dp_from_file (NULL ,0 , filename); + *file =efi_dp_from_file (((!is_net && device) ? desc :NULL ), + part, filename);return EFI_SUCCESS ; }
Signature · 1 line
2.19.0
PATCH v2 2/14 efi_loader: bootmgr: add load option helper functions
In reply to AKASHI TakahiroIn this patch, helper functions for an load option variable (BootXXXX) are added:
* efi_deserialize_load_option(): parse a string into load_option data (renamed from parse_load_option and exported)
* efi_serialize_load_option(): convert load_option data into a string
Those functions will be used to implement efishell command.
--- include/efi_loader.h | 23 +++++++++ lib/efi_loader/efi_bootmgr.c | 93 +++++++++++++++++++++++------------- 2 files changed, 83 insertions(+), 33 deletions(-)
include/efi_loader.h +23 -0
@@ -517,6 +517,29 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor, u32 attributes, efi_uintn_t data_size, void *data); +/* +* See section 3.1.3 in the v2.7 UEFI spec for more details on +* the layout of EFI_LOAD_OPTION. In short it is: +* +* typedef struct _EFI_LOAD_OPTION { +* UINT32 Attributes; +* UINT16 FilePathListLength; +* // CHAR16 Description[]; <-- variable length, NULL terminated +* // EFI_DEVICE_PATH_PROTOCOL FilePathList[]; +* <-- FilePathListLength bytes +* // UINT8 OptionalData[]; +* } EFI_LOAD_OPTION; +*/ +struct efi_load_option { +u32 attributes; +u16 file_path_length; +u16 *label; +struct efi_device_path *file_path; +u8 *optional_data; +}; + +void efi_deserialize_load_option (struct efi_load_option *lo,u8 *data); +unsigned long efi_serialize_load_option (struct efi_load_option *lo,u8 **data);void *efi_bootmgr_load (struct efi_device_path **device_path,struct efi_device_path **file_path);
lib/efi_loader/efi_bootmgr.c +60 -33
122 lines not on this page · raw message
Signature · 1 line
2.19.0
PATCH v2 3/14 efi_loader: bootmgr: allow for running a given load option
In reply to AKASHI TakahiroWith an extra argument, efi_bootmgr_load() can now load an efi binary based on a "BootXXXX" variable specified.
--- include/efi_loader.h | 3 ++- lib/efi_loader/efi_bootmgr.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-)
include/efi_loader.h +2 -1
@@ -540,7 +540,8 @@ struct efi_load_option {void efi_deserialize_load_option (struct efi_load_option *lo,u8 *data);unsigned long efi_serialize_load_option (struct efi_load_option *lo,u8 **data); -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path);#else /* CONFIG_IS_ENABLED(EFI_LOADER) */
lib/efi_loader/efi_bootmgr.c +7 -1
@@ -170,7 +170,8 @@ error:* available load-options, finding and returning the first one that can * be loaded successfully. */ -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path) {uint16_t *bootorder;
@@ -183,6 +184,11 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, bs = systab.boottime; rs = systab.runtime; +if (boot_id !=-1 ) { + image =try_load_entry (boot_id, device_path, file_path); + goto error; + } + bootorder =get_var (L"BootOrder" , &efi_global_variable_guid, &size);if (!bootorder) goto error;
Signature · 1 line
2.19.0
PATCH v2 3/14 efi_loader: bootmgr: allow for running a given load option
Quoted 4 lines · AKASHI Takahiro
With an extra argument,
efi_bootmgr_load()can now load an efi binary based on a "BootXXXX" variable specified.Signed-off-by AKASHI Takahiro <[email protected]>
I don't see you changing the caller, so this hunk won't compile on its own?
Please make sure that every single step in your patch set compiles.
Quoted 34 lines
--- include/efi_loader.h | 3 ++- lib/efi_loader/efi_bootmgr.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-)include/efi_loader.h +2
-1@@ -540,7 +540,8 @@ struct efi_load_option {void efi_deserialize_load_option (struct efi_load_option *lo,u8 *data);unsigned long efi_serialize_load_option (struct efi_load_option *lo,u8 **data); -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path);#else /* CONFIG_IS_ENABLED(EFI_LOADER) */ lib/efi_loader/efi_bootmgr.c +2
-1@@ -170,7 +170,8 @@ error:* available load-options, finding and returning the first one that can * be loaded successfully. */ -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path) {uint16_t *bootorder;
lib/efi_loader/efi_bootmgr.c void *efi_bootmgr_load(struct efi_device_path **device_path, · line 189
Quoted 6 lines
lib/efi_loader/efi_bootmgr.c +3
-0@@ -183,6 +184,11 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, bs = systab.boottime; rs = systab.runtime; +if (boot_id !=-1 ) { + image =try_load_entry (boot_id, device_path, file_path); + goto error;
I think at this point it might be better to split the function, no? You're not actually reusing any code from efi_bootmgr_load with the 2 instantiation types (explicit boot id, loop through boot order).
Alex
Quoted 6 lines
lib/efi_loader/efi_bootmgr.c +2
-0+ } + bootorder =get_var (L"BootOrder" , &efi_global_variable_guid, &size);if (!bootorder) goto error;
PATCH v2 3/14 efi_loader: bootmgr: allow for running a given load option
Quoted 9 lines · Alexander Graf
Quoted 4 lines · AKASHI Takahiro
With an extra argument,
efi_bootmgr_load()can now load an efi binary based on a "BootXXXX" variable specified.Signed-off-by AKASHI Takahiro <[email protected]>I don't see you changing the caller, so this hunk won't compile on its own?
You're correct.
Quoted 1 line
Please make sure that every single step in your patch set compiles.
I will try to double-check in the future.
Quoted 37 lines
Quoted 37 lines
--- include/efi_loader.h | 3 ++- lib/efi_loader/efi_bootmgr.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-)include/efi_loader.h +2
-1@@ -540,7 +540,8 @@ struct efi_load_option {void efi_deserialize_load_option (struct efi_load_option *lo,u8 *data);unsigned long efi_serialize_load_option (struct efi_load_option *lo,u8 **data); -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path);#else /* CONFIG_IS_ENABLED(EFI_LOADER) */ lib/efi_loader/efi_bootmgr.c +2
-1@@ -170,7 +170,8 @@ error:* available load-options, finding and returning the first one that can * be loaded successfully. */ -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path) {uint16_t *bootorder;@@ -183,6 +184,11 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, bs = systab.boottime; rs = systab.runtime;
Quoted 5 lines
lib/efi_loader/efi_bootmgr.c void *efi_bootmgr_load(struct efi_device_path **device_path, · line 189
Quoted 3 lines
lib/efi_loader/efi_bootmgr.c +3
-0+if (boot_id !=-1 ) { + image =try_load_entry (boot_id, device_path, file_path); + goto error;I think at this point it might be better to split the function, no?
It's one way to fix, but I want simply to fix the issue by modifying the caller, do_bootefi_bootmgr_exec() because
Quoted 2 lines
You're not actually reusing any code from
efi_bootmgr_loadwith the 2 instantiation types (explicit boot id, loop through boot order).
I will add "BootNext" support to efi_bootmgr_load() so that it will be a single point of loading. See my relevant patch:
https://lists.denx.de/pipermail/u-boot/2018-November/349281.html
Thanks,
-Takahiro Akashi
Quoted 9 lines
Alex
Quoted 6 lines
lib/efi_loader/efi_bootmgr.c +2
-0+ } + bootorder =get_var (L"BootOrder" , &efi_global_variable_guid, &size);if (!bootorder) goto error;
PATCH v2 3/14 efi_loader: bootmgr: allow for running a given load option
Quoted 63 lines · AKASHI Takahiro
Quoted 9 lines · Alexander Graf
Quoted 4 lines · AKASHI Takahiro
With an extra argument,
efi_bootmgr_load()can now load an efi binary based on a "BootXXXX" variable specified.Signed-off-by AKASHI Takahiro <[email protected]>I don't see you changing the caller, so this hunk won't compile on its own?
You're correct.
Quoted 1 line
Please make sure that every single step in your patch set compiles.
I will try to double-check in the future.
Quoted 37 lines
Quoted 37 lines
--- include/efi_loader.h | 3 ++- lib/efi_loader/efi_bootmgr.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-)include/efi_loader.h +2
-1@@ -540,7 +540,8 @@ struct efi_load_option {void efi_deserialize_load_option (struct efi_load_option *lo,u8 *data);unsigned long efi_serialize_load_option (struct efi_load_option *lo,u8 **data); -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path);#else /* CONFIG_IS_ENABLED(EFI_LOADER) */ lib/efi_loader/efi_bootmgr.c +2
-1@@ -170,7 +170,8 @@ error:* available load-options, finding and returning the first one that can * be loaded successfully. */ -void *efi_bootmgr_load (struct efi_device_path **device_path, +void *efi_bootmgr_load (int boot_id, +struct efi_device_path **device_path,struct efi_device_path **file_path) {uint16_t *bootorder;@@ -183,6 +184,11 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, bs = systab.boottime; rs = systab.runtime;Quoted 5 lines
lib/efi_loader/efi_bootmgr.c void *efi_bootmgr_load(struct efi_device_path **device_path, · line 189
Quoted 3 lines
lib/efi_loader/efi_bootmgr.c +3
-0+if (boot_id !=-1 ) { + image =try_load_entry (boot_id, device_path, file_path); + goto error;I think at this point it might be better to split the function, no?
It's one way to fix, but I want simply to fix the issue by modifying the caller,
do_bootefi_bootmgr_exec()because
Quoted 6 lines
Quoted 2 lines
You're not actually reusing any code from
efi_bootmgr_loadwith the 2 instantiation types (explicit boot id, loop through boot order).I will add "BootNext" support to
efi_bootmgr_load()so that it will be a single point of loading. See my relevant patch:
https://lists.denx.de/pipermail/u-boot/2018-November/349281.html
I don't fully understand. I would expect BootNext to only take effect when *not* booting an explicit ID? So that would fit quite nicely into a function based split.
Alex
PATCH v2 4/14 cmd: add efishell command
In reply to AKASHI TakahiroCurrently, there is no easy way to add or modify UEFI variables. In particular, bootmgr supports BootOrder/BootXXXX variables, it is quite hard to define them as u-boot variables because they are represented in a complicated and encoded format.
The new command, efishell, helps address these issues and give us more friendly interfaces:
* efishell boot add: add BootXXXX variable
* efishell boot rm: remove BootXXXX variable
* efishell boot dump: display all BootXXXX variables
* efishell boot order: set/display a boot order (BootOrder)
* efishell setvar: set an UEFI variable (with limited functionality)
* efishell dumpvar: display all UEFI variables
As the name suggests, this command basically provides a subset fo UEFI shell commands with simplified functionality.
--- cmd/Makefile | 2 +- cmd/efishell.c | 673 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/efishell.h | 5 + 3 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 cmd/efishell.c create mode 100644 cmd/efishell.h
cmd/Makefile +1 -1
@@ -24,7 +24,7 @@ obj-$(CONFIG_CMD_BINOP) += binop.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o -obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o +obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o efishell.o obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o obj-$(CONFIG_CMD_BOOTZ) += bootz.o
cmd/efishell.c new file +673 -0
673 lines not on this page · raw message
cmd/efishell.h new file +5 -0
@@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <efi.h> + +efi_status_t efi_init_obj_list (void );
Signature · 1 line
2.19.0
PATCH v2 4/14 cmd: add efishell command
Quoted 31 lines · AKASHI Takahiro
Currently, there is no easy way to add or modify UEFI variables. In particular, bootmgr supports BootOrder/BootXXXX variables, it is quite hard to define them as u-boot variables because they are represented in a complicated and encoded format.
The new command, efishell, helps address these issues and give us more friendly interfaces:
* efishell boot add: add BootXXXX variable
* efishell boot rm: remove BootXXXX variable
* efishell boot dump: display all BootXXXX variables
* efishell boot order: set/display a boot order (BootOrder)
* efishell setvar: set an UEFI variable (with limited functionality)
* efishell dumpvar: display all UEFI variablesAs the name suggests, this command basically provides a subset fo UEFI shell commands with simplified functionality.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/Makefile | 2 +- cmd/efishell.c | 673 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/efishell.h | 5 + 3 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 cmd/efishell.c create mode 100644 cmd/efishell.hcmd/Makefile +0
-0
cmd/Makefile obj-$(CONFIG_CMD_BINOP) += binop.o · line 27
Quoted 5 lines
cmd/Makefile +1
-1@@ -24,7 +24,7 @@ obj-$(CONFIG_CMD_BINOP) += binop.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o -obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o +obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o efishell.o
Please create a separate command line option for efishell and make it disabled by default.
I think it's a really really useful debugging aid, but in a normal environment people should only need to run efi binaries (plus bootmgr) and modify efi variables, no?
Quoted 21 lines
cmd/Makefile +0
-0obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o obj-$(CONFIG_CMD_BOOTZ) += bootz.ocmd/efishell.c new file +12
-0@@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* EFI Shell-like command +* +* Copyright (c) 2018 AKASHI Takahiro, Linaro Limited +*/ + +#include <charset.h> +#include <common.h> +#include <command.h> +#include <efi_loader.h> +#include <environment.h>
cmd/efishell.c line 22
Quoted 10 lines
cmd/efishell.c new file +10
-0+#include <errno.h> +#include <exports.h> +#include <hexdump.h> +#include <malloc.h> +#include <search.h> +#include <linux/ctype.h> +#include <asm/global_data.h> +#include "efishell.h" + +DECLARE_GLOBAL_DATA_PTR ;
Where in this file do you need gd?
Quoted 303 lines
cmd/efishell.c new file +303
-0+ +static void dump_var_data (char *data,unsigned long len) +{ +char *start, *end, *p; +unsigned long pos, count; +char hex[3 ], line[9 ]; +int i; + + end = data + len; +for (start = data, pos =0 ; start < end; start += count, pos += count) { + count = end - start; +if (count >16 ) + count =16 ; + +/* count should be multiple of two */ +printf ("%08lx: " , pos); + +/* in hex format */ + p = start; +for (i =0 ; i < count /2 ; p +=2 , i++) +printf (" %c%c" , *p, *(p +1 )); +for (; i <8 ; i++) +printf (" " ); + +/* in character format */ + p = start; + hex[2 ] ='\0' ; +for (i =0 ; i < count /2 ; i++) { + hex[0 ] = *p++; + hex[1 ] = *p++; + line[i] =simple_strtoul (hex,0 ,16 ); +if (line[i] <0x20 || line[i] >0x7f ) + line[i] ='.' ; + } + line[i] ='\0' ; +printf (" %s\n" , line); + } +} + +/* +* From efi_variable.c, +* +* Mapping between EFI variables and u-boot variables: +* +* efi_$guid_$varname = {attributes}(type)value +*/ +static int do_efi_dump_var (int argc,char *const argv[]) +{ +char regex[256 ]; +char *const regexlist[] = {regex}; +char *res =NULL , *start, *end; +int len; + +if (argc >2 ) +return CMD_RET_USAGE ; + +if (argc ==2 ) +snprintf (regex,256 ,"efi_.*-.*-.*-.*-.*_%s" , argv[1 ]); +else +snprintf (regex,256 ,"efi_.*-.*-.*-.*-.*_.*" ); +debug ("%s:%d grep uefi var %s\n" , __func__, __LINE__, regex); + + len =hexport_r (&env_htab,'\n' ,H_MATCH_REGEX |H_MATCH_KEY , + &res,0 ,1 , regexlist); + +if (len <0 ) +return CMD_RET_FAILURE ; + +if (len >0 ) { + end = res; +while (true) { +/* variable name */ + start =strchr (end,'_' ); +if (!start) +break ; + start =strchr (++start,'_' ); +if (!start) +break ; + end =strchr (++start,'=' ); +if (!end) +break ; +printf ("%.*s:" , (int )(end - start), start); + end++; + +/* value */ + start = end; + end =strstr (start,"(blob)" ); +if (!end) { +putc ('\n' ); +break ; + } + end +=6 ; +printf (" %.*s\n" , (int )(end - start), start); + + start = end; + end =strchr (start,'\n' ); +if (!end) +break ; +dump_var_data (start, end - start); + } +free (res); + +if (len <2 && argc ==2 ) +printf ("%s: not found\n" , argv[1 ]); + } + +return CMD_RET_SUCCESS ; +} + +static int append_value (char **bufp,unsigned long *sizep,char *data) +{ +char *tmp_buf =NULL , *new_buf =NULL , *value; +unsigned long len =0 ; + +if (!strncmp (data,"=0x" ,2 )) {/* hexadecimal number */ +union { +u8 u8; +u16 u16; +u32 u32; +u64 u64; + } tmp_data; +unsigned long hex_value; +void *hex_ptr; + + data +=3 ; + len =strlen (data); +if ((len &0x1 ))/* not multiple of two */ +return -1 ; + + len /=2 ; +if (len >8 ) +return -1 ; +else if (len >4 ) + len =8 ; +else if (len >2 ) + len =4 ; + +/* convert hex hexadecimal number */ +if (strict_strtoul (data,16 , &hex_value) <0 ) +return -1 ; + + tmp_buf =malloc (len); +if (!tmp_buf) +return -1 ; + +if (len ==1 ) { + tmp_data.u8 = hex_value; + hex_ptr = &tmp_data.u8; + }else if (len ==2 ) { + tmp_data.u16 = hex_value; + hex_ptr = &tmp_data.u16; + }else if (len ==4 ) { + tmp_data.u32 = hex_value; + hex_ptr = &tmp_data.u32; + }else { + tmp_data.u64 = hex_value; + hex_ptr = &tmp_data.u64; + } +memcpy (tmp_buf, hex_ptr, len); + value = tmp_buf; + + }else if (!strncmp (data,"=H" ,2 )) {/* hexadecimal-byte array */ + data +=2 ; + len =strlen (data); +if (len &0x1 )/* not multiple of two */ +return -1 ; + + len /=2 ; + tmp_buf =malloc (len); +if (!tmp_buf) +return -1 ; + +if (hex2bin ((u8 *)tmp_buf, data, len) <0 ) +return -1 ; + + value = tmp_buf; + }else {/* string */ +if (!strncmp (data,"=\"" ,2 ) || !strncmp (data,"=S\"" ,3 )) { +if (data[1 ] =='"' ) + data +=2 ; +else + data +=3 ; + value = data; + len =strlen (data) -1 ; +if (data[len] !='"' ) +return -1 ; + }else { + value = data; + len =strlen (data); + } + } + + new_buf =realloc (*bufp, *sizep + len); +if (!new_buf) + goto out; + +memcpy (new_buf + *sizep, value, len); + *bufp = new_buf; + *sizep += len; + +out: +free (tmp_buf); + +return 0 ; +} + +static int do_efi_set_var (int argc,char *const argv[]) +{ +char *var_name, *value =NULL ; +unsigned long size =0 ; +u16 *var_name16, *p; +efi_guid_t guid; +efi_status_t ret; + +if (argc ==1 ) +return CMD_RET_SUCCESS ; + + var_name = argv[1 ]; +if (argc ==2 ) { +/* remove */ + value =NULL ; + size =0 ; + }else {/* set */ + argc -=2 ; + argv +=2 ; + +for ( ; argc >0 ; argc--, argv++) +if (append_value (&value, &size, argv[0 ]) <0 ) { + ret =CMD_RET_FAILURE ; + goto out; + } + } + + var_name16 =malloc ((strlen (var_name) +1 ) *2 ); + p = var_name16; +utf8_utf16_strncpy (&p, var_name,strlen (var_name) +1 ); + + guid = efi_global_variable_guid; + ret =efi_set_variable (var_name16, &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS , size, value); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +return ret; +} + +static int do_efi_boot_add (int argc,char *const argv[]) +{ +int id; +char *endp; +char var_name[9 ]; +u16 var_name16[9 ], *p; +efi_guid_t guid; +size_t label_len, label_len16; +u16 *label; +struct efi_device_path *device_path =NULL , *file_path =NULL ; +struct efi_load_option lo; +void *data =NULL ; +unsigned long size; +int ret; + +if (argc <6 || argc >7 ) +return CMD_RET_USAGE ; + + id = (int )simple_strtoul (argv[1 ], &endp,0 ); +if (*endp !='\0' || id >0xffff ) +return CMD_RET_FAILURE ; + +sprintf (var_name,"Boot%04X" , id); + p = var_name16; +utf8_utf16_strncpy (&p, var_name,9 ); + + guid = efi_global_variable_guid; + +/* attributes */ + lo.attributes =0x1 ;/* always ACTIVE */ + +/* label */ + label_len =strlen (argv[2 ]); + label_len16 =utf8_utf16_strnlen (argv[2 ], label_len); + label =malloc ((label_len16 +1 ) *sizeof (u16)); +if (!label) +return CMD_RET_FAILURE ; + lo.label = label;/* label will be changed below */ +utf8_utf16_strncpy (&label, argv[2 ], label_len); + +/* file path */ + ret =efi_dp_from_name (argv[3 ], argv[4 ], argv[5 ], &device_path, + &file_path); +if (ret !=EFI_SUCCESS ) { + ret =CMD_RET_FAILURE ; + goto out; + } + lo.file_path = file_path; + lo.file_path_length =efi_dp_size (file_path) + +sizeof (struct efi_device_path );/* for END */ + +/* optional data */ + lo.optional_data = (u8 *)(argc ==6 ?"" : argv[6 ]); + + size =efi_serialize_load_option (&lo, (u8 **)&data); +if (!size) { + ret =CMD_RET_FAILURE ;
cmd/efishell.c line 335
Quoted 10 lines
cmd/efishell.c new file +10
-0+ goto out; + } + + ret =efi_set_variable (var_name16, &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS , size, data); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +free (data); +#if 0 /* FIXME */
Eh, what? :)
Quoted 92 lines
cmd/efishell.c new file +92
-0+free (device_path); +free (file_path); +#endif +free (lo.label); +return ret; +} + +static int do_efi_boot_rm (int argc,char *const argv[]) +{ +efi_guid_t guid; +int id, i; +char *endp; +char var_name[9 ]; +u16 var_name16[9 ]; +efi_status_t ret; + +if (argc ==1 ) +return CMD_RET_USAGE ; + + guid = efi_global_variable_guid; +for (i =1 ; i < argc; i++, argv++) { + id = (int )simple_strtoul (argv[1 ], &endp,0 ); +if (*endp !='\0' || id >0xffff ) +return CMD_RET_FAILURE ; + +sprintf (var_name,"Boot%04X" , id); +utf8_utf16_strncpy ((u16 **)&var_name16, var_name,9 ); + + ret =efi_set_variable (var_name16, &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS ,0 ,NULL ); +if (ret) { +printf ("cannot remove Boot%04X" , id); +return CMD_RET_FAILURE ; + } + } + +return CMD_RET_SUCCESS ; +} + +static void show_efi_boot_opt_data (int id,void *data) +{ +struct efi_load_option lo; +char *label, *p; +size_t label_len16, label_len; +u16 *dp_str; + +efi_deserialize_load_option (&lo, data); + + label_len16 =u16_strlen (lo.label); + label_len =utf16_utf8_strnlen (lo.label, label_len16); + label =malloc (label_len +1 ); +if (!label) +return ; + p = label; +utf16_utf8_strncpy (&p, lo.label, label_len16); + +printf ("Boot%04X:\n" , id); +printf ("\tattributes: %c%c%c (0x%08x)\n" , +/* ACTIVE */ + lo.attributes &0x1 ?'A' :'-' , +/* FORCE RECONNECT */ + lo.attributes &0x2 ?'R' :'-' , +/* HIDDEN */ + lo.attributes &0x8 ?'H' :'-' , + lo.attributes); +printf ("\tlabel: %s\n" , label); + + dp_str =efi_dp_str (lo.file_path); +printf ("\tfile_path: %ls\n" , dp_str); +efi_free_pool (dp_str); + +printf ("\tdata: %s\n" , lo.optional_data); + +free (label); +} + +static void show_efi_boot_opt (int id) +{ +char var_name[9 ]; +u16 var_name16[9 ], *p; +efi_guid_t guid; +void *data =NULL ; +unsigned long size; +int ret; + +sprintf (var_name,"Boot%04X" , id); + p = var_name16; +utf8_utf16_strncpy (&p, var_name,9 ); + guid = efi_global_variable_guid; + + size =0 ;
cmd/efishell.c line 437
Quoted 10 lines
cmd/efishell.c new file +10
-0+ ret =efi_get_variable (var_name16, &guid,NULL , &size,NULL ); +if (ret == (int )EFI_BUFFER_TOO_SMALL ) { + data =malloc (size); + ret =efi_get_variable (var_name16, &guid,NULL , &size, data); + } +if (ret ==EFI_SUCCESS ) { +show_efi_boot_opt_data (id, data); +free (data); + }else if (ret ==EFI_NOT_FOUND ) { +printf ("Boot%04X: not found\n" , id);
Missing free?
Quoted 54 lines
cmd/efishell.c new file +54
-0+ } +} + +static int do_efi_boot_dump (int argc,char *const argv[]) +{ +char regex[256 ]; +char *const regexlist[] = {regex}; +char *variables =NULL , *boot, *value; +int len; +int id; + +if (argc >1 ) +return CMD_RET_USAGE ; + +snprintf (regex,256 ,"efi_.*-.*-.*-.*-.*_Boot[0-9A-F]+" ); + + len =hexport_r (&env_htab,'\n' ,H_MATCH_REGEX |H_MATCH_KEY , + &variables,0 ,1 , regexlist); + +if (!len) +return CMD_RET_SUCCESS ; + +if (len <0 ) +return CMD_RET_FAILURE ; + + boot = variables; +while (*boot) { + value =strstr (boot,"Boot" ) +4 ; + id = (int )simple_strtoul (value,NULL ,16 ); +show_efi_boot_opt (id); + boot =strchr (boot,'\n' ); +if (!*boot) +break ; + boot++; + } +free (variables); + +return CMD_RET_SUCCESS ; +} + +static int show_efi_boot_order (void ) +{ +efi_guid_t guid; +u16 *bootorder =NULL ; +unsigned long size; +int num, i; +char var_name[9 ]; +u16 var_name16[9 ], *p16; +void *data; +struct efi_load_option lo; +char *label, *p; +size_t label_len16, label_len; +efi_status_t ret =CMD_RET_SUCCESS ; +
cmd/efishell.c line 501
Quoted 10 lines
cmd/efishell.c new file +10
-0+ guid = efi_global_variable_guid; + size =0 ; + ret =efi_get_variable (L"BootOrder" , &guid,NULL , &size,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + bootorder =malloc (size); + ret =efi_get_variable (L"BootOrder" , &guid,NULL , &size, + bootorder); + } +if (ret !=EFI_SUCCESS ) { +printf ("BootOrder not defined\n" );
Missing free(bootorder)
Quoted 17 lines
cmd/efishell.c new file +17
-0+return CMD_RET_SUCCESS ; + } + + num = size /sizeof (u16); +for (i =0 ; i < num; i++) { +sprintf (var_name,"Boot%04X" , bootorder[i]); + p16 = var_name16; +utf8_utf16_strncpy (&p16, var_name,9 ); + + size =0 ; + ret =efi_get_variable (var_name16, &guid,NULL , &size,NULL ); +if (ret !=EFI_BUFFER_TOO_SMALL ) { +printf ("%2d: Boot%04X: (not defined)\n" , + i +1 , bootorder[i]); +continue ; + } +
cmd/efishell.c line 528
Quoted 10 lines
cmd/efishell.c new file +10
-0+ data =malloc (size); +if (!data) { + ret =CMD_RET_FAILURE ; + goto out; + } + ret =efi_get_variable (var_name16, &guid,NULL , &size, data); +if (ret !=EFI_SUCCESS ) { +free (data); + ret =CMD_RET_FAILURE ; + goto out;
Probably better to free(data) at out:, no?
Quoted 151 lines
cmd/efishell.c new file +145
-0+ } + +efi_deserialize_load_option (&lo, data); + + label_len16 =u16_strlen (lo.label); + label_len =utf16_utf8_strnlen (lo.label, label_len16); + label =malloc (label_len +1 ); +if (!label) { +free (data); + ret =CMD_RET_FAILURE ; + goto out; + } + p = label; +utf16_utf8_strncpy (&p, lo.label, label_len16); +printf ("%2d: Boot%04X: %s\n" , i +1 , bootorder[i], label); +free (label); + +free (data); + } +out: +free (bootorder); + +return ret; +} + +static int do_efi_boot_order (int argc,char *const argv[]) +{ +u16 *bootorder =NULL ; +unsigned long size; +int id, i; +char *endp; +efi_guid_t guid; +efi_status_t ret; + +if (argc ==1 ) +return show_efi_boot_order (); + + argc--; + argv++; + + size = argc *sizeof (u16); + bootorder =malloc (size); +if (!bootorder) +return CMD_RET_FAILURE ; + +for (i =0 ; i < argc; i++) { + id = (int )simple_strtoul (argv[i], &endp,0 ); +if (*endp !='\0' || id >0xffff ) { +printf ("invalid value: %s\n" , argv[i]); + ret =CMD_RET_FAILURE ; + goto out; + } + + bootorder[i] = (u16 )id; + } + + guid = efi_global_variable_guid; + ret =efi_set_variable (L"BootOrder" , &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS , size, bootorder); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +free (bootorder); + +return ret; +} + +static int do_efi_boot_opt (int argc,char *const argv[]) +{ +char *sub_command; + +if (argc <2 ) +return CMD_RET_USAGE ; + + argc--; argv++; + sub_command = argv[0 ]; + +if (!strcmp (sub_command,"add" )) +return do_efi_boot_add (argc, argv); +else if (!strcmp (sub_command,"rm" )) +return do_efi_boot_rm (argc, argv); +else if (!strcmp (sub_command,"dump" )) +return do_efi_boot_dump (argc, argv); +else if (!strcmp (sub_command,"order" )) +return do_efi_boot_order (argc, argv); +else +return CMD_RET_USAGE ; +} + +/* Interpreter command to configure EFI environment */ +static int do_efishell (cmd_tbl_t *cmdtp,int flag, +int argc,char *const argv[]) +{ +char *command; +efi_status_t r; + +if (argc <2 ) +return CMD_RET_USAGE ; + + argc--; argv++; + command = argv[0 ]; + +/* Initialize EFI drivers */ + r =efi_init_obj_list (); +if (r !=EFI_SUCCESS ) { +printf ("Error: Cannot set up EFI drivers, r = %lu\n" , + r & ~EFI_ERROR_MASK ); +return CMD_RET_FAILURE ; + } + +if (!strcmp (command,"boot" )) +return do_efi_boot_opt (argc, argv); +else if (!strcmp (command,"dumpvar" ) || !strcmp (command,"dmpstore" )) +return do_efi_dump_var (argc, argv); +else if (!strcmp (command,"setvar" )) +return do_efi_set_var (argc, argv); +else +return CMD_RET_USAGE ; +} + +#ifdef CONFIG_SYS_LONGHELP +static char efishell_help_text[] = +" - EFI Shell-like interface to configure EFI environment\n" +"\n" +"efishell boot add <bootid> <label> <interface> <device>[:<part>] <file path> <option>\n" +" - set uefi's BOOT variable\n" +"efishell boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n" +" - set/display uefi boot order\n" +"efishell boot dump\n" +" - display all uefi's BOOT variables\n" +"efishell boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n" +" - set/display uefi boot order\n" +"\n" +"efishell dumpvar [<name>]\n" +" - get uefi variable's value\n" +"efishell setvar <name> [<value>]\n" +" - set/delete uefi variable's value\n" +" <value> may be \"=\"...\"\", \"=0x...\" (set) or \"=\" (delete)\n" ; +#endif + +U_BOOT_CMD ( + efishell,10 ,0 , do_efishell, +"Configure EFI environment" , + efishell_help_text +);cmd/efishell.h new file +0
-0
cmd/efishell.h line 5
Quoted 5 lines
cmd/efishell.h new file +5
-0@@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <efi.h> + +efi_status_t efi_init_obj_list (void );
Why isn't this in efi_loader.h? That's the subsystem that exports it, no?
Alex
PATCH v2 4/14 cmd: add efishell command
Quoted 29 lines · Alexander Graf
Quoted 26 lines · AKASHI Takahiro
Currently, there is no easy way to add or modify UEFI variables. In particular, bootmgr supports BootOrder/BootXXXX variables, it is quite hard to define them as u-boot variables because they are represented in a complicated and encoded format.
The new command, efishell, helps address these issues and give us more friendly interfaces:
* efishell boot add: add BootXXXX variable
* efishell boot rm: remove BootXXXX variable
* efishell boot dump: display all BootXXXX variables
* efishell boot order: set/display a boot order (BootOrder)
* efishell setvar: set an UEFI variable (with limited functionality)
* efishell dumpvar: display all UEFI variablesAs the name suggests, this command basically provides a subset fo UEFI shell commands with simplified functionality.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/Makefile | 2 +- cmd/efishell.c | 673 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/efishell.h | 5 + 3 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 cmd/efishell.c create mode 100644 cmd/efishell.h
Quoted 13 lines
cmd/Makefile obj-$(CONFIG_CMD_BINOP) += binop.o · line 27
Quoted 10 lines
cmd/Makefile +1
-1@@ -24,7 +24,7 @@ obj-$(CONFIG_CMD_BINOP) += binop.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o -obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o +obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o efishell.oPlease create a separate command line option for efishell and make it disabled by default.
OK.
Quoted 3 lines
I think it's a really really useful debugging aid, but in a normal environment people should only need to run efi binaries (plus bootmgr) and modify efi variables, no?
The ultimate goal would be to provide this command as a separate application. In this case, however, it won't much different from uefi shell itself :)
Quoted 27 lines
Quoted 27 lines
cmd/Makefile +0
-0obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o obj-$(CONFIG_CMD_BOOTZ) += bootz.ocmd/efishell.c new file +16
-0@@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* EFI Shell-like command +* +* Copyright (c) 2018 AKASHI Takahiro, Linaro Limited +*/ + +#include <charset.h> +#include <common.h> +#include <command.h> +#include <efi_loader.h> +#include <environment.h> +#include <errno.h> +#include <exports.h> +#include <hexdump.h> +#include <malloc.h>
Quoted 8 lines
cmd/efishell.c line 22
Quoted 6 lines
cmd/efishell.c new file +6
-0+#include <search.h> +#include <linux/ctype.h> +#include <asm/global_data.h> +#include "efishell.h" + +DECLARE_GLOBAL_DATA_PTR ;Where in this file do you need gd?
OK.
# I thought this should always be declared in any file by default.
Quoted 307 lines
Quoted 307 lines
cmd/efishell.c new file +307
-0+ +static void dump_var_data (char *data,unsigned long len) +{ +char *start, *end, *p; +unsigned long pos, count; +char hex[3 ], line[9 ]; +int i; + + end = data + len; +for (start = data, pos =0 ; start < end; start += count, pos += count) { + count = end - start; +if (count >16 ) + count =16 ; + +/* count should be multiple of two */ +printf ("%08lx: " , pos); + +/* in hex format */ + p = start; +for (i =0 ; i < count /2 ; p +=2 , i++) +printf (" %c%c" , *p, *(p +1 )); +for (; i <8 ; i++) +printf (" " ); + +/* in character format */ + p = start; + hex[2 ] ='\0' ; +for (i =0 ; i < count /2 ; i++) { + hex[0 ] = *p++; + hex[1 ] = *p++; + line[i] =simple_strtoul (hex,0 ,16 ); +if (line[i] <0x20 || line[i] >0x7f ) + line[i] ='.' ; + } + line[i] ='\0' ; +printf (" %s\n" , line); + } +} + +/* +* From efi_variable.c, +* +* Mapping between EFI variables and u-boot variables: +* +* efi_$guid_$varname = {attributes}(type)value +*/ +static int do_efi_dump_var (int argc,char *const argv[]) +{ +char regex[256 ]; +char *const regexlist[] = {regex}; +char *res =NULL , *start, *end; +int len; + +if (argc >2 ) +return CMD_RET_USAGE ; + +if (argc ==2 ) +snprintf (regex,256 ,"efi_.*-.*-.*-.*-.*_%s" , argv[1 ]); +else +snprintf (regex,256 ,"efi_.*-.*-.*-.*-.*_.*" ); +debug ("%s:%d grep uefi var %s\n" , __func__, __LINE__, regex); + + len =hexport_r (&env_htab,'\n' ,H_MATCH_REGEX |H_MATCH_KEY , + &res,0 ,1 , regexlist); + +if (len <0 ) +return CMD_RET_FAILURE ; + +if (len >0 ) { + end = res; +while (true) { +/* variable name */ + start =strchr (end,'_' ); +if (!start) +break ; + start =strchr (++start,'_' ); +if (!start) +break ; + end =strchr (++start,'=' ); +if (!end) +break ; +printf ("%.*s:" , (int )(end - start), start); + end++; + +/* value */ + start = end; + end =strstr (start,"(blob)" ); +if (!end) { +putc ('\n' ); +break ; + } + end +=6 ; +printf (" %.*s\n" , (int )(end - start), start); + + start = end; + end =strchr (start,'\n' ); +if (!end) +break ; +dump_var_data (start, end - start); + } +free (res); + +if (len <2 && argc ==2 ) +printf ("%s: not found\n" , argv[1 ]); + } + +return CMD_RET_SUCCESS ; +} + +static int append_value (char **bufp,unsigned long *sizep,char *data) +{ +char *tmp_buf =NULL , *new_buf =NULL , *value; +unsigned long len =0 ; + +if (!strncmp (data,"=0x" ,2 )) {/* hexadecimal number */ +union { +u8 u8; +u16 u16; +u32 u32; +u64 u64; + } tmp_data; +unsigned long hex_value; +void *hex_ptr; + + data +=3 ; + len =strlen (data); +if ((len &0x1 ))/* not multiple of two */ +return -1 ; + + len /=2 ; +if (len >8 ) +return -1 ; +else if (len >4 ) + len =8 ; +else if (len >2 ) + len =4 ; + +/* convert hex hexadecimal number */ +if (strict_strtoul (data,16 , &hex_value) <0 ) +return -1 ; + + tmp_buf =malloc (len); +if (!tmp_buf) +return -1 ; + +if (len ==1 ) { + tmp_data.u8 = hex_value; + hex_ptr = &tmp_data.u8; + }else if (len ==2 ) { + tmp_data.u16 = hex_value; + hex_ptr = &tmp_data.u16; + }else if (len ==4 ) { + tmp_data.u32 = hex_value; + hex_ptr = &tmp_data.u32; + }else { + tmp_data.u64 = hex_value; + hex_ptr = &tmp_data.u64; + } +memcpy (tmp_buf, hex_ptr, len); + value = tmp_buf; + + }else if (!strncmp (data,"=H" ,2 )) {/* hexadecimal-byte array */ + data +=2 ; + len =strlen (data); +if (len &0x1 )/* not multiple of two */ +return -1 ; + + len /=2 ; + tmp_buf =malloc (len); +if (!tmp_buf) +return -1 ; + +if (hex2bin ((u8 *)tmp_buf, data, len) <0 ) +return -1 ; + + value = tmp_buf; + }else {/* string */ +if (!strncmp (data,"=\"" ,2 ) || !strncmp (data,"=S\"" ,3 )) { +if (data[1 ] =='"' ) + data +=2 ; +else + data +=3 ; + value = data; + len =strlen (data) -1 ; +if (data[len] !='"' ) +return -1 ; + }else { + value = data; + len =strlen (data); + } + } + + new_buf =realloc (*bufp, *sizep + len); +if (!new_buf) + goto out; + +memcpy (new_buf + *sizep, value, len); + *bufp = new_buf; + *sizep += len; + +out: +free (tmp_buf); + +return 0 ; +} + +static int do_efi_set_var (int argc,char *const argv[]) +{ +char *var_name, *value =NULL ; +unsigned long size =0 ; +u16 *var_name16, *p; +efi_guid_t guid; +efi_status_t ret; + +if (argc ==1 ) +return CMD_RET_SUCCESS ; + + var_name = argv[1 ]; +if (argc ==2 ) { +/* remove */ + value =NULL ; + size =0 ; + }else {/* set */ + argc -=2 ; + argv +=2 ; + +for ( ; argc >0 ; argc--, argv++) +if (append_value (&value, &size, argv[0 ]) <0 ) { + ret =CMD_RET_FAILURE ; + goto out; + } + } + + var_name16 =malloc ((strlen (var_name) +1 ) *2 ); + p = var_name16; +utf8_utf16_strncpy (&p, var_name,strlen (var_name) +1 ); + + guid = efi_global_variable_guid; + ret =efi_set_variable (var_name16, &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS , size, value); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +return ret; +} + +static int do_efi_boot_add (int argc,char *const argv[]) +{ +int id; +char *endp; +char var_name[9 ]; +u16 var_name16[9 ], *p; +efi_guid_t guid; +size_t label_len, label_len16; +u16 *label; +struct efi_device_path *device_path =NULL , *file_path =NULL ; +struct efi_load_option lo; +void *data =NULL ; +unsigned long size; +int ret; + +if (argc <6 || argc >7 ) +return CMD_RET_USAGE ; + + id = (int )simple_strtoul (argv[1 ], &endp,0 ); +if (*endp !='\0' || id >0xffff ) +return CMD_RET_FAILURE ; + +sprintf (var_name,"Boot%04X" , id); + p = var_name16; +utf8_utf16_strncpy (&p, var_name,9 ); + + guid = efi_global_variable_guid; + +/* attributes */ + lo.attributes =0x1 ;/* always ACTIVE */ + +/* label */ + label_len =strlen (argv[2 ]); + label_len16 =utf8_utf16_strnlen (argv[2 ], label_len); + label =malloc ((label_len16 +1 ) *sizeof (u16)); +if (!label) +return CMD_RET_FAILURE ; + lo.label = label;/* label will be changed below */ +utf8_utf16_strncpy (&label, argv[2 ], label_len); + +/* file path */ + ret =efi_dp_from_name (argv[3 ], argv[4 ], argv[5 ], &device_path, + &file_path); +if (ret !=EFI_SUCCESS ) { + ret =CMD_RET_FAILURE ; + goto out; + } + lo.file_path = file_path; + lo.file_path_length =efi_dp_size (file_path) + +sizeof (struct efi_device_path );/* for END */ + +/* optional data */ + lo.optional_data = (u8 *)(argc ==6 ?"" : argv[6 ]); + + size =efi_serialize_load_option (&lo, (u8 **)&data); +if (!size) { + ret =CMD_RET_FAILURE ; + goto out; + } + + ret = efi_set_variable(var_name16, &guid,
Quoted 8 lines
cmd/efishell.c line 335
Quoted 6 lines
cmd/efishell.c new file +6
-0+EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, size, data); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +free (data); +#if 0 /* FIXME */ Eh, what? :)
Well, in the past, I saw u-boot hang-out if free()'s were enabled. Now I found that we must free data with efi_free_pool() instead of free().
Quoted 96 lines
Quoted 96 lines
cmd/efishell.c new file +96
-0+free (device_path); +free (file_path); +#endif +free (lo.label); +return ret; +} + +static int do_efi_boot_rm (int argc,char *const argv[]) +{ +efi_guid_t guid; +int id, i; +char *endp; +char var_name[9 ]; +u16 var_name16[9 ]; +efi_status_t ret; + +if (argc ==1 ) +return CMD_RET_USAGE ; + + guid = efi_global_variable_guid; +for (i =1 ; i < argc; i++, argv++) { + id = (int )simple_strtoul (argv[1 ], &endp,0 ); +if (*endp !='\0' || id >0xffff ) +return CMD_RET_FAILURE ; + +sprintf (var_name,"Boot%04X" , id); +utf8_utf16_strncpy ((u16 **)&var_name16, var_name,9 ); + + ret =efi_set_variable (var_name16, &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS ,0 ,NULL ); +if (ret) { +printf ("cannot remove Boot%04X" , id); +return CMD_RET_FAILURE ; + } + } + +return CMD_RET_SUCCESS ; +} + +static void show_efi_boot_opt_data (int id,void *data) +{ +struct efi_load_option lo; +char *label, *p; +size_t label_len16, label_len; +u16 *dp_str; + +efi_deserialize_load_option (&lo, data); + + label_len16 =u16_strlen (lo.label); + label_len =utf16_utf8_strnlen (lo.label, label_len16); + label =malloc (label_len +1 ); +if (!label) +return ; + p = label; +utf16_utf8_strncpy (&p, lo.label, label_len16); + +printf ("Boot%04X:\n" , id); +printf ("\tattributes: %c%c%c (0x%08x)\n" , +/* ACTIVE */ + lo.attributes &0x1 ?'A' :'-' , +/* FORCE RECONNECT */ + lo.attributes &0x2 ?'R' :'-' , +/* HIDDEN */ + lo.attributes &0x8 ?'H' :'-' , + lo.attributes); +printf ("\tlabel: %s\n" , label); + + dp_str =efi_dp_str (lo.file_path); +printf ("\tfile_path: %ls\n" , dp_str); +efi_free_pool (dp_str); + +printf ("\tdata: %s\n" , lo.optional_data); + +free (label); +} + +static void show_efi_boot_opt (int id) +{ +char var_name[9 ]; +u16 var_name16[9 ], *p; +efi_guid_t guid; +void *data =NULL ; +unsigned long size; +int ret; + +sprintf (var_name,"Boot%04X" , id); + p = var_name16; +utf8_utf16_strncpy (&p, var_name,9 ); + guid = efi_global_variable_guid; + + size =0 ; + ret =efi_get_variable (var_name16, &guid,NULL , &size,NULL ); +if (ret == (int )EFI_BUFFER_TOO_SMALL ) { + data =malloc (size); + ret =efi_get_variable (var_name16, &guid,NULL , &size, data);
Quoted 8 lines
cmd/efishell.c line 437
Quoted 6 lines
cmd/efishell.c new file +6
-0+ } +if (ret ==EFI_SUCCESS ) { +show_efi_boot_opt_data (id, data); +free (data); + }else if (ret ==EFI_NOT_FOUND ) { +printf ("Boot%04X: not found\n" , id);Missing free?
Fix it.
Quoted 58 lines
Quoted 58 lines
cmd/efishell.c new file +58
-0+ } +} + +static int do_efi_boot_dump (int argc,char *const argv[]) +{ +char regex[256 ]; +char *const regexlist[] = {regex}; +char *variables =NULL , *boot, *value; +int len; +int id; + +if (argc >1 ) +return CMD_RET_USAGE ; + +snprintf (regex,256 ,"efi_.*-.*-.*-.*-.*_Boot[0-9A-F]+" ); + + len =hexport_r (&env_htab,'\n' ,H_MATCH_REGEX |H_MATCH_KEY , + &variables,0 ,1 , regexlist); + +if (!len) +return CMD_RET_SUCCESS ; + +if (len <0 ) +return CMD_RET_FAILURE ; + + boot = variables; +while (*boot) { + value =strstr (boot,"Boot" ) +4 ; + id = (int )simple_strtoul (value,NULL ,16 ); +show_efi_boot_opt (id); + boot =strchr (boot,'\n' ); +if (!*boot) +break ; + boot++; + } +free (variables); + +return CMD_RET_SUCCESS ; +} + +static int show_efi_boot_order (void ) +{ +efi_guid_t guid; +u16 *bootorder =NULL ; +unsigned long size; +int num, i; +char var_name[9 ]; +u16 var_name16[9 ], *p16; +void *data; +struct efi_load_option lo; +char *label, *p; +size_t label_len16, label_len; +efi_status_t ret =CMD_RET_SUCCESS ; + + guid = efi_global_variable_guid; + size =0 ; + ret =efi_get_variable (L"BootOrder" , &guid,NULL , &size,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) {
Quoted 8 lines
cmd/efishell.c line 501
Quoted 6 lines
cmd/efishell.c new file +6
-0+ bootorder =malloc (size); + ret =efi_get_variable (L"BootOrder" , &guid,NULL , &size, + bootorder); + } +if (ret !=EFI_SUCCESS ) { +printf ("BootOrder not defined\n" );Missing free(bootorder)
OK. In addition, I will modify the code to check for EFI_NOT_FOUND.
Quoted 21 lines
Quoted 21 lines
cmd/efishell.c new file +21
-0+return CMD_RET_SUCCESS ; + } + + num = size /sizeof (u16); +for (i =0 ; i < num; i++) { +sprintf (var_name,"Boot%04X" , bootorder[i]); + p16 = var_name16; +utf8_utf16_strncpy (&p16, var_name,9 ); + + size =0 ; + ret =efi_get_variable (var_name16, &guid,NULL , &size,NULL ); +if (ret !=EFI_BUFFER_TOO_SMALL ) { +printf ("%2d: Boot%04X: (not defined)\n" , + i +1 , bootorder[i]); +continue ; + } + + data =malloc (size); +if (!data) { + ret =CMD_RET_FAILURE ; + goto out;
Quoted 8 lines
cmd/efishell.c line 528
Quoted 6 lines
cmd/efishell.c new file +6
-0+ } + ret =efi_get_variable (var_name16, &guid,NULL , &size, data); +if (ret !=EFI_SUCCESS ) { +free (data); + ret =CMD_RET_FAILURE ; + goto out;Probably better to free(data) at out:, no?
It's possible, but 'data' is only allocated and used repeatedly in a loop, so freeing it within a loop would look to be a good manner.
Quoted 150 lines
Quoted 150 lines
cmd/efishell.c new file +145
-0+ } + +efi_deserialize_load_option (&lo, data); + + label_len16 =u16_strlen (lo.label); + label_len =utf16_utf8_strnlen (lo.label, label_len16); + label =malloc (label_len +1 ); +if (!label) { +free (data); + ret =CMD_RET_FAILURE ; + goto out; + } + p = label; +utf16_utf8_strncpy (&p, lo.label, label_len16); +printf ("%2d: Boot%04X: %s\n" , i +1 , bootorder[i], label); +free (label); + +free (data); + } +out: +free (bootorder); + +return ret; +} + +static int do_efi_boot_order (int argc,char *const argv[]) +{ +u16 *bootorder =NULL ; +unsigned long size; +int id, i; +char *endp; +efi_guid_t guid; +efi_status_t ret; + +if (argc ==1 ) +return show_efi_boot_order (); + + argc--; + argv++; + + size = argc *sizeof (u16); + bootorder =malloc (size); +if (!bootorder) +return CMD_RET_FAILURE ; + +for (i =0 ; i < argc; i++) { + id = (int )simple_strtoul (argv[i], &endp,0 ); +if (*endp !='\0' || id >0xffff ) { +printf ("invalid value: %s\n" , argv[i]); + ret =CMD_RET_FAILURE ; + goto out; + } + + bootorder[i] = (u16 )id; + } + + guid = efi_global_variable_guid; + ret =efi_set_variable (L"BootOrder" , &guid, +EFI_VARIABLE_BOOTSERVICE_ACCESS | +EFI_VARIABLE_RUNTIME_ACCESS , size, bootorder); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +free (bootorder); + +return ret; +} + +static int do_efi_boot_opt (int argc,char *const argv[]) +{ +char *sub_command; + +if (argc <2 ) +return CMD_RET_USAGE ; + + argc--; argv++; + sub_command = argv[0 ]; + +if (!strcmp (sub_command,"add" )) +return do_efi_boot_add (argc, argv); +else if (!strcmp (sub_command,"rm" )) +return do_efi_boot_rm (argc, argv); +else if (!strcmp (sub_command,"dump" )) +return do_efi_boot_dump (argc, argv); +else if (!strcmp (sub_command,"order" )) +return do_efi_boot_order (argc, argv); +else +return CMD_RET_USAGE ; +} + +/* Interpreter command to configure EFI environment */ +static int do_efishell (cmd_tbl_t *cmdtp,int flag, +int argc,char *const argv[]) +{ +char *command; +efi_status_t r; + +if (argc <2 ) +return CMD_RET_USAGE ; + + argc--; argv++; + command = argv[0 ]; + +/* Initialize EFI drivers */ + r =efi_init_obj_list (); +if (r !=EFI_SUCCESS ) { +printf ("Error: Cannot set up EFI drivers, r = %lu\n" , + r & ~EFI_ERROR_MASK ); +return CMD_RET_FAILURE ; + } + +if (!strcmp (command,"boot" )) +return do_efi_boot_opt (argc, argv); +else if (!strcmp (command,"dumpvar" ) || !strcmp (command,"dmpstore" )) +return do_efi_dump_var (argc, argv); +else if (!strcmp (command,"setvar" )) +return do_efi_set_var (argc, argv); +else +return CMD_RET_USAGE ; +} + +#ifdef CONFIG_SYS_LONGHELP +static char efishell_help_text[] = +" - EFI Shell-like interface to configure EFI environment\n" +"\n" +"efishell boot add <bootid> <label> <interface> <device>[:<part>] <file path> <option>\n" +" - set uefi's BOOT variable\n" +"efishell boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n" +" - set/display uefi boot order\n" +"efishell boot dump\n" +" - display all uefi's BOOT variables\n" +"efishell boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n" +" - set/display uefi boot order\n" +"\n" +"efishell dumpvar [<name>]\n" +" - get uefi variable's value\n" +"efishell setvar <name> [<value>]\n" +" - set/delete uefi variable's value\n" +" <value> may be \"=\"...\"\", \"=0x...\" (set) or \"=\" (delete)\n" ; +#endif + +U_BOOT_CMD ( + efishell,10 ,0 , do_efishell, +"Configure EFI environment" , + efishell_help_text +);cmd/efishell.h new file +0
-0
Quoted 8 lines
cmd/efishell.h line 5
Quoted 6 lines
cmd/efishell.h new file +5
-0@@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <efi.h> + +efi_status_t efi_init_obj_list (void );Why isn't this in
efi_loader.h? That's the subsystem that exports it, no?
Agree. Moreover, I think of refactoring the code and moving efi_init_obj_list() to a new file, lib/efi_loader/efi_setup.c, so that we can add more features directly as part of the initialization code.
Features may include USB removable disk support for which I already posted a patch set[1] and yet-coming capsule-on-disk support.
Actually, I have this refactoring patch in my local dev branch. May I submit it as a separate one?
[1] https://lists.denx.de/pipermail/u-boot/2018-November/347493.html
Thanks,
-Takahiro Akashi
Quoted 2 lines
Alex
PATCH v2 4/14 cmd: add efishell command
Quoted 90 lines · AKASHI Takahiro
Quoted 29 lines · Alexander Graf
Quoted 26 lines · AKASHI Takahiro
Currently, there is no easy way to add or modify UEFI variables. In particular, bootmgr supports BootOrder/BootXXXX variables, it is quite hard to define them as u-boot variables because they are represented in a complicated and encoded format.
The new command, efishell, helps address these issues and give us more friendly interfaces:
* efishell boot add: add BootXXXX variable
* efishell boot rm: remove BootXXXX variable
* efishell boot dump: display all BootXXXX variables
* efishell boot order: set/display a boot order (BootOrder)
* efishell setvar: set an UEFI variable (with limited functionality)
* efishell dumpvar: display all UEFI variablesAs the name suggests, this command basically provides a subset fo UEFI shell commands with simplified functionality.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/Makefile | 2 +- cmd/efishell.c | 673 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/efishell.h | 5 + 3 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 cmd/efishell.c create mode 100644 cmd/efishell.hQuoted 13 lines
cmd/Makefile obj-$(CONFIG_CMD_BINOP) += binop.o · line 27
Quoted 10 lines
cmd/Makefile +1
-1@@ -24,7 +24,7 @@ obj-$(CONFIG_CMD_BINOP) += binop.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o -obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o +obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o efishell.oPlease create a separate command line option for efishell and make it disabled by default.
OK.
Quoted 3 lines
I think it's a really really useful debugging aid, but in a normal environment people should only need to run efi binaries (plus bootmgr) and modify efi variables, no?
The ultimate goal would be to provide this command as a separate application. In this case, however, it won't much different from uefi shell itself :)
Quoted 27 lines
Quoted 27 lines
cmd/Makefile +0
-0obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o obj-$(CONFIG_CMD_BOOTZ) += bootz.ocmd/efishell.c new file +16
-0@@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* EFI Shell-like command +* +* Copyright (c) 2018 AKASHI Takahiro, Linaro Limited +*/ + +#include <charset.h> +#include <common.h> +#include <command.h> +#include <efi_loader.h> +#include <environment.h> +#include <errno.h> +#include <exports.h> +#include <hexdump.h> +#include <malloc.h> Quoted 8 lines
cmd/efishell.c line 22
Quoted 6 lines
cmd/efishell.c new file +6
-0+#include <search.h> +#include <linux/ctype.h> +#include <asm/global_data.h> +#include "efishell.h" + +DECLARE_GLOBAL_DATA_PTR ;Where in this file do you need gd?
Quoted 2 lines
OK.
# I thought this should always be declared in any file by default.
You only need to declare it when you need gd :). Most efi_loader code should be able to live just fine without.
[...]
Quoted 19 lines
Quoted 10 lines
Quoted 10 lines
cmd/efishell.c new file +10
-0+/* optional data */ + lo.optional_data = (u8 *)(argc ==6 ?"" : argv[6 ]); + + size =efi_serialize_load_option (&lo, (u8 **)&data); +if (!size) { + ret =CMD_RET_FAILURE ; + goto out; + } + + ret = efi_set_variable(var_name16, &guid,Quoted 8 lines
cmd/efishell.c line 335
Quoted 6 lines
cmd/efishell.c new file +6
-0+EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, size, data); + ret = (ret ==EFI_SUCCESS ?CMD_RET_SUCCESS :CMD_RET_FAILURE ); +out: +free (data); +#if 0 /* FIXME */ Eh, what? :)
Quoted 2 lines
Well, in the past, I saw u-boot hang-out if free()'s were enabled. Now I found that we must free data with
efi_free_pool()instead offree().
It depends on how data was allocated, yes.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
cmd/efishell.c new file +7
-0+free (device_path); +free (file_path); +#endif +free (lo.label); +return ret; +} +
[...]
Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
cmd/efishell.h new file +0
-0Quoted 8 lines
cmd/efishell.h line 5
Quoted 6 lines
cmd/efishell.h new file +5
-0@@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <efi.h> + +efi_status_t efi_init_obj_list (void );Why isn't this in
efi_loader.h? That's the subsystem that exports it, no?
Quoted 3 lines
Agree. Moreover, I think of refactoring the code and moving
efi_init_obj_list()to a new file,lib/efi_loader/efi_setup.c, so that we can add more features directly as part of the initialization code.
Well, as Heinrich already indicated, the long term goal would be to have UEFI handles implicitly generated for DM devices. So we wouldn't need to maintain our own copy of the already existing object model.
Alex
Quoted 14 lines
Features may include USB removable disk support for which I already posted a patch set[1] and yet-coming capsule-on-disk support.
Actually, I have this refactoring patch in my local dev branch. May I submit it as a separate one?
[1] https://lists.denx.de/pipermail/u-boot/2018-November/347493.html
Thanks,
-Takahiro AkashiQuoted 2 lines
Alex
PATCH v2 5/14 cmd: efishell: add devices command
In reply to AKASHI Takahiro"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)
--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)
cmd/efishell.c +87 -1
@@ -21,6 +21,8 @@DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs; +static void dump_var_data (char *data,unsigned long len) {char *start, *end, *p;
@@ -266,6 +268,84 @@ out:return ret; } +static efi_handle_t *efi_get_handles_by_proto (efi_guid_t *guid) +{ +efi_handle_t *handles =NULL ; +efi_uintn_t size =0 ; +efi_status_t ret; + +if (guid) { + ret = bs->locate_handle (BY_PROTOCOL , guid,NULL , &size, + handles); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + handles =calloc (1 , size); +if (!handles) +return NULL ; + + ret = bs->locate_handle (BY_PROTOCOL , guid,NULL , &size, + handles); + } +if (ret !=EFI_SUCCESS ) { +free (handles); +return NULL ; + } + }else { + ret = bs->locate_handle (ALL_HANDLES ,NULL ,NULL , &size,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + handles =calloc (1 , size); +if (!handles) +return NULL ; + + ret = bs->locate_handle (ALL_HANDLES ,NULL ,NULL , &size, + handles); + } +if (ret !=EFI_SUCCESS ) { +free (handles); +return NULL ; + } + } + +return handles; +} + +static int efi_get_device_handle_info (efi_handle_t handle,u16 **name) +{ +struct efi_device_path *dp; +efi_status_t ret; + + ret = bs->open_protocol (handle, &efi_guid_device_path, + (void **)&dp,NULL /* FIXME */ ,NULL , +EFI_OPEN_PROTOCOL_GET_PROTOCOL ); +if (ret ==EFI_SUCCESS ) { + *name =efi_dp_str (dp); +return 0 ; + }else { +return -1 ; + } +} + +static int do_efi_show_devices (int argc,char *const argv[]) +{ +efi_handle_t *handles =NULL , *handle; +u16 *devname; + + handles =efi_get_handles_by_proto (NULL ); +if (!handles) +return CMD_RET_SUCCESS ; + +printf ("Device Name\n" ); +printf ("============================================\n" ); +for (handle = handles; *handle; handle++) { +if (!efi_get_device_handle_info (*handle, &devname)) { +printf ("%ls\n" , devname); +efi_free_pool (devname); + } + handle++; + } + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;
@@ -625,6 +705,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,if (argc <2 )return CMD_RET_USAGE ; + bs = systab.boottime; + argc--; argv++; command = argv[0 ];
@@ -642,6 +724,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_dump_var (argc, argv); else if (!strcmp(command, "setvar"))return do_efi_set_var (argc, argv); + else if (!strcmp(command, "devices")) +return do_efi_show_devices (argc, argv); else return CMD_RET_USAGE; }
@@ -663,7 +747,9 @@ static char efishell_help_text[] =" - get uefi variable's value\n" "efishell setvar <name> [<value>]\n" " - set/delete uefi variable's value\n" -" <value> may be \"=\"...\"\", \"=0x...\" (set) or \"=\" (delete)\n" ; +" <value> may be \"=\"...\"\", \"=0x...\" (set) or \"=\" (delete)\n" +"efishell devices\n" +" - show uefi devices\n" ;#endif U_BOOT_CMD(
Signature · 1 line
2.19.0
PATCH v2 5/14 cmd: efishell: add devices command
Quoted 21 lines · AKASHI Takahiro
"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)cmd/efishell.c +0
-0
cmd/efishell.c line 24
Quoted 4 lines
cmd/efishell.c +1
-0@@ -21,6 +21,8 @@DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs;
Why do you need a local copy of this?
Alex
PATCH v2 5/14 cmd: efishell: add devices command
Quoted 25 lines · Alexander Graf
Quoted 22 lines · AKASHI Takahiro
"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)cmd/efishell.c +0
-0@@ -21,6 +21,8 @@
Quoted 5 lines
cmd/efishell.c line 24
Quoted 3 lines
cmd/efishell.c +1
-0DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs;Why do you need a local copy of this?
Good point. It's because I followed the way boot manager does :)
I think that it would be good to do so since either boot manager or efishell should ultimately be an independent efi application in its nature.
What do you think?
FYI, one of the reasons why efishell cannot be an application is that we lack an runtime service interface of GetNextVariableName() which can be used to enumerate variables in dumpvar sub-command.
I also have a patch for adding GetNextVariableName() in my local dev branch. I intend to post this patch along with capsule-on-disk support, but I may be able to submit it separately if you like.
Thanks,
-Takahiro Akashi
Quoted 2 lines
Alex
PATCH v2 5/14 cmd: efishell: add devices command
Quoted 32 lines · AKASHI Takahiro
Quoted 25 lines · Alexander Graf
Quoted 22 lines · AKASHI Takahiro
"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)cmd/efishell.c +0
-0@@ -21,6 +21,8 @@Quoted 5 lines
cmd/efishell.c line 24
Quoted 3 lines
cmd/efishell.c +1
-0DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs;Why do you need a local copy of this?
Quoted 7 lines
Good point. It's because I followed the way boot manager does :)
I think that it would be good to do so since either boot manager or efishell should ultimately be an independent efi application in its nature.
What do you think?
As mentioned in the other email thread, I think that we should definitely evaluate to add the edk2 shell as built-in option.
That way for the "full-fledged" shell experience, your built-in code is not needed. But I still believe it would be useful for quick and built-in debugging.
Alex
PATCH v2 5/14 cmd: efishell: add devices command
Quoted 35 lines · Alexander Graf
Quoted 32 lines · AKASHI Takahiro
Quoted 30 lines · Alexander Graf
Quoted 21 lines · AKASHI Takahiro
"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)cmd/efishell.c +0
-0cmd/efishell.c line 24
Quoted 4 lines
cmd/efishell.c +1
-0@@ -21,6 +21,8 @@DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs;Why do you need a local copy of this?
Quoted 7 lines
Quoted 7 lines
Good point. It's because I followed the way boot manager does :)
I think that it would be good to do so since either boot manager or efishell should ultimately be an independent efi application in its nature.
What do you think?
Back to your original comment: Why do you need a local copy of this?
Do you think we should use systab.boottime,runtime instead?
Quoted 2 lines
As mentioned in the other email thread, I think that we should definitely evaluate to add the edk2 shell as built-in option.
Do you expect that I will add a new config, say, CONFIG_EFI_SHELL_PATH?
-Takahiro Akashi
Quoted 6 lines
That way for the "full-fledged" shell experience, your built-in code is not needed. But I still believe it would be useful for quick and built-in debugging.
Alex
PATCH v2 5/14 cmd: efishell: add devices command
Quoted 42 lines · AKASHI Takahiro
Quoted 41 lines · Alexander Graf
Quoted 38 lines · AKASHI Takahiro
Quoted 25 lines · Alexander Graf
Quoted 22 lines · AKASHI Takahiro
"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)cmd/efishell.c +0
-0@@ -21,6 +21,8 @@Quoted 5 lines
cmd/efishell.c line 24
Quoted 3 lines
cmd/efishell.c +1
-0DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs;Why do you need a local copy of this?
Good point. It's because I followed the way boot manager does :)
I think that it would be good to do so since either boot manager or efishell should ultimately be an independent efi application in its nature.
Quoted 5 lines
Quoted 1 line
Quoted 1 line
What do you think?
Back to your original comment: Why do you need a local copy of this?
Do you think we should use systab.boottime,runtime instead?
Sure, that's one thing. Or you could make it a local variable. Or you could even do a #define in the file. But that static const here will most likely waste space in .bss and does not take into account when someone patches the systab.
Quoted 4 lines
Quoted 2 lines
As mentioned in the other email thread, I think that we should definitely evaluate to add the edk2 shell as built-in option.
Do you expect that I will add a new config, say,
CONFIG_EFI_SHELL_PATH?
Doesn't have to be you, but it might be useful to have something like that, yes.
CONFIG_CMD_BOOTEFI_SHELL=yCONFIG_CMD_BOOTEFI_SHELL_PATH=shell.efi
which then would work the same as CONFIG_CMD_BOOTEFI_HELLO, but simply execute a precompiled version of the UEFI shell. IIRC the UEFI shell also supports passing arguments via the command line (load_options -> "bootargs" variable).
So with that you should be able to run
U-Boot# setenv bootargs memmap; bootefi shell
and get a list of the UEFI memory map.
Alex
PATCH v2 5/14 cmd: efishell: add devices command
Quoted 47 lines · Alexander Graf
Quoted 44 lines · AKASHI Takahiro
Quoted 42 lines · Alexander Graf
Quoted 39 lines · AKASHI Takahiro
Quoted 25 lines · Alexander Graf
Quoted 22 lines · AKASHI Takahiro
"devices" command prints all the uefi variables on the system. => efishell devices
Device Name
============================================
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(2,MBR,0x086246ba,0x40800,0x3f800) /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/SD(0)/\ HD(1,MBR,0x086246ba,0x800,0x40000)Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)cmd/efishell.c +0
-0@@ -21,6 +21,8 @@Quoted 5 lines
cmd/efishell.c line 24
Quoted 3 lines
cmd/efishell.c +1
-0DECLARE_GLOBAL_DATA_PTR ; +static const struct efi_boot_services *bs;Why do you need a local copy of this?
Good point. It's because I followed the way boot manager does :)
I think that it would be good to do so since either boot manager or efishell should ultimately be an independent efi application in its nature.
What do you think?
Quoted 8 lines
Quoted 3 lines
Back to your original comment: Why do you need a local copy of this?
Do you think we should use systab.boottime,runtime instead?
Sure, that's one thing. Or you could make it a local variable. Or you could even do a #define in the file. But that static const here will most likely waste space in .bss and does not take into account when someone patches the systab.
OK, I will add a macro definition.
-Takahiro Akashi
Quoted 24 lines
Quoted 4 lines
Quoted 2 lines
As mentioned in the other email thread, I think that we should definitely evaluate to add the edk2 shell as built-in option.
Do you expect that I will add a new config, say,
CONFIG_EFI_SHELL_PATH?Doesn't have to be you, but it might be useful to have something like that, yes.
CONFIG_CMD_BOOTEFI_SHELL=yCONFIG_CMD_BOOTEFI_SHELL_PATH=shell.efiwhich then would work the same as
CONFIG_CMD_BOOTEFI_HELLO, but simply execute a precompiled version of the UEFI shell. IIRC the UEFI shell also supports passing arguments via the command line (load_options-> "bootargs" variable).So with that you should be able to run
U-Boot# setenv bootargs memmap; bootefi shell
and get a list of the UEFI memory map.
Alex
PATCH v2 6/14 cmd: efishell: add drivers command
In reply to AKASHI Takahiro"drivers" command prints all the uefi drivers on the system. => efi drivers
Driver Name Image Path
============================================
(unknown) <NULL>+(not found)
guid: 18a031ab-b443-4d1a-a5c0-0c09261e9f71
Currently, no useful information can be printed.
--- cmd/efishell.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-)
cmd/efishell.c +94 -1
@@ -346,6 +346,95 @@ static int do_efi_show_devices(int argc, char * const argv[])return CMD_RET_SUCCESS ; } +static int efi_get_driver_handle_info (efi_handle_t handle,u16 **name, +u16 **devname,u16 **filename) +{ +struct efi_driver_binding_protocol *binding; +struct efi_loaded_image *image; +efi_status_t ret; + + ret = bs->open_protocol (handle, &efi_guid_driver_binding_protocol, + (void **)&binding,NULL ,NULL , +EFI_OPEN_PROTOCOL_GET_PROTOCOL ); +if (ret !=EFI_SUCCESS ) +return -1 ; + + ret = bs->open_protocol (binding->image_handle, &efi_guid_loaded_image, + (void **)&image,NULL /* FIXME */ ,NULL , +EFI_OPEN_PROTOCOL_GET_PROTOCOL ); +if (ret !=EFI_SUCCESS ) + goto e_out; + +/* +* TODO: +* handle image->device_handle, +* use append_device_path() +*/ + *devname =NULL ; + *filename =efi_dp_str (image->file_path); + +return 0 ; + +e_out: + *devname =NULL ; + *filename =L"(not found)" ; + +return 0 ; +} + +static int do_efi_show_drivers (int argc,char *const argv[]) +{ +efi_handle_t *handles =NULL , *handle; +efi_uintn_t size =0 ; +u16 *drvname, *devname, *filename; +efi_status_t ret; +int i; + + ret = bs->locate_handle (BY_PROTOCOL , &efi_guid_driver_binding_protocol, +NULL , &size,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + handles =calloc (1 , size); +if (!handles) +return CMD_RET_FAILURE ; + + ret = bs->locate_handle (BY_PROTOCOL , + &efi_guid_driver_binding_protocol, +NULL , &size, handles); + } +if (ret !=EFI_SUCCESS ) { +free (handles); +return CMD_RET_FAILURE ; + } + +printf ("Driver Name Image Path\n" ); +printf ("============================================\n" ); + handle = handles; +for (i =0 ; i < size /sizeof (*handle); i++) { +if (!efi_get_driver_handle_info (*handle, &drvname, &devname, + &filename)) { +printf ("%-16s%ls+%ls\n" , +"(unknown)" , devname, filename); +efi_free_pool (devname); +efi_free_pool (filename); + +/* TODO: no other info */ +struct efi_object *efiobj; +struct list_head *lhandle; +struct efi_handler *protocol; + + efiobj =efi_search_obj (*handle); +list_for_each (lhandle, &efiobj->protocols) { + protocol =list_entry (lhandle, + struct efi_handler, link); +printf (" guid: %pUl\n" , protocol->guid); + } + } + handle++; + } + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;
@@ -726,6 +815,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_set_var (argc, argv); else if (!strcmp(command, "devices"))return do_efi_show_devices (argc, argv); + else if (!strcmp(command, "drivers")) +return do_efi_show_drivers (argc, argv); else return CMD_RET_USAGE; }
@@ -749,7 +840,9 @@ static char efishell_help_text[] =" - set/delete uefi variable's value\n" " <value> may be \"=\"...\"\", \"=0x...\" (set) or \"=\" (delete)\n" "efishell devices\n" -" - show uefi devices\n" ; +" - show uefi devices\n" +"efishell drivers\n" +" - show uefi drivers\n" ;#endif U_BOOT_CMD(
Signature · 1 line
2.19.0
PATCH v2 7/14 cmd: efishell: add images command
In reply to AKASHI Takahiro"images" command prints loaded images-related information.
--- cmd/efishell.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
cmd/efishell.c +12 -1
@@ -435,6 +435,13 @@ static int do_efi_show_drivers(int argc, char * const argv[])return CMD_RET_SUCCESS ; } +static int do_efi_show_images (int argc,char *const argv[]) +{ +efi_print_image_infos (NULL ); + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;
@@ -817,6 +824,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_show_devices (argc, argv); else if (!strcmp(command, "drivers"))return do_efi_show_drivers (argc, argv); + else if (!strcmp(command, "images")) +return do_efi_show_images (argc, argv); else return CMD_RET_USAGE; }
@@ -842,7 +851,9 @@ static char efishell_help_text[] ="efishell devices\n" " - show uefi devices\n" "efishell drivers\n" -" - show uefi drivers\n" ; +" - show uefi drivers\n" +"efishell images\n" +" - show loaded images\n" ;#endif U_BOOT_CMD(
Signature · 1 line
2.19.0
PATCH v2 8/14 cmd: efishell: add memmap command
In reply to AKASHI Takahiro"memmap" command prints uefi-specific memory map information. => efi memmap
Type Start End Attributes
================ ================ ================ ==========
CONVENTIONAL 0000000040000000-000000007de27000 WB RUNTIME DATA 000000007de27000-000000007de28000 WB|RT RESERVED 000000007de28000-000000007de2a000 WB RUNTIME DATA 000000007de2a000-000000007de2b000 WB|RT RESERVED 000000007de2b000-000000007de2c000 WB RUNTIME DATA 000000007de2c000-000000007de2d000 WB|RT LOADER DATA 000000007de2d000-000000007ff37000 WB RUNTIME CODE 000000007ff37000-000000007ff38000 WB|RT LOADER DATA 000000007ff38000-0000000080000000 WB
--- cmd/efishell.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-)
cmd/efishell.c +77 -1
@@ -442,6 +442,78 @@ static int do_efi_show_images(int argc, char * const argv[])return CMD_RET_SUCCESS ; } +static const char *const efi_mem_type_string[] = { + [EFI_RESERVED_MEMORY_TYPE ] ="RESERVED" , + [EFI_LOADER_CODE ] ="LOADER CODE" , + [EFI_LOADER_DATA ] ="LOADER DATA" , + [EFI_BOOT_SERVICES_CODE ] ="BOOT CODE" , + [EFI_BOOT_SERVICES_DATA ] ="BOOT DATA" , + [EFI_RUNTIME_SERVICES_CODE ] ="RUNTIME CODE" , + [EFI_RUNTIME_SERVICES_DATA ] ="RUNTIME DATA" , + [EFI_CONVENTIONAL_MEMORY ] ="CONVENTIONAL" , + [EFI_UNUSABLE_MEMORY ] ="UNUSABLE MEM" , + [EFI_ACPI_RECLAIM_MEMORY ] ="ACPI RECLAIM MEM" , + [EFI_ACPI_MEMORY_NVS ] ="ACPI NVS" , + [EFI_MMAP_IO ] ="IO" , + [EFI_MMAP_IO_PORT ] ="IO PORT" , + [EFI_PAL_CODE ] ="PAL" , +}; + +#define EFI_MEM_ATTR (attribute, bit, string) \ + if ((attribute) & (bit)) { \ + if (sep) \ + putc('|'); \ + sep = 1; \ + printf(string); \ + } + +static int do_efi_show_memmap (int argc,char *const argv[]) +{ +struct efi_mem_desc *map =NULL ; +efi_uintn_t map_size =0 ; +int i, sep; +efi_status_t ret; + + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + map =malloc (map_size); +if (!map) +return CMD_RET_FAILURE ; + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); + } +if (ret !=EFI_SUCCESS ) +return CMD_RET_FAILURE ; + + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); +if (ret !=EFI_SUCCESS ) +return CMD_RET_FAILURE ; + +printf ("Type Start End Attributes\n" ); +printf ("================ ================ ================ ==========\n" ); +for (i =0 ; i < map_size /sizeof (*map); map++, i++) { + sep =0 ; +printf ("%-16s %016llx-%016llx " , + efi_mem_type_string[map->type], + map->physical_start, + map->physical_start + map->num_pages *EFI_PAGE_SIZE ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_UC ,"UC" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WC ,"WC" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WT ,"WT" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WB ,"WB" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_UCE ,"UCE" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WP ,"WP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RP ,"RP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_XP ,"WP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_NV ,"NV" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_MORE_RELIABLE ,"REL" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RO ,"RO" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RUNTIME ,"RT" ); +putc ('\n' ); + } + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;
@@ -826,6 +898,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_show_drivers (argc, argv); else if (!strcmp(command, "images"))return do_efi_show_images (argc, argv); + else if (!strcmp(command, "memmap")) +return do_efi_show_memmap (argc, argv); else return CMD_RET_USAGE; }
@@ -853,7 +927,9 @@ static char efishell_help_text[] ="efishell drivers\n" " - show uefi drivers\n" "efishell images\n" -" - show loaded images\n" ; +" - show loaded images\n" +"efishell memmap\n" +" - show uefi memory map\n" ;#endif U_BOOT_CMD(
Signature · 1 line
2.19.0
PATCH v2 8/14 cmd: efishell: add memmap command
Quoted 52 lines · AKASHI Takahiro
"memmap" command prints uefi-specific memory map information. => efi memmap
Type Start End Attributes
================ ================ ================ ==========CONVENTIONAL 0000000040000000-000000007de27000 WB RUNTIME DATA 000000007de27000-000000007de28000 WB|RT RESERVED 000000007de28000-000000007de2a000 WB RUNTIME DATA 000000007de2a000-000000007de2b000 WB|RT RESERVED 000000007de2b000-000000007de2c000 WB RUNTIME DATA 000000007de2c000-000000007de2d000 WB|RT LOADER DATA 000000007de2d000-000000007ff37000 WB RUNTIME CODE 000000007ff37000-000000007ff38000 WB|RT LOADER DATA 000000007ff38000-0000000080000000 WBSigned-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-)cmd/efishell.c +25
-0@@ -442,6 +442,78 @@ static int do_efi_show_images(int argc, char * const argv[])return CMD_RET_SUCCESS ; } +static const char *const efi_mem_type_string[] = { + [EFI_RESERVED_MEMORY_TYPE ] ="RESERVED" , + [EFI_LOADER_CODE ] ="LOADER CODE" , + [EFI_LOADER_DATA ] ="LOADER DATA" , + [EFI_BOOT_SERVICES_CODE ] ="BOOT CODE" , + [EFI_BOOT_SERVICES_DATA ] ="BOOT DATA" , + [EFI_RUNTIME_SERVICES_CODE ] ="RUNTIME CODE" , + [EFI_RUNTIME_SERVICES_DATA ] ="RUNTIME DATA" , + [EFI_CONVENTIONAL_MEMORY ] ="CONVENTIONAL" , + [EFI_UNUSABLE_MEMORY ] ="UNUSABLE MEM" , + [EFI_ACPI_RECLAIM_MEMORY ] ="ACPI RECLAIM MEM" , + [EFI_ACPI_MEMORY_NVS ] ="ACPI NVS" , + [EFI_MMAP_IO ] ="IO" , + [EFI_MMAP_IO_PORT ] ="IO PORT" , + [EFI_PAL_CODE ] ="PAL" , +}; + +#define EFI_MEM_ATTR (attribute, bit, string) \ + if ((attribute) & (bit)) { \ + if (sep) \ + putc('|'); \ + sep = 1; \ + printf(string); \ + } +
cmd/efishell.c static int do_efi_show_images(int argc, char * const argv[]) · line 479
Quoted 10 lines
cmd/efishell.c +10
-0+static int do_efi_show_memmap (int argc,char *const argv[]) +{ +struct efi_mem_desc *map =NULL ; +efi_uintn_t map_size =0 ; +int i, sep; +efi_status_t ret; + + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + map =malloc (map_size);
Where is the free() to this malloc()?
Alex
Quoted 61 lines
cmd/efishell.c +42
-1+if (!map) +return CMD_RET_FAILURE ; + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); + } +if (ret !=EFI_SUCCESS ) +return CMD_RET_FAILURE ; + + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); +if (ret !=EFI_SUCCESS ) +return CMD_RET_FAILURE ; + +printf ("Type Start End Attributes\n" ); +printf ("================ ================ ================ ==========\n" ); +for (i =0 ; i < map_size /sizeof (*map); map++, i++) { + sep =0 ; +printf ("%-16s %016llx-%016llx " , + efi_mem_type_string[map->type], + map->physical_start, + map->physical_start + map->num_pages *EFI_PAGE_SIZE ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_UC ,"UC" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WC ,"WC" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WT ,"WT" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WB ,"WB" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_UCE ,"UCE" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WP ,"WP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RP ,"RP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_XP ,"WP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_NV ,"NV" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_MORE_RELIABLE ,"REL" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RO ,"RO" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RUNTIME ,"RT" ); +putc ('\n' ); + } + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;@@ -826,6 +898,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_show_drivers (argc, argv); else if (!strcmp(command, "images"))return do_efi_show_images (argc, argv); + else if (!strcmp(command, "memmap")) +return do_efi_show_memmap (argc, argv); else return CMD_RET_USAGE; }@@ -853,7 +927,9 @@ static char efishell_help_text[] ="efishell drivers\n" " - show uefi drivers\n" "efishell images\n" -" - show loaded images\n" ; +" - show loaded images\n" +"efishell memmap\n" +" - show uefi memory map\n" ;#endif U_BOOT_CMD(
PATCH v2 8/14 cmd: efishell: add memmap command
Quoted 59 lines · Alexander Graf
Quoted 56 lines · AKASHI Takahiro
"memmap" command prints uefi-specific memory map information. => efi memmap
Type Start End Attributes
================ ================ ================ ==========CONVENTIONAL 0000000040000000-000000007de27000 WB RUNTIME DATA 000000007de27000-000000007de28000 WB|RT RESERVED 000000007de28000-000000007de2a000 WB RUNTIME DATA 000000007de2a000-000000007de2b000 WB|RT RESERVED 000000007de2b000-000000007de2c000 WB RUNTIME DATA 000000007de2c000-000000007de2d000 WB|RT LOADER DATA 000000007de2d000-000000007ff37000 WB RUNTIME CODE 000000007ff37000-000000007ff38000 WB|RT LOADER DATA 000000007ff38000-0000000080000000 WBSigned-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-)cmd/efishell.c +29
-0@@ -442,6 +442,78 @@ static int do_efi_show_images(int argc, char * const argv[])return CMD_RET_SUCCESS ; } +static const char *const efi_mem_type_string[] = { + [EFI_RESERVED_MEMORY_TYPE ] ="RESERVED" , + [EFI_LOADER_CODE ] ="LOADER CODE" , + [EFI_LOADER_DATA ] ="LOADER DATA" , + [EFI_BOOT_SERVICES_CODE ] ="BOOT CODE" , + [EFI_BOOT_SERVICES_DATA ] ="BOOT DATA" , + [EFI_RUNTIME_SERVICES_CODE ] ="RUNTIME CODE" , + [EFI_RUNTIME_SERVICES_DATA ] ="RUNTIME DATA" , + [EFI_CONVENTIONAL_MEMORY ] ="CONVENTIONAL" , + [EFI_UNUSABLE_MEMORY ] ="UNUSABLE MEM" , + [EFI_ACPI_RECLAIM_MEMORY ] ="ACPI RECLAIM MEM" , + [EFI_ACPI_MEMORY_NVS ] ="ACPI NVS" , + [EFI_MMAP_IO ] ="IO" , + [EFI_MMAP_IO_PORT ] ="IO PORT" , + [EFI_PAL_CODE ] ="PAL" , +}; + +#define EFI_MEM_ATTR (attribute, bit, string) \ + if ((attribute) & (bit)) { \ + if (sep) \ + putc('|'); \ + sep = 1; \ + printf(string); \ + } + +static int do_efi_show_memmap (int argc,char *const argv[]) +{ +struct efi_mem_desc *map =NULL ; +efi_uintn_t map_size =0 ;
Quoted 8 lines
cmd/efishell.c static int do_efi_show_images(int argc, char * const argv[]) · line 479
Quoted 6 lines
cmd/efishell.c +6
-0+int i, sep; +efi_status_t ret; + + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); +if (ret ==EFI_BUFFER_TOO_SMALL ) { + map =malloc (map_size);Where is the
free()to thismalloc()?
OK, fix it.
Thanks,
-Takahiro Akashi
Quoted 64 lines
Alex
Quoted 61 lines
cmd/efishell.c +42
-1+if (!map) +return CMD_RET_FAILURE ; + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); + } +if (ret !=EFI_SUCCESS ) +return CMD_RET_FAILURE ; + + ret =efi_get_memory_map (&map_size, map,NULL ,NULL ,NULL ); +if (ret !=EFI_SUCCESS ) +return CMD_RET_FAILURE ; + +printf ("Type Start End Attributes\n" ); +printf ("================ ================ ================ ==========\n" ); +for (i =0 ; i < map_size /sizeof (*map); map++, i++) { + sep =0 ; +printf ("%-16s %016llx-%016llx " , + efi_mem_type_string[map->type], + map->physical_start, + map->physical_start + map->num_pages *EFI_PAGE_SIZE ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_UC ,"UC" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WC ,"WC" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WT ,"WT" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WB ,"WB" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_UCE ,"UCE" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_WP ,"WP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RP ,"RP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_XP ,"WP" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_NV ,"NV" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_MORE_RELIABLE ,"REL" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RO ,"RO" ); +EFI_MEM_ATTR (map->attribute,EFI_MEMORY_RUNTIME ,"RT" ); +putc ('\n' ); + } + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;@@ -826,6 +898,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_show_drivers (argc, argv); else if (!strcmp(command, "images"))return do_efi_show_images (argc, argv); + else if (!strcmp(command, "memmap")) +return do_efi_show_memmap (argc, argv); else return CMD_RET_USAGE; }@@ -853,7 +927,9 @@ static char efishell_help_text[] ="efishell drivers\n" " - show uefi drivers\n" "efishell images\n" -" - show loaded images\n" ; +" - show loaded images\n" +"efishell memmap\n" +" - show uefi memory map\n" ;#endif U_BOOT_CMD(
PATCH v2 9/14 cmd: efishell: add dh command
In reply to AKASHI Takahiro"dh" command prints all the uefi handles used in the system. => efishell dh
(T.B.D.)
0: (protocol info not available)
1: (protocol info not available)
2: (protocol info not available)
3: (protocol info not available)
4: (protocol info not available)
5: (protocol info not available)
6: (protocol info not available)
7: (protocol info not available)
8: (protocol info not available)
9: (protocol info not available)
10: (protocol info not available)
11: (protocol info not available)
12: (protocol info not available)
13: (protocol info not available)
14: (protocol info not available)
15: (protocol info not available)
--- cmd/efishell.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
cmd/efishell.c +32 -1
@@ -514,6 +514,33 @@ static int do_efi_show_memmap(int argc, char * const argv[])return CMD_RET_SUCCESS ; } +static char *efi_get_proto_info (efi_handle_t handle) +{ +return strdup ("(protocol info not available)" ); +} + +static int do_efi_show_handles (int argc,char *const argv[]) +{ +efi_handle_t *handles =NULL , *handle; +char *info; +int i; + + handles =efi_get_handles_by_proto (NULL ); +if (!handles) +return CMD_RET_SUCCESS ; + +for (handle = handles, i =0 ; *handle; handle++, i++) { +/* TODO: depends on protocols */ + info =efi_get_proto_info (*handle); +printf ("%d: %s\n" , i, info ?:"" ); +free (info); + } + +free (handles); + +return CMD_RET_SUCCESS ; +} +static int do_efi_boot_add (int argc,char *const argv[]) {int id;
@@ -900,6 +927,8 @@ static int do_efishell(cmd_tbl_t *cmdtp, int flag,return do_efi_show_images (argc, argv); else if (!strcmp(command, "memmap"))return do_efi_show_memmap (argc, argv); + else if (!strcmp(command, "dh")) +return do_efi_show_handles (argc, argv); else return CMD_RET_USAGE; }
@@ -929,7 +958,9 @@ static char efishell_help_text[] ="efishell images\n" " - show loaded images\n" "efishell memmap\n" -" - show uefi memory map\n" ; +" - show uefi memory map\n" +"efishell dh\n" +" - show uefi handles\n" ;#endif U_BOOT_CMD(
Signature · 1 line
2.19.0
PATCH v2 10/14 cmd: bootefi: carve out fdt parameter handling
In reply to AKASHI TakahiroThe current way how command parameters, particularly "fdt addr," are handled makes it a bit complicated to add a subcommand-specific parameter. So just refactor the code and extract efi_handle_fdt().
This commit is a preparatory change for enhancing bootmgr sub-command.
--- cmd/bootefi.c | 51 +++++++++++++++++++++++++++++++++----------------- cmd/efishell.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)
cmd/bootefi.c +34 -17
@@ -356,6 +356,31 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)return ret; } +int efi_handle_fdt (char *fdt_opt) +{ +unsigned long fdt_addr; +efi_status_t r; + +if (fdt_opt) { + fdt_addr =simple_strtoul (fdt_opt,NULL ,16 ); +if (!fdt_addr && *fdt_opt !='0' ) +return CMD_RET_USAGE ; + +/* Install device tree */ + r =efi_install_fdt (fdt_addr); +if (r !=EFI_SUCCESS ) { +printf ("ERROR: failed to install device tree\n" ); +return CMD_RET_FAILURE ; + } + }else { +/* Remove device tree. EFI_NOT_FOUND can be ignored here */ +efi_install_configuration_table (&efi_guid_fdt,NULL ); +printf ("WARNING: booting without device tree\n" ); + } + +return CMD_RET_SUCCESS ; +} +/** * do_bootefi_exec() - execute EFI binary *
@@ -511,7 +536,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])unsigned long addr;char *saddr;efi_status_t r; -unsigned long fdt_addr;/* Allow unaligned memory access */ allow_unaligned ();
@@ -527,21 +551,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ; -if (argc >2 ) { - fdt_addr =simple_strtoul (argv[2 ],NULL ,16 ); -if (!fdt_addr && *argv[2 ] !='0' ) -return CMD_RET_USAGE ; -/* Install device tree */ - r =efi_install_fdt (fdt_addr); -if (r !=EFI_SUCCESS ) { -printf ("ERROR: failed to install device tree\n" ); -return CMD_RET_FAILURE ; - } - }else { -/* Remove device tree. EFI_NOT_FOUND can be ignored here */ -efi_install_configuration_table (&efi_guid_fdt,NULL ); -printf ("WARNING: booting without device tree\n" ); - }#ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp (argv[1 ],"hello" )) {ulong size = __efi_helloworld_end - __efi_helloworld_begin;
@@ -559,6 +568,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])struct efi_loaded_image_obj *image_obj;struct efi_loaded_image *loaded_image_info; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; +/* Construct a dummy device path. */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)&efi_selftest,
@@ -583,7 +595,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else#endif if (!strcmp (argv[1 ],"bootmgr" )) { -return do_bootefi_bootmgr_exec (); +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); }else { saddr = argv[1 ];
@@ -592,6 +607,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (!addr && *saddr !='0' )return CMD_RET_USAGE ; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; }printf ("## Starting EFI application at %08lx ...\n" , addr);
cmd/efishell.h +1 -0
@@ -3,3 +3,4 @@#include <efi.h> efi_status_t efi_init_obj_list (void ); +int efi_handle_fdt (char *fdt_opt);
Signature · 1 line
2.19.0
PATCH v2 10/14 cmd: bootefi: carve out fdt parameter handling
Quoted 114 lines · AKASHI Takahiro
The current way how command parameters, particularly "fdt addr," are handled makes it a bit complicated to add a subcommand-specific parameter. So just refactor the code and extract
efi_handle_fdt().This commit is a preparatory change for enhancing bootmgr sub-command.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/bootefi.c | 51 +++++++++++++++++++++++++++++++++----------------- cmd/efishell.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)cmd/bootefi.c +34
-17@@ -356,6 +356,31 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)return ret; } +int efi_handle_fdt (char *fdt_opt) +{ +unsigned long fdt_addr; +efi_status_t r; + +if (fdt_opt) { + fdt_addr =simple_strtoul (fdt_opt,NULL ,16 ); +if (!fdt_addr && *fdt_opt !='0' ) +return CMD_RET_USAGE ; + +/* Install device tree */ + r =efi_install_fdt (fdt_addr); +if (r !=EFI_SUCCESS ) { +printf ("ERROR: failed to install device tree\n" ); +return CMD_RET_FAILURE ; + } + }else { +/* Remove device tree. EFI_NOT_FOUND can be ignored here */ +efi_install_configuration_table (&efi_guid_fdt,NULL ); +printf ("WARNING: booting without device tree\n" ); + } + +return CMD_RET_SUCCESS ; +} +/** * do_bootefi_exec() - execute EFI binary * @@ -511,7 +536,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])unsigned long addr;char *saddr;efi_status_t r; -unsigned long fdt_addr;/* Allow unaligned memory access */ allow_unaligned ();@@ -527,21 +551,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ; -if (argc >2 ) { - fdt_addr =simple_strtoul (argv[2 ],NULL ,16 ); -if (!fdt_addr && *argv[2 ] !='0' ) -return CMD_RET_USAGE ; -/* Install device tree */ - r =efi_install_fdt (fdt_addr); -if (r !=EFI_SUCCESS ) { -printf ("ERROR: failed to install device tree\n" ); -return CMD_RET_FAILURE ; - } - }else { -/* Remove device tree. EFI_NOT_FOUND can be ignored here */ -efi_install_configuration_table (&efi_guid_fdt,NULL ); -printf ("WARNING: booting without device tree\n" ); - }#ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp (argv[1 ],"hello" )) {ulong size = __efi_helloworld_end - __efi_helloworld_begin;@@ -559,6 +568,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])struct efi_loaded_image_obj *image_obj;struct efi_loaded_image *loaded_image_info; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; +/* Construct a dummy device path. */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)&efi_selftest,@@ -583,7 +595,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else#endif if (!strcmp (argv[1 ],"bootmgr" )) { -return do_bootefi_bootmgr_exec (); +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); }else { saddr = argv[1 ];@@ -592,6 +607,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (!addr && *saddr !='0' )return CMD_RET_USAGE ; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; }printf ("## Starting EFI application at %08lx ...\n" , addr);cmd/efishell.h +0
-0
cmd/efishell.h line 6
Quoted 4 lines
cmd/efishell.h +1
-0@@ -3,3 +3,4 @@#include <efi.h> efi_status_t efi_init_obj_list (void ); +int efi_handle_fdt (char *fdt_opt);
This should also go into efi_loader.h, as that's the subsystem that exports the function.
Alex
PATCH v2 10/14 cmd: bootefi: carve out fdt parameter handling
Quoted 119 lines · Alexander Graf
Quoted 116 lines · AKASHI Takahiro
The current way how command parameters, particularly "fdt addr," are handled makes it a bit complicated to add a subcommand-specific parameter. So just refactor the code and extract
efi_handle_fdt().This commit is a preparatory change for enhancing bootmgr sub-command.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/bootefi.c | 51 +++++++++++++++++++++++++++++++++----------------- cmd/efishell.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)cmd/bootefi.c +34
-17@@ -356,6 +356,31 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)return ret; } +int efi_handle_fdt (char *fdt_opt) +{ +unsigned long fdt_addr; +efi_status_t r; + +if (fdt_opt) { + fdt_addr =simple_strtoul (fdt_opt,NULL ,16 ); +if (!fdt_addr && *fdt_opt !='0' ) +return CMD_RET_USAGE ; + +/* Install device tree */ + r =efi_install_fdt (fdt_addr); +if (r !=EFI_SUCCESS ) { +printf ("ERROR: failed to install device tree\n" ); +return CMD_RET_FAILURE ; + } + }else { +/* Remove device tree. EFI_NOT_FOUND can be ignored here */ +efi_install_configuration_table (&efi_guid_fdt,NULL ); +printf ("WARNING: booting without device tree\n" ); + } + +return CMD_RET_SUCCESS ; +} +/** * do_bootefi_exec() - execute EFI binary * @@ -511,7 +536,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])unsigned long addr;char *saddr;efi_status_t r; -unsigned long fdt_addr;/* Allow unaligned memory access */ allow_unaligned ();@@ -527,21 +551,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ; -if (argc >2 ) { - fdt_addr =simple_strtoul (argv[2 ],NULL ,16 ); -if (!fdt_addr && *argv[2 ] !='0' ) -return CMD_RET_USAGE ; -/* Install device tree */ - r =efi_install_fdt (fdt_addr); -if (r !=EFI_SUCCESS ) { -printf ("ERROR: failed to install device tree\n" ); -return CMD_RET_FAILURE ; - } - }else { -/* Remove device tree. EFI_NOT_FOUND can be ignored here */ -efi_install_configuration_table (&efi_guid_fdt,NULL ); -printf ("WARNING: booting without device tree\n" ); - }#ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp (argv[1 ],"hello" )) {ulong size = __efi_helloworld_end - __efi_helloworld_begin;@@ -559,6 +568,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])struct efi_loaded_image_obj *image_obj;struct efi_loaded_image *loaded_image_info; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; +/* Construct a dummy device path. */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)&efi_selftest,@@ -583,7 +595,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else#endif if (!strcmp (argv[1 ],"bootmgr" )) { -return do_bootefi_bootmgr_exec (); +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); }else { saddr = argv[1 ];@@ -592,6 +607,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (!addr && *saddr !='0' )return CMD_RET_USAGE ; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; }printf ("## Starting EFI application at %08lx ...\n" , addr);cmd/efishell.h +0
-0@@ -3,3 +3,4 @@#include <efi.h>
Quoted 5 lines
cmd/efishell.h line 6
Quoted 2 lines
cmd/efishell.h +1
-0efi_status_t efi_init_obj_list (void ); +int efi_handle_fdt (char *fdt_opt);This should also go into
efi_loader.h, as that's the subsystem that exports the function.
I hesitate to agree with you here as this function is provided as part of bootefi in the first place. Run command is just a variant of bootefi for efi binary. So it won't be seen as part of efi_loader function.
# In this sense, efishell.h should be renamed to bootefi.h?
Thanks,
-Takahiro Akashi
Quoted 2 lines
Alex
PATCH v2 10/14 cmd: bootefi: carve out fdt parameter handling
Quoted 126 lines · AKASHI Takahiro
Quoted 119 lines · Alexander Graf
Quoted 116 lines · AKASHI Takahiro
The current way how command parameters, particularly "fdt addr," are handled makes it a bit complicated to add a subcommand-specific parameter. So just refactor the code and extract
efi_handle_fdt().This commit is a preparatory change for enhancing bootmgr sub-command.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/bootefi.c | 51 +++++++++++++++++++++++++++++++++----------------- cmd/efishell.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)cmd/bootefi.c +34
-17@@ -356,6 +356,31 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)return ret; } +int efi_handle_fdt (char *fdt_opt) +{ +unsigned long fdt_addr; +efi_status_t r; + +if (fdt_opt) { + fdt_addr =simple_strtoul (fdt_opt,NULL ,16 ); +if (!fdt_addr && *fdt_opt !='0' ) +return CMD_RET_USAGE ; + +/* Install device tree */ + r =efi_install_fdt (fdt_addr); +if (r !=EFI_SUCCESS ) { +printf ("ERROR: failed to install device tree\n" ); +return CMD_RET_FAILURE ; + } + }else { +/* Remove device tree. EFI_NOT_FOUND can be ignored here */ +efi_install_configuration_table (&efi_guid_fdt,NULL ); +printf ("WARNING: booting without device tree\n" ); + } + +return CMD_RET_SUCCESS ; +} +/** * do_bootefi_exec() - execute EFI binary * @@ -511,7 +536,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])unsigned long addr;char *saddr;efi_status_t r; -unsigned long fdt_addr;/* Allow unaligned memory access */ allow_unaligned ();@@ -527,21 +551,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ; -if (argc >2 ) { - fdt_addr =simple_strtoul (argv[2 ],NULL ,16 ); -if (!fdt_addr && *argv[2 ] !='0' ) -return CMD_RET_USAGE ; -/* Install device tree */ - r =efi_install_fdt (fdt_addr); -if (r !=EFI_SUCCESS ) { -printf ("ERROR: failed to install device tree\n" ); -return CMD_RET_FAILURE ; - } - }else { -/* Remove device tree. EFI_NOT_FOUND can be ignored here */ -efi_install_configuration_table (&efi_guid_fdt,NULL ); -printf ("WARNING: booting without device tree\n" ); - }#ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp (argv[1 ],"hello" )) {ulong size = __efi_helloworld_end - __efi_helloworld_begin;@@ -559,6 +568,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])struct efi_loaded_image_obj *image_obj;struct efi_loaded_image *loaded_image_info; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; +/* Construct a dummy device path. */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)&efi_selftest,@@ -583,7 +595,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else#endif if (!strcmp (argv[1 ],"bootmgr" )) { -return do_bootefi_bootmgr_exec (); +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); }else { saddr = argv[1 ];@@ -592,6 +607,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (!addr && *saddr !='0' )return CMD_RET_USAGE ; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; }printf ("## Starting EFI application at %08lx ...\n" , addr);cmd/efishell.h +0
-0@@ -3,3 +3,4 @@#include <efi.h> Quoted 5 lines
cmd/efishell.h line 6
Quoted 2 lines
cmd/efishell.h +1
-0efi_status_t efi_init_obj_list (void ); +int efi_handle_fdt (char *fdt_opt);This should also go into
efi_loader.h, as that's the subsystem that exports the function.
Quoted 5 lines
I hesitate to agree with you here as this function is provided as part of bootefi in the first place. Run command is just a variant of bootefi for efi binary. So it won't be seen as part of
efi_loaderfunction.# In this sense,
efishell.hshould be renamed tobootefi.h?
Feel free to introduce a bootefi.h that contains all exports from bootefi.c, yes :).
Alex
PATCH v2 10/14 cmd: bootefi: carve out fdt parameter handling
Quoted 129 lines · Alexander Graf
Quoted 126 lines · AKASHI Takahiro
Quoted 124 lines · Alexander Graf
Quoted 114 lines · AKASHI Takahiro
The current way how command parameters, particularly "fdt addr," are handled makes it a bit complicated to add a subcommand-specific parameter. So just refactor the code and extract
efi_handle_fdt().This commit is a preparatory change for enhancing bootmgr sub-command.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/bootefi.c | 51 +++++++++++++++++++++++++++++++++----------------- cmd/efishell.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)cmd/bootefi.c +34
-17@@ -356,6 +356,31 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)return ret; } +int efi_handle_fdt (char *fdt_opt) +{ +unsigned long fdt_addr; +efi_status_t r; + +if (fdt_opt) { + fdt_addr =simple_strtoul (fdt_opt,NULL ,16 ); +if (!fdt_addr && *fdt_opt !='0' ) +return CMD_RET_USAGE ; + +/* Install device tree */ + r =efi_install_fdt (fdt_addr); +if (r !=EFI_SUCCESS ) { +printf ("ERROR: failed to install device tree\n" ); +return CMD_RET_FAILURE ; + } + }else { +/* Remove device tree. EFI_NOT_FOUND can be ignored here */ +efi_install_configuration_table (&efi_guid_fdt,NULL ); +printf ("WARNING: booting without device tree\n" ); + } + +return CMD_RET_SUCCESS ; +} +/** * do_bootefi_exec() - execute EFI binary * @@ -511,7 +536,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])unsigned long addr;char *saddr;efi_status_t r; -unsigned long fdt_addr;/* Allow unaligned memory access */ allow_unaligned ();@@ -527,21 +551,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ; -if (argc >2 ) { - fdt_addr =simple_strtoul (argv[2 ],NULL ,16 ); -if (!fdt_addr && *argv[2 ] !='0' ) -return CMD_RET_USAGE ; -/* Install device tree */ - r =efi_install_fdt (fdt_addr); -if (r !=EFI_SUCCESS ) { -printf ("ERROR: failed to install device tree\n" ); -return CMD_RET_FAILURE ; - } - }else { -/* Remove device tree. EFI_NOT_FOUND can be ignored here */ -efi_install_configuration_table (&efi_guid_fdt,NULL ); -printf ("WARNING: booting without device tree\n" ); - }#ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp (argv[1 ],"hello" )) {ulong size = __efi_helloworld_end - __efi_helloworld_begin;@@ -559,6 +568,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])struct efi_loaded_image_obj *image_obj;struct efi_loaded_image *loaded_image_info; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; +/* Construct a dummy device path. */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)&efi_selftest,@@ -583,7 +595,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else#endif if (!strcmp (argv[1 ],"bootmgr" )) { -return do_bootefi_bootmgr_exec (); +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); }else { saddr = argv[1 ];@@ -592,6 +607,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (!addr && *saddr !='0' )return CMD_RET_USAGE ; +if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) +return CMD_RET_FAILURE ; }printf ("## Starting EFI application at %08lx ...\n" , addr);cmd/efishell.h +0
-0cmd/efishell.h line 6
Quoted 4 lines
cmd/efishell.h +1
-0@@ -3,3 +3,4 @@#include <efi.h> efi_status_t efi_init_obj_list (void ); +int efi_handle_fdt (char *fdt_opt);This should also go into
efi_loader.h, as that's the subsystem that exports the function.
Quoted 8 lines
Quoted 5 lines
I hesitate to agree with you here as this function is provided as part of bootefi in the first place. Run command is just a variant of bootefi for efi binary. So it won't be seen as part of
efi_loaderfunction.# In this sense,
efishell.hshould be renamed tobootefi.h?Feel free to introduce a
bootefi.hthat contains all exports frombootefi.c, yes :).
OK, but due to your comment on a new do_bootefi_run() function, we may no longer need to export efi_handle_fdt() (at least for now). That's good.
-Takahiro Akashi
Quoted 2 lines
Alex
PATCH v2 11/14 cmd: bootefi: run an EFI application of a specific load option
In reply to AKASHI TakahiroWith this patch applied, we will be able to selectively execute an EFI application by specifying a load option, say "1" for Boot0001, "2" for Boot0002 and so on.
=> bootefi bootmgr <fdt addr> 1, or
bootefi bootmgr - 1
Please note that BootXXXX need not be included in "BootOrder".
--- cmd/bootefi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
cmd/bootefi.c +18 -6
@@ -509,13 +509,13 @@ exit:return ret; } -static int do_bootefi_bootmgr_exec (void ) +static int do_bootefi_bootmgr_exec (int boot_id) {struct efi_device_path *device_path, *file_path;void *addr;efi_status_t r; - addr =efi_bootmgr_load (&device_path, &file_path); + addr =efi_bootmgr_load (boot_id, &device_path, &file_path);if (!addr)return 1 ;
@@ -595,8 +595,20 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else#endif if (!strcmp (argv[1 ],"bootmgr" )) { -if (efi_handle_fdt (argc >2 ? argv[2 ] :NULL )) -return CMD_RET_FAILURE ; +char *endp; +int boot_id =-1 ; + +if (argc >2 ) +if (efi_handle_fdt ((argv[2 ][0 ] =='-' ) ? +NULL : argv[2 ])) +return CMD_RET_FAILURE ; + +if (argc >3 ) { + boot_id = (int )simple_strtoul (argv[3 ], &endp,0 ); +if ((argv[3 ] +strlen (argv[3 ]) != endp) || + boot_id >0xffff ) +return CMD_RET_USAGE ; + }return do_bootefi_bootmgr_exec (boot_id); }else {
@@ -639,7 +651,7 @@ static char bootefi_help_text[] =" Use environment variable efi_selftest to select a single test.\n" " Use 'setenv efi_selftest list' to enumerate all tests.\n"#endif -"bootefi bootmgr [fdt addr]\n" +"bootefi bootmgr [<fdt addr>|'-' [<boot id>]]\n" " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" "\n" " If specified, the device tree located at <fdt address> gets\n"
@@ -647,7 +659,7 @@ static char bootefi_help_text[] =#endif U_BOOT_CMD ( - bootefi,3 ,0 , do_bootefi, + bootefi,5 ,0 , do_bootefi,"Boots an EFI payload from memory" , bootefi_help_text );
Signature · 1 line
2.19.0
PATCH v2 12/14 cmd: run: add "-e" option to run an EFI application
In reply to AKASHI Takahiro"run -e" allows for executing EFI application with a specific "BootXXXX" variable. If no "BootXXXX" is specified or "BootOrder" is specified, it tries to run an EFI application specified in the order of "bootOrder."
--- cmd/bootefi.c | 2 +- cmd/nvedit.c | 5 +++++ common/cli.c | 30 ++++++++++++++++++++++++++++++ include/command.h | 3 +++ 4 files changed, 39 insertions(+), 1 deletion(-)
cmd/bootefi.c +1 -1
@@ -509,7 +509,7 @@ exit:return ret; } -static int do_bootefi_bootmgr_exec (int boot_id) +int do_bootefi_bootmgr_exec (int boot_id) {struct efi_device_path *device_path, *file_path;void *addr;
cmd/nvedit.c +5 -0
@@ -1343,8 +1343,13 @@ U_BOOT_CMD(U_BOOT_CMD_COMPLETE ( run,CONFIG_SYS_MAXARGS ,1 , do_run,"run commands in an environment variable" , +#if defined(CONFIG_CMD_BOOTEFI) +"var -e [BootXXXX]\n" +" - load and run UEFI app based on 'BootXXXX' UEFI variable" , +#else"var [...]\n" " - run the commands in the environment variable(s) 'var'" , +#endif var_complete );#endif
common/cli.c +30 -0
@@ -14,6 +14,7 @@#include <console.h> #include <fdtdec.h> #include <malloc.h> +#include "../cmd/efishell.h" DECLARE_GLOBAL_DATA_PTR ;
@@ -125,6 +126,35 @@ int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ; +#ifdef CONFIG_CMD_BOOTEFI +if (!strcmp (argv[1 ],"-e" )) { +int boot_id =-1 ; +char *endp; + +if (argc ==3 ) { +if (!strcmp (argv[2 ],"BootOrder" )) { +/* boot_id = -1 */ ; + }else if (!strncmp (argv[2 ],"Boot" ,4 )) { + boot_id = (int )simple_strtoul (&argv[2 ][4 ], + &endp,0 ); +if ((argv[2 ] +strlen (argv[2 ]) != endp) || + boot_id >0xffff ) +return CMD_RET_USAGE ; + }else { +return CMD_RET_USAGE ; + } + } + +if (efi_init_obj_list ()) +return CMD_RET_FAILURE ; + +if (efi_handle_fdt (NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); + } +#endif +for (i =1 ; i < argc; ++i) {char *arg;
include/command.h +3 -0
@@ -48,6 +48,9 @@ typedef struct cmd_tbl_s cmd_tbl_t;#if defined(CONFIG_CMD_RUN )extern int do_run (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]);#endif +#if defined(CONFIG_CMD_BOOTEFI ) +int do_bootefi_bootmgr_exec (int boot_id); +#endif /* common/command.c */ int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int
Signature · 1 line
2.19.0
PATCH v2 12/14 cmd: run: add "-e" option to run an EFI application
Quoted 48 lines · AKASHI Takahiro
"run -e" allows for executing EFI application with a specific "BootXXXX" variable. If no "BootXXXX" is specified or "BootOrder" is specified, it tries to run an EFI application specified in the order of "bootOrder."
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/bootefi.c | 2 +- cmd/nvedit.c | 5 +++++ common/cli.c | 30 ++++++++++++++++++++++++++++++ include/command.h | 3 +++ 4 files changed, 39 insertions(+), 1 deletion(-)cmd/bootefi.c +1
-1@@ -509,7 +509,7 @@ exit:return ret; } -static int do_bootefi_bootmgr_exec (int boot_id) +int do_bootefi_bootmgr_exec (int boot_id) {struct efi_device_path *device_path, *file_path;void *addr;cmd/nvedit.c +5
-0@@ -1343,8 +1343,13 @@ U_BOOT_CMD(U_BOOT_CMD_COMPLETE ( run,CONFIG_SYS_MAXARGS ,1 , do_run,"run commands in an environment variable" , +#if defined(CONFIG_CMD_BOOTEFI) +"var -e [BootXXXX]\n" +" - load and run UEFI app based on 'BootXXXX' UEFI variable" , +#else"var [...]\n" " - run the commands in the environment variable(s) 'var'" , +#endif var_complete );#endif common/cli.c +0
-0
common/cli.c line 17
Quoted 4 lines
common/cli.c +1
-0@@ -14,6 +14,7 @@#include <console.h> #include <fdtdec.h> #include <malloc.h> +#include "../cmd/efishell.h"
I guess this already shows that something is going wrong ;).
Please move the depending functions into lib/efi_loader. That way we can have the efishell command be optional, but keep this logic around regardless.
Quoted 5 lines
common/cli.c +0
-0DECLARE_GLOBAL_DATA_PTR ;@@ -125,6 +126,35 @@ int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )
common/cli.c int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 136
Quoted 10 lines
common/cli.c +8
-0return CMD_RET_USAGE ; +#ifdef CONFIG_CMD_BOOTEFI +if (!strcmp (argv[1 ],"-e" )) { +int boot_id =-1 ; +char *endp; + +if (argc ==3 ) { +if (!strcmp (argv[2 ],"BootOrder" )) { +/* boot_id = -1 */ ;
Just write that in code. The compiler will optimize it out.
Quoted 29 lines
common/cli.c +21
-0+ } else if (!strncmp(argv[2], "Boot", 4)) { + boot_id = (int )simple_strtoul (&argv[2 ][4 ], + &endp,0 ); +if ((argv[2 ] +strlen (argv[2 ]) != endp) || + boot_id >0xffff ) +return CMD_RET_USAGE ; + }else { +return CMD_RET_USAGE ; + } + } + +if (efi_init_obj_list ()) +return CMD_RET_FAILURE ; + +if (efi_handle_fdt (NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); + } +#endif +for (i =1 ; i < argc; ++i) {char *arg;include/command.h +0
-0
include/command.h typedef struct cmd_tbl_s cmd_tbl_t; · line 53
Quoted 6 lines
include/command.h +3
-0@@ -48,6 +48,9 @@ typedef struct cmd_tbl_s cmd_tbl_t;#if defined(CONFIG_CMD_RUN )extern int do_run (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]);#endif +#if defined(CONFIG_CMD_BOOTEFI ) +int do_bootefi_bootmgr_exec (int boot_id); +#endif
This needs to be in efi_loader.h which then needs to get included from cli.c.
Alex
PATCH v2 12/14 cmd: run: add "-e" option to run an EFI application
Quoted 49 lines · Alexander Graf
Quoted 46 lines · AKASHI Takahiro
"run -e" allows for executing EFI application with a specific "BootXXXX" variable. If no "BootXXXX" is specified or "BootOrder" is specified, it tries to run an EFI application specified in the order of "bootOrder."
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/bootefi.c | 2 +- cmd/nvedit.c | 5 +++++ common/cli.c | 30 ++++++++++++++++++++++++++++++ include/command.h | 3 +++ 4 files changed, 39 insertions(+), 1 deletion(-)cmd/bootefi.c +1
-1@@ -509,7 +509,7 @@ exit:return ret; } -static int do_bootefi_bootmgr_exec (int boot_id) +int do_bootefi_bootmgr_exec (int boot_id) {struct efi_device_path *device_path, *file_path;void *addr;cmd/nvedit.c +5
-0@@ -1343,8 +1343,13 @@ U_BOOT_CMD(U_BOOT_CMD_COMPLETE ( run,CONFIG_SYS_MAXARGS ,1 , do_run,"run commands in an environment variable" , +#if defined(CONFIG_CMD_BOOTEFI) +"var -e [BootXXXX]\n" +" - load and run UEFI app based on 'BootXXXX' UEFI variable" , +#else"var [...]\n" " - run the commands in the environment variable(s) 'var'" , +#endif var_complete );#endif common/cli.c +0
-1--- a/common/cli.c
Quoted 8 lines
common/cli.c line 17
Quoted 6 lines
+++
b/common/cli.ccommon/cli.c +1
-0@@ -14,6 +14,7 @@#include <console.h> #include <fdtdec.h> #include <malloc.h> +#include "../cmd/efishell.h" I guess this already shows that something is going wrong ;).
efishell.h here is included solely for efi_init_obj_list() definition and so
Quoted 3 lines
Please move the depending functions into
lib/efi_loader. That way we can have the efishell command be optional, but keep this logic around regardless.
I can assume that you agree to this function being moved to efi_setup.c.
Quoted 7 lines
Quoted 7 lines
common/cli.c +0
-0DECLARE_GLOBAL_DATA_PTR ;@@ -125,6 +126,35 @@ int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])if (argc <2 )return CMD_RET_USAGE ;
Quoted 10 lines
common/cli.c int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 136
Quoted 8 lines
common/cli.c +8
-0+#ifdef CONFIG_CMD_BOOTEFI +if (!strcmp (argv[1 ],"-e" )) { +int boot_id =-1 ; +char *endp; + +if (argc ==3 ) { +if (!strcmp (argv[2 ],"BootOrder" )) { +/* boot_id = -1 */ ;Just write that in code. The compiler will optimize it out.
OK.
Quoted 24 lines
Quoted 24 lines
common/cli.c +21
-0+ } else if (!strncmp(argv[2], "Boot", 4)) { + boot_id = (int )simple_strtoul (&argv[2 ][4 ], + &endp,0 ); +if ((argv[2 ] +strlen (argv[2 ]) != endp) || + boot_id >0xffff ) +return CMD_RET_USAGE ; + }else { +return CMD_RET_USAGE ; + } + } + +if (efi_init_obj_list ()) +return CMD_RET_FAILURE ; + +if (efi_handle_fdt (NULL )) +return CMD_RET_FAILURE ; + +return do_bootefi_bootmgr_exec (boot_id); + } +#endif +for (i =1 ; i < argc; ++i) {char *arg;
Quoted 14 lines
include/command.h typedef struct cmd_tbl_s cmd_tbl_t; · line 53
Quoted 11 lines
include/command.h +3
-0@@ -48,6 +48,9 @@ typedef struct cmd_tbl_s cmd_tbl_t;#if defined(CONFIG_CMD_RUN )extern int do_run (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]);#endif +#if defined(CONFIG_CMD_BOOTEFI ) +int do_bootefi_bootmgr_exec (int boot_id); +#endif This needs to be in
efi_loader.hwhich then needs to get included fromcli.c.
After your comment above, you expect that do_bootefi_bootmgr_exec(), hence do_bootefi_exec() (and efi_handle_fdt()?) as well, be also moved to lib/efi_loader/(efi_bootmgr.c)?
Thanks,
-Takahiro Akashi
Quoted 2 lines
Alex
PATCH v2 13/14 cmd: efishell: export uefi variable helper functions
In reply to AKASHI TakahiroThose function will be used for integration with 'env' command so as to handle uefi variables.
--- cmd/efishell.c | 4 ++-- include/command.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)
cmd/efishell.c +2 -2
@@ -68,7 +68,7 @@ static void dump_var_data(char *data, unsigned long len)* * efi_$guid_$varname = {attributes}(type)value */ -static int do_efi_dump_var (int argc,char *const argv[]) +int do_efi_dump_var (int argc,char *const argv[]) {char regex[256 ];char *const regexlist[] = {regex};
@@ -228,7 +228,7 @@ out:return 0 ; } -static int do_efi_set_var (int argc,char *const argv[]) +int do_efi_set_var (int argc,char *const argv[]) {char *var_name, *value =NULL ;unsigned long size =0 ;
include/command.h +2 -0
@@ -50,6 +50,8 @@ extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);#endif #if defined(CONFIG_CMD_BOOTEFI )int do_bootefi_bootmgr_exec (int boot_id); +int do_efi_dump_var (int argc,char *const argv[]); +int do_efi_set_var (int argc,char *const argv[]);#endif /* common/command.c */
Signature · 1 line
2.19.0
PATCH v2 13/14 cmd: efishell: export uefi variable helper functions
Quoted 36 lines · AKASHI Takahiro
Those function will be used for integration with 'env' command so as to handle uefi variables.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 4 ++-- include/command.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)cmd/efishell.c +2
-2@@ -68,7 +68,7 @@ static void dump_var_data(char *data, unsigned long len)* * efi_$guid_$varname = {attributes}(type)value */ -static int do_efi_dump_var (int argc,char *const argv[]) +int do_efi_dump_var (int argc,char *const argv[]) {char regex[256 ];char *const regexlist[] = {regex};@@ -228,7 +228,7 @@ out:return 0 ; } -static int do_efi_set_var (int argc,char *const argv[]) +int do_efi_set_var (int argc,char *const argv[]) {char *var_name, *value =NULL ;unsigned long size =0 ;include/command.h +0
-0
include/command.h extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); · line 54
Quoted 5 lines
include/command.h +2
-0@@ -50,6 +50,8 @@ extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);#endif #if defined(CONFIG_CMD_BOOTEFI )int do_bootefi_bootmgr_exec (int boot_id); +int do_efi_dump_var (int argc,char *const argv[]); +int do_efi_set_var (int argc,char *const argv[]);
I guess you're seeing a pattern to my comments by now. This needs to go into efi_loader.h. The respective functions need to go into lib/efi_loader.
Alex
PATCH v2 13/14 cmd: efishell: export uefi variable helper functions
Quoted 38 lines · Alexander Graf
Quoted 35 lines · AKASHI Takahiro
Those function will be used for integration with 'env' command so as to handle uefi variables.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 4 ++-- include/command.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)cmd/efishell.c +2
-2@@ -68,7 +68,7 @@ static void dump_var_data(char *data, unsigned long len)* * efi_$guid_$varname = {attributes}(type)value */ -static int do_efi_dump_var (int argc,char *const argv[]) +int do_efi_dump_var (int argc,char *const argv[]) {char regex[256 ];char *const regexlist[] = {regex};@@ -228,7 +228,7 @@ out:return 0 ; } -static int do_efi_set_var (int argc,char *const argv[]) +int do_efi_set_var (int argc,char *const argv[]) {char *var_name, *value =NULL ;unsigned long size =0 ;include/command.h +0
-0
Quoted 8 lines
include/command.h extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); · line 54
Quoted 6 lines
include/command.h +2
-0@@ -50,6 +50,8 @@ extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);#endif #if defined(CONFIG_CMD_BOOTEFI )int do_bootefi_bootmgr_exec (int boot_id); +int do_efi_dump_var (int argc,char *const argv[]); +int do_efi_set_var (int argc,char *const argv[]);I guess you're seeing a pattern to my comments by now.
Definitely, but
Quoted 2 lines
This needs to go
intoefi_loader.h. The respective functions need to go intolib/efi_loader.
Those two functions are dedicated for command interfaces, and in my opinion, it is hard for them to be seen as part of efi_loader functionality.
Thanks,
-Takahiro Akashi
Quoted 3 lines
Alex
PATCH v2 13/14 cmd: efishell: export uefi variable helper functions
Quoted 48 lines · AKASHI Takahiro
Quoted 38 lines · Alexander Graf
Quoted 35 lines · AKASHI Takahiro
Those function will be used for integration with 'env' command so as to handle uefi variables.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 4 ++-- include/command.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)cmd/efishell.c +2
-2@@ -68,7 +68,7 @@ static void dump_var_data(char *data, unsigned long len)* * efi_$guid_$varname = {attributes}(type)value */ -static int do_efi_dump_var (int argc,char *const argv[]) +int do_efi_dump_var (int argc,char *const argv[]) {char regex[256 ];char *const regexlist[] = {regex};@@ -228,7 +228,7 @@ out:return 0 ; } -static int do_efi_set_var (int argc,char *const argv[]) +int do_efi_set_var (int argc,char *const argv[]) {char *var_name, *value =NULL ;unsigned long size =0 ;include/command.h +0
-0Quoted 8 lines
include/command.h extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); · line 54
Quoted 6 lines
include/command.h +2
-0@@ -50,6 +50,8 @@ extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);#endif #if defined(CONFIG_CMD_BOOTEFI )int do_bootefi_bootmgr_exec (int boot_id); +int do_efi_dump_var (int argc,char *const argv[]); +int do_efi_set_var (int argc,char *const argv[]);I guess you're seeing a pattern to my comments by now.
Quoted 7 lines
Definitely, but
Quoted 2 lines
This needs to go
intoefi_loader.h. The respective functions need to go intolib/efi_loader.Those two functions are dedicated for command interfaces, and in my opinion, it is hard for them to be seen as part of
efi_loaderfunctionality.
Same comment here then :). Feel free to introduce a new header file for bootefi bits, but I'm not a big fan of a giant command.h that just exposes all possible command handlers in the world.
Alex
PATCH v2 13/14 cmd: efishell: export uefi variable helper functions
Quoted 56 lines · Alexander Graf
Quoted 53 lines · AKASHI Takahiro
Quoted 38 lines · Alexander Graf
Quoted 35 lines · AKASHI Takahiro
Those function will be used for integration with 'env' command so as to handle uefi variables.
Signed-off-by AKASHI Takahiro <[email protected]>--- cmd/efishell.c | 4 ++-- include/command.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)cmd/efishell.c +2
-2@@ -68,7 +68,7 @@ static void dump_var_data(char *data, unsigned long len)* * efi_$guid_$varname = {attributes}(type)value */ -static int do_efi_dump_var (int argc,char *const argv[]) +int do_efi_dump_var (int argc,char *const argv[]) {char regex[256 ];char *const regexlist[] = {regex};@@ -228,7 +228,7 @@ out:return 0 ; } -static int do_efi_set_var (int argc,char *const argv[]) +int do_efi_set_var (int argc,char *const argv[]) {char *var_name, *value =NULL ;unsigned long size =0 ;include/command.h +0
-0Quoted 8 lines
include/command.h extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); · line 54
Quoted 6 lines
include/command.h +2
-0@@ -50,6 +50,8 @@ extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);#endif #if defined(CONFIG_CMD_BOOTEFI )int do_bootefi_bootmgr_exec (int boot_id); +int do_efi_dump_var (int argc,char *const argv[]); +int do_efi_set_var (int argc,char *const argv[]);I guess you're seeing a pattern to my comments by now.
Definitely, but
Quoted 2 lines
This needs to go
intoefi_loader.h. The respective functions need to go intolib/efi_loader.
Quoted 6 lines
Quoted 2 lines
Those two functions are dedicated for command interfaces, and in my opinion, it is hard for them to be seen as part of
efi_loaderfunctionality.Same comment here then :). Feel free to introduce a new header file for bootefi bits, but I'm not a big fan of a giant
command.hthat just exposes all possible command handlers in the world.
I've assumed that all the do_xxx() stuff should go into command.h. I will leave them in command.h for now.
-Takahiro Akashi
Quoted 2 lines
Alex
PATCH v2 14/14 cmd: env: add "-e" option for handling UEFI variables
In reply to AKASHI Takahiro"env [print|set] -e" allows for handling uefi variables without knowing details about mapping to corresponding u-boot variables.
--- cmd/nvedit.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-)
cmd/nvedit.c +57 -1
@@ -36,6 +36,7 @@#include <linux/stddef.h> #include <asm/byteorder.h> #include <asm/io.h> +#include "efishell.h" DECLARE_GLOBAL_DATA_PTR ;
@@ -119,6 +120,25 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,int rcode =0 ;int env_flag =H_HIDE_DOT ; +#if defined(CONFIG_CMD_BOOTEFI ) +if (argc >1 && argv[1 ][0 ] =='-' && argv[1 ][1 ] =='e' ) { +efi_status_t r; + + argc--; + argv++; + +/* Initialize EFI drivers */ + r =efi_init_obj_list (); +if (r !=EFI_SUCCESS ) { +printf ("Error: Cannot set up EFI drivers, r = %lu\n" , + r & ~EFI_ERROR_MASK ); +return CMD_RET_FAILURE ; + } + +return do_efi_dump_var (argc, argv); + } +#endif +if (argc >1 && argv[1 ][0 ] =='-' && argv[1 ][1 ] =='a' ) { argc--; argv++;
@@ -216,6 +236,26 @@ static int _do_env_set(int flag, int argc, char * const argv[], int env_flag)ENTRY e, *ep;debug ("Initial value for argc=%d\n" , argc); + +#if defined(CONFIG_CMD_BOOTEFI ) +if (argc >1 && argv[1 ][0 ] =='-' && argv[1 ][1 ] =='e' ) { +efi_status_t r; + + argc--; + argv++; + +/* Initialize EFI drivers */ + r =efi_init_obj_list (); +if (r !=EFI_SUCCESS ) { +printf ("Error: Cannot set up EFI drivers, r = %lu\n" , + r & ~EFI_ERROR_MASK ); +return CMD_RET_FAILURE ; + } + +return do_efi_set_var (argc, argv); + } +#endif +while (argc >1 && **(argv +1 ) =='-' ) {char *arg = *++argv;
@@ -1262,15 +1302,23 @@ static char env_help_text[] =#if defined(CONFIG_CMD_IMPORTENV ) "env import [-d] [-t [-r] | -b | -c] addr [size] [var ...] - import environment\n"#endif +#if defined(CONFIG_CMD_BOOTEFI ) +"env print [-a | -e [name] | name ...] - print environment\n" +#else "env print [-a | name ...] - print environment\n" +#endif #if defined(CONFIG_CMD_RUN ) "env run var [...] - run commands in an environment variable\n"#endif #if defined(CONFIG_CMD_SAVEENV ) && !defined(CONFIG_ENV_IS_NOWHERE ) "env save - save environment\n"#endif +#if defined(CONFIG_CMD_BOOTEFI ) +"env set [-e | -f] name [arg ...]\n" ; +#else "env set [-f] name [arg ...]\n" ;#endif +#endif U_BOOT_CMD( env, CONFIG_SYS_MAXARGS, 1, do_env,
@@ -1295,6 +1343,10 @@ U_BOOT_CMD_COMPLETE( printenv, CONFIG_SYS_MAXARGS, 1, do_env_print, "print environment variables", "[-a]\n - print [all] values of all environment variables\n" +#if defined(CONFIG_CMD_BOOTEFI ) +"printenv -e [<name>]\n" + " - print UEFI variable 'name' or all the variables\n" +#endif "printenv name ...\n" " - print value of environment variable 'name'" , var_complete
@@ -1322,7 +1374,11 @@ U_BOOT_CMD_COMPLETE(U_BOOT_CMD_COMPLETE ( setenv,CONFIG_SYS_MAXARGS ,0 , do_env_set,"set environment variables" , - "[-f] name value ...\n" +#if defined(CONFIG_CMD_BOOTEFI) + "-e <name> [<value>]\n" + " - set UEFI variable 'name' to 'value' ...'\n" +#endif +"setenv [-f] name value ...\n" " - [forcibly] set environment variable 'name' to 'value ...'\n" "setenv [-f] name\n" " - [forcibly] delete environment variable 'name'",
Signature · 1 line
2.19.0