[U-Boot] [PATCH v3 00/21] efi: Enable basic sandbox support for EFI loader

A limitation of the EFI loader at present is that it does not build with sandbox. This makes it hard to write tests, since sandbox is used for most testing in U-Boot.
This series enables the EFI loader feature. It allows sandbox to build and run a trivial function which calls the EFI API to output a message.
This series is at u-boot-dm/efi-working
Changes in v3: - Add new patch to init the 'rows' and 'cols' variables - Return error value of efi_allocate_pages() - Update function comment for write_smbios_table() - Add comments on aligment - Avoid adding a new call to efi_init_obj_list() - Fix spelling of initalized - Drop incorrect map_sysmem() in map_sysmem() - Init the 'rows' and 'cols' vars to avoid a compiler error (gcc 4.8.4) - Add new patch to split out test init/uninit into functions - Rebase to master - Add new patch to reorder code in do_bootefi_exec() - Add patch to create a function to set up for running EFI code - Add new patch to rename bootefi_test_finish() to bootefi_run_finish()
Changes in v2: - Update return type of efi_smbios_register() to efi_status_t - Use return value of efi_install_configuration_table - Change return type of efi_init_obj_list() to efi_status_t - Convert #ifdef CONFIG_GENERATE_SMBIOS_TABLE to if() - Update commit message to dropping libfdt_env.h - Update to use mapmem instead of a cast - Rebase to master
Simon Glass (21): efi: Init the 'rows' and 'cols' variables efi: Update efi_smbios_register() to return error code efi: Move the init check inside efi_init_obj_list() efi: Add error checking for efi_init_obj_list() efi: Add a TODO to efi_init_obj_list() efi: Correct header order in efi_memory efi: sandbox: Adjust memory usage for sandbox sandbox: smbios: Update to support sandbox sandbox: Add a setjmp() implementation efi: sandbox: Add required linker sections efi: sandbox: Add distroboot support Define board_quiesce_devices() in a shared location Add a comment for board_quiesce_devices() efi: sandbox: Add relocation constants efi: Add a comment about duplicated ELF constants efi: sandbox: Enable EFI loader builder for sandbox efi: Split out test init/uninit into functions efi: sandbox: Add a simple 'bootefi test' command efi: Reorder code in do_bootefi_exec() efi: Create a function to set up for running EFI code efi: Rename bootefi_test_finish() to bootefi_run_finish()
arch/arm/include/asm/u-boot-arm.h | 1 - arch/sandbox/cpu/cpu.c | 13 ++ arch/sandbox/cpu/os.c | 17 +++ arch/sandbox/cpu/u-boot.lds | 29 +++++ arch/sandbox/include/asm/setjmp.h | 21 ++++ arch/sandbox/lib/Makefile | 2 +- arch/sandbox/lib/sections.c | 12 ++ arch/x86/include/asm/u-boot-x86.h | 1 - arch/x86/lib/bootm.c | 4 - cmd/bootefi.c | 203 +++++++++++++++++++----------- common/bootm.c | 4 + include/bootm.h | 8 ++ include/config_distro_bootcmd.h | 2 +- include/efi_loader.h | 12 +- include/os.h | 21 ++++ include/smbios.h | 5 +- lib/efi_loader/Kconfig | 12 +- lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_console.c | 2 +- lib/efi_loader/efi_memory.c | 36 +++--- lib/efi_loader/efi_runtime.c | 7 ++ lib/efi_loader/efi_smbios.c | 18 ++- lib/efi_loader/efi_test.c | 17 +++ lib/smbios.c | 32 +++-- 24 files changed, 367 insertions(+), 113 deletions(-) create mode 100644 arch/sandbox/include/asm/setjmp.h create mode 100644 arch/sandbox/lib/sections.c create mode 100644 lib/efi_loader/efi_test.c

The current code causes a compiler error on gcc 4.8.4 as used by sandbox on Ubuntu 14.04, which is fairly recent. Init these variables to fix the problem.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add new patch to init the 'rows' and 'cols' variables
Changes in v2: None
lib/efi_loader/efi_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 28d63635ec..971e36da48 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -242,7 +242,7 @@ static efi_status_t EFIAPI efi_cout_query_mode(
if (!console_size_queried) { const char *stdout_name = env_get("stdout"); - int rows, cols; + int rows = 0, cols = 0;
console_size_queried = true;

On 02/19/2018 04:48 PM, Simon Glass wrote:
The current code causes a compiler error on gcc 4.8.4 as used by sandbox
gcc 4 is legacy. The current version of ggc is 7.3. The current version of Ubuntu is 17.10. The commit message should describe the warning produced by gcc.
The patch might quiet a warning but does not get to the point.
In query_console_serial() term_read_reply() might return less than 3 values. In this case rows and columns is still based on an uninitialized value.
Best regards
Heinrich
on Ubuntu 14.04, which is fairly recent. Init these variables to fix the problem.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3:
- Add new patch to init the 'rows' and 'cols' variables
Changes in v2: None
lib/efi_loader/efi_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 28d63635ec..971e36da48 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -242,7 +242,7 @@ static efi_status_t EFIAPI efi_cout_query_mode(
if (!console_size_queried) { const char *stdout_name = env_get("stdout");
int rows, cols;
int rows = 0, cols = 0;
console_size_queried = true;

On Mon, Feb 19, 2018 at 7:21 PM, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 02/19/2018 04:48 PM, Simon Glass wrote:
The current code causes a compiler error on gcc 4.8.4 as used by sandbox
gcc 4 is legacy. The current version of ggc is 7.3. The current version of Ubuntu is 17.10.
It's still a supported LTS release, 4.8.x is also the core version of gcc in RHEL-7 so it's likely still useful to support 4.8.x
The commit message should describe the warning produced by gcc.
The patch might quiet a warning but does not get to the point.
In query_console_serial() term_read_reply() might return less than 3 values. In this case rows and columns is still based on an uninitialized value.
Best regards
Heinrich
on Ubuntu 14.04, which is fairly recent. Init these variables to fix the problem.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3:
- Add new patch to init the 'rows' and 'cols' variables
Changes in v2: None
lib/efi_loader/efi_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 28d63635ec..971e36da48 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -242,7 +242,7 @@ static efi_status_t EFIAPI efi_cout_query_mode( if (!console_size_queried) { const char *stdout_name = env_get("stdout");
int rows, cols;
int rows = 0, cols = 0; console_size_queried = true;
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

This function can fail but gives no indication of failure. Update it to return an error when something goes wrong.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Return error value of efi_allocate_pages() - Update function comment for write_smbios_table() - Add comments on aligment
Changes in v2: - Update return type of efi_smbios_register() to efi_status_t - Use return value of efi_install_configuration_table
include/efi_loader.h | 9 ++++++++- include/smbios.h | 5 +++-- lib/efi_loader/efi_smbios.c | 18 +++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 07730c3f39..831883287f 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -185,7 +185,14 @@ int efi_net_register(void); /* Called by bootefi to make the watchdog available */ int efi_watchdog_register(void); /* Called by bootefi to make SMBIOS tables available */ -void efi_smbios_register(void); +/** + * efi_smbios_register() - write out SMBIOS tables + * + * Called by bootefi to make SMBIOS tables available + * + * @return 0 if OK, -ENOMEM if no memory is available for the tables + */ +efi_status_t efi_smbios_register(void);
struct efi_simple_file_system_protocol * efi_fs_from_path(struct efi_device_path *fp); diff --git a/include/smbios.h b/include/smbios.h index c24d00e38d..a94dbbd78b 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -232,8 +232,9 @@ typedef int (*smbios_write_type)(ulong *addr, int handle); * * This writes SMBIOS table at a given address. * - * @addr: start address to write SMBIOS table - * @return: end address of SMBIOS table + * @addr: start address to write SMBIOS table. If this is not + * 16-byte-aligned then it will be aligned before the table is written + * @return: end address of SMBIOS table (and start address for next entry) */ ulong write_smbios_table(ulong addr);
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index ac412e7362..754ae9a5c3 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -13,20 +13,28 @@
static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
-void efi_smbios_register(void) +efi_status_t efi_smbios_register(void) { /* Map within the low 32 bits, to allow for 32bit SMBIOS tables */ uint64_t dmi = 0xffffffff; /* Reserve 4kb for SMBIOS */ uint64_t pages = 1; int memtype = EFI_RUNTIME_SERVICES_DATA; + efi_status_t ret;
- if (efi_allocate_pages(1, memtype, pages, &dmi) != EFI_SUCCESS) - return; + ret = efi_allocate_pages(1, memtype, pages, &dmi); + if (ret) + return ret;
- /* Generate SMBIOS tables */ + /* + * Generate SMBIOS tables - we know that efi_allocate_pages() returns + * a 4k-aligned address, so it is safe to assume that + * write_smbios_table() will write the table at that address. + */ + assert(!(dmi & 0xf)); write_smbios_table(dmi);
/* And expose them to our EFI payload */ - efi_install_configuration_table(&smbios_guid, (void*)(uintptr_t)dmi); + return efi_install_configuration_table(&smbios_guid, + (void *)(uintptr_t)dmi); }

On 02/19/2018 04:48 PM, Simon Glass wrote:
This function can fail but gives no indication of failure. Update it to return an error when something goes wrong.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3:
- Return error value of efi_allocate_pages()
- Update function comment for write_smbios_table()
- Add comments on aligment
Changes in v2:
Update return type of efi_smbios_register() to efi_status_t
Use return value of efi_install_configuration_table
include/efi_loader.h | 9 ++++++++- include/smbios.h | 5 +++-- lib/efi_loader/efi_smbios.c | 18 +++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 07730c3f39..831883287f 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -185,7 +185,14 @@ int efi_net_register(void); /* Called by bootefi to make the watchdog available */ int efi_watchdog_register(void); /* Called by bootefi to make SMBIOS tables available */ -void efi_smbios_register(void); +/**
- efi_smbios_register() - write out SMBIOS tables
- Called by bootefi to make SMBIOS tables available
- @return 0 if OK, -ENOMEM if no memory is available for the tables
- */
+efi_status_t efi_smbios_register(void);
struct efi_simple_file_system_protocol * efi_fs_from_path(struct efi_device_path *fp); diff --git a/include/smbios.h b/include/smbios.h index c24d00e38d..a94dbbd78b 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -232,8 +232,9 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
- This writes SMBIOS table at a given address.
- @addr: start address to write SMBIOS table
- @return: end address of SMBIOS table
- @addr: start address to write SMBIOS table. If this is not
- 16-byte-aligned then it will be aligned before the table is written
*/ ulong write_smbios_table(ulong addr);
- @return: end address of SMBIOS table (and start address for next entry)
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index ac412e7362..754ae9a5c3 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -13,20 +13,28 @@
static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
-void efi_smbios_register(void) +efi_status_t efi_smbios_register(void) { /* Map within the low 32 bits, to allow for 32bit SMBIOS tables */ uint64_t dmi = 0xffffffff; /* Reserve 4kb for SMBIOS */ uint64_t pages = 1; int memtype = EFI_RUNTIME_SERVICES_DATA;
- efi_status_t ret;
- if (efi_allocate_pages(1, memtype, pages, &dmi) != EFI_SUCCESS)
return;
Please, use the predefined constant EFI_ALLOCATE_MAX_ADDRESS and not "1".
Your patch is duplicate to https://lists.denx.de/pipermail/u-boot/2018-February/320488.html
Best regards
Heinrich
- ret = efi_allocate_pages(1, memtype, pages, &dmi);
- if (ret)
return ret;
- /* Generate SMBIOS tables */
/*
* Generate SMBIOS tables - we know that efi_allocate_pages() returns
* a 4k-aligned address, so it is safe to assume that
* write_smbios_table() will write the table at that address.
*/
assert(!(dmi & 0xf)); write_smbios_table(dmi);
/* And expose them to our EFI payload */
- efi_install_configuration_table(&smbios_guid, (void*)(uintptr_t)dmi);
- return efi_install_configuration_table(&smbios_guid,
}(void *)(uintptr_t)dmi);

Rather than having the caller check this variable and the callee set it, move all access to the variable inside the function. This reduces the logic needed to call efi_init_obj_list().
Fix the spelling of initalized at the same time to fix a patman warning on this patch.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed: Heinrich Schuchardt xypron.glpk@gmx.de ---
Changes in v3: - Avoid adding a new call to efi_init_obj_list() - Fix spelling of initalized
Changes in v2: None
cmd/bootefi.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2106ed9c8c..064c069757 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -22,7 +22,7 @@
DECLARE_GLOBAL_DATA_PTR;
-static uint8_t efi_obj_list_initalized; +static uint8_t efi_obj_list_initialised;
static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; @@ -30,7 +30,9 @@ static struct efi_device_path *bootefi_device_path; /* Initialize and populate EFI object list */ static void efi_init_obj_list(void) { - efi_obj_list_initalized = 1; + if (efi_obj_list_initialised) + return; + efi_obj_list_initialised = 1;
/* Initialize EFI driver uclass */ efi_driver_init(); @@ -184,8 +186,7 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, }
/* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); + efi_init_obj_list();
efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, device_path, image_path); @@ -284,8 +285,7 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) efi_status_t r;
/* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); + efi_init_obj_list();
/* * gd lives in a fixed register which may get clobbered while we execute @@ -350,8 +350,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ efi_save_gd(); /* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); + efi_init_obj_list(); /* Transfer environment variable efi_selftest as load options */ set_load_options(&loaded_image_info, "efi_selftest"); /* Execute the test */

On 02/19/2018 04:48 PM, Simon Glass wrote:
Rather than having the caller check this variable and the callee set it, move all access to the variable inside the function. This reduces the logic needed to call efi_init_obj_list().
Fix the spelling of initalized at the same time to fix a patman warning on this patch.
We should have only one location from wehre we call efi_init_obj_list().
We should be able to distinguish between a successful and a failed initialization. If the initialization has failed we should not allow bootefi to execute.
This patch is duplicate to the https://lists.denx.de/pipermail/u-boot/2018-February/320487.html patch series.
Regards
Heinrich
Signed-off-by: Simon Glass sjg@chromium.org Reviewed: Heinrich Schuchardt xypron.glpk@gmx.de
Changes in v3:
- Avoid adding a new call to efi_init_obj_list()
- Fix spelling of initalized
Changes in v2: None
cmd/bootefi.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2106ed9c8c..064c069757 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -22,7 +22,7 @@
DECLARE_GLOBAL_DATA_PTR;
-static uint8_t efi_obj_list_initalized; +static uint8_t efi_obj_list_initialised;
static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; @@ -30,7 +30,9 @@ static struct efi_device_path *bootefi_device_path; /* Initialize and populate EFI object list */ static void efi_init_obj_list(void) {
- efi_obj_list_initalized = 1;
if (efi_obj_list_initialised)
return;
efi_obj_list_initialised = 1;
/* Initialize EFI driver uclass */ efi_driver_init();
@@ -184,8 +186,7 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, }
/* Initialize and populate EFI object list */
- if (!efi_obj_list_initalized)
efi_init_obj_list();
efi_init_obj_list();
efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, device_path, image_path);
@@ -284,8 +285,7 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) efi_status_t r;
/* Initialize and populate EFI object list */
- if (!efi_obj_list_initalized)
efi_init_obj_list();
efi_init_obj_list();
/*
- gd lives in a fixed register which may get clobbered while we execute
@@ -350,8 +350,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ efi_save_gd(); /* Initialize and populate EFI object list */
if (!efi_obj_list_initalized)
efi_init_obj_list();
/* Transfer environment variable efi_selftest as load options */ set_load_options(&loaded_image_info, "efi_selftest"); /* Execute the test */efi_init_obj_list();

This function calls a function which can fail. Print a message in this case and abort the boot, rather than silently continuing to boot, which will certainly fail.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: - Change return type of efi_init_obj_list() to efi_status_t - Convert #ifdef CONFIG_GENERATE_SMBIOS_TABLE to if()
cmd/bootefi.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 064c069757..259f80a0d8 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -27,11 +27,17 @@ static uint8_t efi_obj_list_initialised; static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path;
-/* Initialize and populate EFI object list */ -static void efi_init_obj_list(void) +/** + * efi_init_obj_list() - Initialize and populate EFI object list + * + * @return 0 if OK, -ve on error (in which case it prints a message) + */ +static efi_status_t efi_init_obj_list(void) { + efi_status_t ret; + if (efi_obj_list_initialised) - return; + return 0; efi_obj_list_initialised = 1;
/* Initialize EFI driver uclass */ @@ -47,14 +53,21 @@ static void efi_init_obj_list(void) #ifdef CONFIG_NET efi_net_register(); #endif -#ifdef CONFIG_GENERATE_SMBIOS_TABLE - efi_smbios_register(); -#endif + if (IS_ENABLED(GENERATE_SMBIOS_TABLE)) { + ret = efi_smbios_register(); + if (ret) + goto error; + } efi_watchdog_register();
/* Initialize EFI runtime services */ efi_reset_system_init(); efi_get_time_init(); + + return EFI_SUCCESS; +error: + printf("Error: Cannot set up EFI object list (err=%lx)\n", ret); + return ret; }
/* @@ -186,7 +199,9 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, }
/* Initialize and populate EFI object list */ - efi_init_obj_list(); + ret = efi_init_obj_list(); + if (ret) + return ret;
efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, device_path, image_path); @@ -350,7 +365,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ efi_save_gd(); /* Initialize and populate EFI object list */ - efi_init_obj_list(); + if (efi_init_obj_list()) + return CMD_RET_FAILURE; /* Transfer environment variable efi_selftest as load options */ set_load_options(&loaded_image_info, "efi_selftest"); /* Execute the test */

This function repeats data structures provided by driver model. They are only created once so can be stale if the EFI loader is called twice (e.g. for testing or on boot failure).
Add a TODO to address this. It should be possible to attach EFI devices and data structures to driver-model devices and avoid having a parallel set of data structures.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
cmd/bootefi.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 259f80a0d8..d670a541eb 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -30,6 +30,10 @@ static struct efi_device_path *bootefi_device_path; /** * efi_init_obj_list() - Initialize and populate EFI object list * + * TODO(sjg@chromium.org): Move this to a dynamic list based on driver model, + * so that it does not need to be created before running EFI applications + * and updates when devices change. + * * @return 0 if OK, -ve on error (in which case it prints a message) */ static efi_status_t efi_init_obj_list(void)

On 02/19/2018 04:48 PM, Simon Glass wrote:
This function repeats data structures provided by driver model. They are only created once so can be stale if the EFI loader is called twice (e.g. for testing or on boot failure).
Add a TODO to address this. It should be possible to attach EFI devices and data structures to driver-model devices and avoid having a parallel set of data structures.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2: None
cmd/bootefi.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 259f80a0d8..d670a541eb 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -30,6 +30,10 @@ static struct efi_device_path *bootefi_device_path; /**
- efi_init_obj_list() - Initialize and populate EFI object list
- TODO(sjg@chromium.org): Move this to a dynamic list based on driver model,
- so that it does not need to be created before running EFI applications
- and updates when devices change.
This could be implemented by calling the ConnectController and DisconnectController boot services and adding the necessary EFI drivers to the EFI uclass (see directory lib/efi_driver/).
Best regards
Heinrich
*/
- @return 0 if OK, -ve on error (in which case it prints a message)
static efi_status_t efi_init_obj_list(void)

From: Simon Glass sjg@chromium.org
This function repeats data structures provided by driver model. They are only created once so can be stale if the EFI loader is called twice (e.g. for testing or on boot failure).
Add a TODO to address this. It should be possible to attach EFI devices and data structures to driver-model devices and avoid having a parallel set of data structures.
Signed-off-by: Simon Glass sjg@chromium.org [Rebased] Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de --- v4 rebased v3 no change v2 no change --- cmd/bootefi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 6afece10bc1..269cc71d0bd 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -29,7 +29,13 @@ static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path;
-/* Initialize and populate EFI object list */ +/* + * Initialize and populate EFI object list + * + * TODO(sjg@chromium.org): Move this to a dynamic list based on driver model, + * so that it does not need to be created before running EFI applications + * and updates when devices change. + */ efi_status_t efi_init_obj_list(void) { efi_status_t ret = EFI_SUCCESS;

The headers are not in the correct order. Fix this. Also drop libfdt_env.h since it is not needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: - Update commit message to dropping libfdt_env.h
lib/efi_loader/efi_memory.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index aaf64421a3..c273a7ba30 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -8,12 +8,11 @@
#include <common.h> #include <efi_loader.h> +#include <inttypes.h> #include <malloc.h> +#include <watchdog.h> #include <asm/global_data.h> -#include <libfdt_env.h> #include <linux/list_sort.h> -#include <inttypes.h> -#include <watchdog.h>
DECLARE_GLOBAL_DATA_PTR;

On 02/19/2018 04:48 PM, Simon Glass wrote:
The headers are not in the correct order. Fix this. Also drop libfdt_env.h since it is not needed.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2:
- Update commit message to dropping libfdt_env.h
lib/efi_loader/efi_memory.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index aaf64421a3..c273a7ba30 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -8,12 +8,11 @@
#include <common.h> #include <efi_loader.h> +#include <inttypes.h> #include <malloc.h> +#include <watchdog.h> #include <asm/global_data.h> -#include <libfdt_env.h>
The patch has to be rebased due to b08c8c48708 libfdt: move headers to <linux/libfdt.h> and <linux/libfdt_env.h>
Otherwise
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
#include <linux/list_sort.h> -#include <inttypes.h> -#include <watchdog.h>
DECLARE_GLOBAL_DATA_PTR;

From: Simon Glass sjg@chromium.org
The headers are not in the correct order. Fix this. Also drop libfdt_env.h since it is not needed.
Signed-off-by: Simon Glass sjg@chromium.org Rebased Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de --- v4 rebased (linux/libfdt_env.h instead of libfdt_env.h) v3 no change v2 update commit message to dropping libfdt_env.h --- lib/efi_loader/efi_memory.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index d980e730ffa..95f9ff0a140 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -8,12 +8,11 @@
#include <common.h> #include <efi_loader.h> +#include <inttypes.h> #include <malloc.h> +#include <watchdog.h> #include <asm/global_data.h> -#include <linux/libfdt_env.h> #include <linux/list_sort.h> -#include <inttypes.h> -#include <watchdog.h>
DECLARE_GLOBAL_DATA_PTR;

With sandbox the U-Boot code is not mapped into the sandbox memory range so does not need to be excluded when allocating EFI memory. Update the EFI memory init code to take account of that.
Also use mapmem instead of a cast to convert a memory address to a pointer.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: - Update to use mapmem instead of a cast
lib/efi_loader/efi_memory.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index c273a7ba30..b113e08783 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -10,6 +10,7 @@ #include <efi_loader.h> #include <inttypes.h> #include <malloc.h> +#include <mapmem.h> #include <watchdog.h> #include <asm/global_data.h> #include <linux/list_sort.h> @@ -389,7 +390,7 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) r = efi_allocate_pages(0, pool_type, num_pages, &t);
if (r == EFI_SUCCESS) { - struct efi_pool_allocation *alloc = (void *)(uintptr_t)t; + struct efi_pool_allocation *alloc = map_sysmem(t, size); alloc->num_pages = num_pages; *buffer = alloc->data; } @@ -500,18 +501,22 @@ int efi_memory_init(void)
efi_add_known_memory();
- /* Add U-Boot */ - uboot_start = (gd->start_addr_sp - uboot_stack_size) & ~EFI_PAGE_MASK; - uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT; - efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false); - - /* Add Runtime Services */ - runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK; - runtime_end = (ulong)&__efi_runtime_stop; - runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; - runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; - efi_add_memory_map(runtime_start, runtime_pages, - EFI_RUNTIME_SERVICES_CODE, false); + if (!IS_ENABLED(CONFIG_SANDBOX)) { + /* Add U-Boot */ + uboot_start = (gd->start_addr_sp - uboot_stack_size) & + ~EFI_PAGE_MASK; + uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT; + efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, + false); + + /* Add Runtime Services */ + runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK; + runtime_end = (ulong)&__efi_runtime_stop; + runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; + runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; + efi_add_memory_map(runtime_start, runtime_pages, + EFI_RUNTIME_SERVICES_CODE, false); + }
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER /* Request a 32bit 64MB bounce buffer region */

On 02/19/2018 04:48 PM, Simon Glass wrote:
With sandbox the U-Boot code is not mapped into the sandbox memory range so does not need to be excluded when allocating EFI memory. Update the EFI memory init code to take account of that.
Also use mapmem instead of a cast to convert a memory address to a pointer.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2:
Update to use mapmem instead of a cast
lib/efi_loader/efi_memory.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index c273a7ba30..b113e08783 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -10,6 +10,7 @@ #include <efi_loader.h> #include <inttypes.h> #include <malloc.h> +#include <mapmem.h> #include <watchdog.h> #include <asm/global_data.h> #include <linux/list_sort.h> @@ -389,7 +390,7 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) r = efi_allocate_pages(0, pool_type, num_pages, &t);
if (r == EFI_SUCCESS) {
struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
struct efi_pool_allocation *alloc = map_sysmem(t, size);
The AllocatePages Service has to return 4096 byte aligned memory. AllocatePool has to return 8 byte aligned memory.
I cannot see that this page makes these guarantees.
alloc->num_pages = num_pages; *buffer = alloc->data;
} @@ -500,18 +501,22 @@ int efi_memory_init(void)
efi_add_known_memory();
You fail guarantee that the known memory is 4096 byte aligned.
- /* Add U-Boot */
- uboot_start = (gd->start_addr_sp - uboot_stack_size) & ~EFI_PAGE_MASK;
- uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT;
- efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false);
- /* Add Runtime Services */
- runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK;
- runtime_end = (ulong)&__efi_runtime_stop;
- runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
- runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
- efi_add_memory_map(runtime_start, runtime_pages,
EFI_RUNTIME_SERVICES_CODE, false);
- if (!IS_ENABLED(CONFIG_SANDBOX)) {
You are passing all memory aquired via mmap() in the above efi_add_known_memory() table.
So here you have to mark any memory range as occupied that has already been given away or may be allocated by non-EFI functions from the mmap() assigned memory.
Best regards
Heinrich
/* Add U-Boot */
uboot_start = (gd->start_addr_sp - uboot_stack_size) &
~EFI_PAGE_MASK;
uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT;
efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA,
false);
/* Add Runtime Services */
runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK;
runtime_end = (ulong)&__efi_runtime_stop;
runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
efi_add_memory_map(runtime_start, runtime_pages,
EFI_RUNTIME_SERVICES_CODE, false);
}
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER /* Request a 32bit 64MB bounce buffer region */

Hi Heinrich,
On 20 February 2018 at 10:12, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 02/19/2018 04:48 PM, Simon Glass wrote:
With sandbox the U-Boot code is not mapped into the sandbox memory range so does not need to be excluded when allocating EFI memory. Update the EFI memory init code to take account of that.
Also use mapmem instead of a cast to convert a memory address to a pointer.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2:
Update to use mapmem instead of a cast
lib/efi_loader/efi_memory.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index c273a7ba30..b113e08783 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -10,6 +10,7 @@ #include <efi_loader.h> #include <inttypes.h> #include <malloc.h> +#include <mapmem.h> #include <watchdog.h> #include <asm/global_data.h> #include <linux/list_sort.h> @@ -389,7 +390,7 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) r = efi_allocate_pages(0, pool_type, num_pages, &t); if (r == EFI_SUCCESS) {
struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
struct efi_pool_allocation *alloc = map_sysmem(t, size);
The AllocatePages Service has to return 4096 byte aligned memory. AllocatePool has to return 8 byte aligned memory.
I cannot see that this page makes these guarantees.
Well I am not changing that code. All I am doing is correctly mapping the long address to a sandbox pointer.
alloc->num_pages = num_pages; *buffer = alloc->data; }
@@ -500,18 +501,22 @@ int efi_memory_init(void) efi_add_known_memory();
You fail guarantee that the known memory is 4096 byte aligned.
Presumable the existing code does that, and I am not changing it.
/* Add U-Boot */
uboot_start = (gd->start_addr_sp - uboot_stack_size) &
~EFI_PAGE_MASK;
uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT;
efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA,
false);
/* Add Runtime Services */
runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK;
runtime_end = (ulong)&__efi_runtime_stop;
runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
efi_add_memory_map(runtime_start, runtime_pages,
EFI_RUNTIME_SERVICES_CODE, false);
if (!IS_ENABLED(CONFIG_SANDBOX)) {
You are passing all memory aquired via mmap() in the above efi_add_known_memory() table.
So here you have to mark any memory range as occupied that has already been given away or may be allocated by non-EFI functions from the mmap() assigned memory.
This is not mmap(), just a map from U-Boot ulong addresses to sandbox pointers. So there should be no additional processing needed.
Regards, Simon

At present this code casts addresses to pointers so cannot be used with sandbox. Update it to use mapmem instead.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Drop incorrect map_sysmem() in map_sysmem()
Changes in v2: None
lib/smbios.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index 8f19ad89c1..c4d715ca99 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -7,6 +7,7 @@ */
#include <common.h> +#include <mapmem.h> #include <smbios.h> #include <tables_csum.h> #include <version.h> @@ -75,9 +76,10 @@ static int smbios_string_table_len(char *start)
static int smbios_write_type0(ulong *current, int handle) { - struct smbios_type0 *t = (struct smbios_type0 *)*current; + struct smbios_type0 *t; int len = sizeof(struct smbios_type0);
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type0)); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); t->vendor = smbios_add_string(t->eos, "U-Boot"); @@ -104,16 +106,18 @@ static int smbios_write_type0(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len; + unmap_sysmem(t);
return len; }
static int smbios_write_type1(ulong *current, int handle) { - struct smbios_type1 *t = (struct smbios_type1 *)*current; + struct smbios_type1 *t; int len = sizeof(struct smbios_type1); char *serial_str = env_get("serial#");
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type1)); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER); @@ -125,15 +129,17 @@ static int smbios_write_type1(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len; + unmap_sysmem(t);
return len; }
static int smbios_write_type2(ulong *current, int handle) { - struct smbios_type2 *t = (struct smbios_type2 *)*current; + struct smbios_type2 *t; int len = sizeof(struct smbios_type2);
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type2)); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER); @@ -143,15 +149,17 @@ static int smbios_write_type2(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len; + unmap_sysmem(t);
return len; }
static int smbios_write_type3(ulong *current, int handle) { - struct smbios_type3 *t = (struct smbios_type3 *)*current; + struct smbios_type3 *t; int len = sizeof(struct smbios_type3);
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type3)); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER); @@ -163,6 +171,7 @@ static int smbios_write_type3(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len; + unmap_sysmem(t);
return len; } @@ -201,9 +210,10 @@ static void smbios_write_type4_dm(struct smbios_type4 *t)
static int smbios_write_type4(ulong *current, int handle) { - struct smbios_type4 *t = (struct smbios_type4 *)*current; + struct smbios_type4 *t; int len = sizeof(struct smbios_type4);
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type4)); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; @@ -217,32 +227,37 @@ static int smbios_write_type4(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len; + unmap_sysmem(t);
return len; }
static int smbios_write_type32(ulong *current, int handle) { - struct smbios_type32 *t = (struct smbios_type32 *)*current; + struct smbios_type32 *t; int len = sizeof(struct smbios_type32);
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type32)); fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
*current += len; + unmap_sysmem(t);
return len; }
static int smbios_write_type127(ulong *current, int handle) { - struct smbios_type127 *t = (struct smbios_type127 *)*current; + struct smbios_type127 *t; int len = sizeof(struct smbios_type127);
+ t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type127)); fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
*current += len; + unmap_sysmem(t);
return len; } @@ -271,7 +286,7 @@ ulong write_smbios_table(ulong addr) /* 16 byte align the table address */ addr = ALIGN(addr, 16);
- se = (struct smbios_entry *)(uintptr_t)addr; + se = map_sysmem(addr, sizeof(struct smbios_entry)); memset(se, 0, sizeof(struct smbios_entry));
addr += sizeof(struct smbios_entry); @@ -300,6 +315,7 @@ ulong write_smbios_table(ulong addr) isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET; se->intermediate_checksum = table_compute_checksum(istart, isize); se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry)); + unmap_sysmem(se);
return addr; }

On 02/19/2018 04:48 PM, Simon Glass wrote:
At present this code casts addresses to pointers so cannot be used with sandbox. Update it to use mapmem instead.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3:
- Drop incorrect map_sysmem() in map_sysmem()
Did you mean - Drop incorrect map_sysmem() in write_smbios_table();
Regards
Heinrich
Changes in v2: None
lib/smbios.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index 8f19ad89c1..c4d715ca99 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -7,6 +7,7 @@ */
#include <common.h> +#include <mapmem.h> #include <smbios.h> #include <tables_csum.h> #include <version.h> @@ -75,9 +76,10 @@ static int smbios_string_table_len(char *start)
static int smbios_write_type0(ulong *current, int handle) {
- struct smbios_type0 *t = (struct smbios_type0 *)*current;
struct smbios_type0 *t; int len = sizeof(struct smbios_type0);
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type0)); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); t->vendor = smbios_add_string(t->eos, "U-Boot");
@@ -104,16 +106,18 @@ static int smbios_write_type0(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len;
unmap_sysmem(t);
return len; }
static int smbios_write_type1(ulong *current, int handle) {
- struct smbios_type1 *t = (struct smbios_type1 *)*current;
struct smbios_type1 *t; int len = sizeof(struct smbios_type1); char *serial_str = env_get("serial#");
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type1)); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
@@ -125,15 +129,17 @@ static int smbios_write_type1(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len;
unmap_sysmem(t);
return len; }
static int smbios_write_type2(ulong *current, int handle) {
- struct smbios_type2 *t = (struct smbios_type2 *)*current;
struct smbios_type2 *t; int len = sizeof(struct smbios_type2);
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type2)); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
@@ -143,15 +149,17 @@ static int smbios_write_type2(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len;
unmap_sysmem(t);
return len; }
static int smbios_write_type3(ulong *current, int handle) {
- struct smbios_type3 *t = (struct smbios_type3 *)*current;
struct smbios_type3 *t; int len = sizeof(struct smbios_type3);
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type3)); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
@@ -163,6 +171,7 @@ static int smbios_write_type3(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len;
unmap_sysmem(t);
return len; }
@@ -201,9 +210,10 @@ static void smbios_write_type4_dm(struct smbios_type4 *t)
static int smbios_write_type4(ulong *current, int handle) {
- struct smbios_type4 *t = (struct smbios_type4 *)*current;
struct smbios_type4 *t; int len = sizeof(struct smbios_type4);
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type4)); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
@@ -217,32 +227,37 @@ static int smbios_write_type4(ulong *current, int handle)
len = t->length + smbios_string_table_len(t->eos); *current += len;
unmap_sysmem(t);
return len; }
static int smbios_write_type32(ulong *current, int handle) {
- struct smbios_type32 *t = (struct smbios_type32 *)*current;
struct smbios_type32 *t; int len = sizeof(struct smbios_type32);
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type32)); fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
*current += len;
unmap_sysmem(t);
return len; }
static int smbios_write_type127(ulong *current, int handle) {
- struct smbios_type127 *t = (struct smbios_type127 *)*current;
struct smbios_type127 *t; int len = sizeof(struct smbios_type127);
t = map_sysmem(*current, len); memset(t, 0, sizeof(struct smbios_type127)); fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
*current += len;
unmap_sysmem(t);
return len; }
@@ -271,7 +286,7 @@ ulong write_smbios_table(ulong addr) /* 16 byte align the table address */ addr = ALIGN(addr, 16);
- se = (struct smbios_entry *)(uintptr_t)addr;
se = map_sysmem(addr, sizeof(struct smbios_entry)); memset(se, 0, sizeof(struct smbios_entry));
addr += sizeof(struct smbios_entry);
@@ -300,6 +315,7 @@ ulong write_smbios_table(ulong addr) isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET; se->intermediate_checksum = table_compute_checksum(istart, isize); se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
unmap_sysmem(se);
return addr; }

Add an implementation of setjmp() and longjmp() which rely on the underlying host C library. Since we cannot know how large the jump buffer needs to be, pick something that should be suitable and check it at runtime. At present we need access to the underlying struct as well.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/sandbox/cpu/cpu.c | 13 +++++++++++++ arch/sandbox/cpu/os.c | 17 +++++++++++++++++ arch/sandbox/include/asm/setjmp.h | 21 +++++++++++++++++++++ include/os.h | 21 +++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 arch/sandbox/include/asm/setjmp.h
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 66c3a6a88a..8b397c7168 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -9,6 +9,7 @@ #include <libfdt.h> #include <os.h> #include <asm/io.h> +#include <asm/setjmp.h> #include <asm/state.h> #include <dm/root.h>
@@ -164,3 +165,15 @@ ulong timer_get_boot_us(void)
return (count - base_count) / 1000; } + +int setjmp(jmp_buf jmp) +{ + return os_setjmp((ulong *)jmp, sizeof(jmp)); +} + +void longjmp(jmp_buf jmp, int ret) +{ + os_longjmp((ulong *)jmp, ret); + while (1) + ; +} diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 9dd90a1b30..f29fa184b8 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -7,6 +7,7 @@ #include <errno.h> #include <fcntl.h> #include <getopt.h> +#include <setjmp.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -628,3 +629,19 @@ void os_localtime(struct rtc_time *rt) rt->tm_yday = tm->tm_yday; rt->tm_isdst = tm->tm_isdst; } + +int os_setjmp(ulong *jmp, int size) +{ + if (size < sizeof(jmp_buf)) { + printf("setjmp: jmpbuf is too small (%d bytes, need %d)\n", + size, sizeof(jmp_buf)); + return -ENOSPC; + } + + return setjmp((struct __jmp_buf_tag *)jmp); +} + +void os_longjmp(ulong *jmp, int ret) +{ + longjmp((struct __jmp_buf_tag *)jmp, ret); +} diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h new file mode 100644 index 0000000000..e25f50107c --- /dev/null +++ b/arch/sandbox/include/asm/setjmp.h @@ -0,0 +1,21 @@ +/* + * (C) Copyright 2016 + * Alexander Graf agraf@suse.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1 + +struct jmp_buf_data { + /* We're not sure how long this should be */ + ulong data[32]; +}; + +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf jmp); +__noreturn void longjmp(jmp_buf jmp, int ret); + +#endif /* _SETJMP_H_ */ diff --git a/include/os.h b/include/os.h index 049b248c5b..80fca6e85e 100644 --- a/include/os.h +++ b/include/os.h @@ -330,4 +330,25 @@ int os_spl_to_uboot(const char *fname); */ void os_localtime(struct rtc_time *rt);
+/** + * os_setjmp() - Call setjmp() + * + * Call the host system's setjmp() function. + * + * @jmp: Buffer to store current execution state + * @size: Size of buffer + * @return normal setjmp() value if OK, -ENOSPC if @size is too small + */ +int os_setjmp(ulong *jmp, int size); + +/** + * os_longjmp() - Call longjmp() + * + * Call the host system's longjmp() function. + * + * @jmp: Buffer where previous execution state was stored + * @ret: Value to pass to longjmp() + */ +void os_longjmp(ulong *jmp, int ret); + #endif

On 02/19/2018 04:48 PM, Simon Glass wrote:
Add an implementation of setjmp() and longjmp() which rely on the underlying host C library. Since we cannot know how large the jump buffer needs to be, pick something that should be suitable and check it at runtime. At present we need access to the underlying struct as well.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3: None
I sent you a reply for version 2 stating that it was creating a compiler warning. https://lists.denx.de/pipermail/u-boot/2018-January/316379.html
Wouldn't you want to address that before resubmitting an unchanged patch?
Best regards
Heinrich
Changes in v2: None
arch/sandbox/cpu/cpu.c | 13 +++++++++++++ arch/sandbox/cpu/os.c | 17 +++++++++++++++++ arch/sandbox/include/asm/setjmp.h | 21 +++++++++++++++++++++ include/os.h | 21 +++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 arch/sandbox/include/asm/setjmp.h
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 66c3a6a88a..8b397c7168 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -9,6 +9,7 @@ #include <libfdt.h> #include <os.h> #include <asm/io.h> +#include <asm/setjmp.h> #include <asm/state.h> #include <dm/root.h>
@@ -164,3 +165,15 @@ ulong timer_get_boot_us(void)
return (count - base_count) / 1000; }
+int setjmp(jmp_buf jmp) +{
- return os_setjmp((ulong *)jmp, sizeof(jmp));
+}
+void longjmp(jmp_buf jmp, int ret) +{
- os_longjmp((ulong *)jmp, ret);
- while (1)
;
+} diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 9dd90a1b30..f29fa184b8 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -7,6 +7,7 @@ #include <errno.h> #include <fcntl.h> #include <getopt.h> +#include <setjmp.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -628,3 +629,19 @@ void os_localtime(struct rtc_time *rt) rt->tm_yday = tm->tm_yday; rt->tm_isdst = tm->tm_isdst; }
+int os_setjmp(ulong *jmp, int size) +{
- if (size < sizeof(jmp_buf)) {
printf("setjmp: jmpbuf is too small (%d bytes, need %d)\n",
size, sizeof(jmp_buf));
return -ENOSPC;
- }
- return setjmp((struct __jmp_buf_tag *)jmp);
+}
+void os_longjmp(ulong *jmp, int ret) +{
- longjmp((struct __jmp_buf_tag *)jmp, ret);
+} diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h new file mode 100644 index 0000000000..e25f50107c --- /dev/null +++ b/arch/sandbox/include/asm/setjmp.h @@ -0,0 +1,21 @@ +/*
- (C) Copyright 2016
- Alexander Graf agraf@suse.de
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1
+struct jmp_buf_data {
- /* We're not sure how long this should be */
- ulong data[32];
+};
+typedef struct jmp_buf_data jmp_buf[1];
+int setjmp(jmp_buf jmp); +__noreturn void longjmp(jmp_buf jmp, int ret);
+#endif /* _SETJMP_H_ */ diff --git a/include/os.h b/include/os.h index 049b248c5b..80fca6e85e 100644 --- a/include/os.h +++ b/include/os.h @@ -330,4 +330,25 @@ int os_spl_to_uboot(const char *fname); */ void os_localtime(struct rtc_time *rt);
+/**
- os_setjmp() - Call setjmp()
- Call the host system's setjmp() function.
- @jmp: Buffer to store current execution state
- @size: Size of buffer
- @return normal setjmp() value if OK, -ENOSPC if @size is too small
- */
+int os_setjmp(ulong *jmp, int size);
+/**
- os_longjmp() - Call longjmp()
- Call the host system's longjmp() function.
- @jmp: Buffer where previous execution state was stored
- @ret: Value to pass to longjmp()
- */
+void os_longjmp(ulong *jmp, int ret);
- #endif

The EFI loader code requires certain linker sections to exist. Add these for sandbox so that the EFI loader code will link.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/sandbox/cpu/u-boot.lds | 29 +++++++++++++++++++++++++++++ arch/sandbox/lib/Makefile | 2 +- arch/sandbox/lib/sections.c | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 arch/sandbox/lib/sections.c
diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds index 7e92b4ac66..38a74bcaf4 100644 --- a/arch/sandbox/cpu/u-boot.lds +++ b/arch/sandbox/cpu/u-boot.lds @@ -19,6 +19,35 @@ SECTIONS __u_boot_sandbox_option_end = .;
__bss_start = .; + + .__efi_runtime_start : { + *(.__efi_runtime_start) + } + + .efi_runtime : { + *(efi_runtime_text) + *(efi_runtime_data) + } + + .__efi_runtime_stop : { + *(.__efi_runtime_stop) + } + + .efi_runtime_rel_start : + { + *(.__efi_runtime_rel_start) + } + + .efi_runtime_rel : { + *(.relefi_runtime_text) + *(.relefi_runtime_data) + } + + .efi_runtime_rel_stop : + { + *(.__efi_runtime_rel_stop) + } + }
INSERT BEFORE .data; diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile index a79ade7b11..0a8c9f4050 100644 --- a/arch/sandbox/lib/Makefile +++ b/arch/sandbox/lib/Makefile @@ -7,7 +7,7 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-y += interrupts.o +obj-y += interrupts.o sections.o obj-$(CONFIG_PCI) += pci_io.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o diff --git a/arch/sandbox/lib/sections.c b/arch/sandbox/lib/sections.c new file mode 100644 index 0000000000..6455e0f088 --- /dev/null +++ b/arch/sandbox/lib/sections.c @@ -0,0 +1,12 @@ +/* + * Copyright 2013 Albert ARIBAUD albert.u.boot@aribaud.net + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start"))); +char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop"))); +char __efi_runtime_rel_start[0] + __attribute__((section(".__efi_runtime_rel_start"))); +char __efi_runtime_rel_stop[0] + __attribute__((section(".__efi_runtime_rel_stop")));

With sandbox these values depend on the host system. Let's assume that it is x86_64 for now.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
include/config_distro_bootcmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index f567cebd38..a265bfe01c 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -247,7 +247,7 @@ #elif defined(CONFIG_ARM) #define BOOTENV_EFI_PXE_ARCH "0xa" #define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00010:UNDI:003000" -#elif defined(CONFIG_X86) +#elif defined(CONFIG_X86) || defined(CONFIG_SANDBOX) /* Always assume we're running 64bit */ #define BOOTENV_EFI_PXE_ARCH "0x7" #define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00007:UNDI:003000"

This undocumented function relies on arch-specific code to declare a nop weak version. Add the weak function in common code instead to avoid having to duplicate the same function in each arch.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/arm/include/asm/u-boot-arm.h | 1 - arch/x86/include/asm/u-boot-x86.h | 1 - arch/x86/lib/bootm.c | 4 ---- common/bootm.c | 4 ++++ include/bootm.h | 2 ++ 5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h index ef4fca68ee..73ccf41f8c 100644 --- a/arch/arm/include/asm/u-boot-arm.h +++ b/arch/arm/include/asm/u-boot-arm.h @@ -38,7 +38,6 @@ int arch_early_init_r(void);
/* board/.../... */ int board_init(void); -void board_quiesce_devices(void);
/* cpu/.../interrupt.c */ int arch_interrupt_init (void); diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 187fe5fd8c..d2e1426042 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -85,7 +85,6 @@ static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void) /* board/... */ void timer_set_tsc_base(uint64_t new_base); uint64_t timer_get_tsc(void); -void board_quiesce_devices(void);
void quick_ram_check(void);
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index e548cdbed5..60ae043f24 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -33,10 +33,6 @@ int arch_fixup_fdt(void *blob) return 0; }
-__weak void board_quiesce_devices(void) -{ -} - void bootm_announce_and_cleanup(void) { printf("\nStarting kernel ...\n\n"); diff --git a/common/bootm.c b/common/bootm.c index adb12137c7..077978f318 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -47,6 +47,10 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len);
+__weak void board_quiesce_devices(void) +{ +} + #ifdef CONFIG_LMB static void boot_start_lmb(bootm_headers_t *images) { diff --git a/include/bootm.h b/include/bootm.h index 49813772ce..76b6ab42e6 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -73,4 +73,6 @@ int bootm_decomp_image(int comp, ulong load, ulong image_start, int type, void *load_buf, void *image_buf, ulong image_len, uint unc_len, ulong *load_end);
+void board_quiesce_devices(void); + #endif

This exported function should have a comment describing what it does. Also it should really be removed in favour of device_remove(), which handles this sort of thing now. Add a comment with a TODO.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
include/bootm.h | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/include/bootm.h b/include/bootm.h index 76b6ab42e6..caf331f54b 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -73,6 +73,12 @@ int bootm_decomp_image(int comp, ulong load, ulong image_start, int type, void *load_buf, void *image_buf, ulong image_len, uint unc_len, ulong *load_end);
+/* + * boards should define this to disable devices when EFI exits from boot + * services. + * + * TODO(sjg@chromium.org>): Update this to use driver model's device_remove(). + */ void board_quiesce_devices(void);
#endif

Add these so that we can build the EFI loader for sandbox. The values are for x86_64 so potentially bogus. But we don't support relocation within sandbox anyway.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
lib/efi_loader/efi_runtime.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index ccb4fc6141..fbf89c4a49 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -48,6 +48,9 @@ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); #include <asm/elf.h> #define R_RELATIVE R_386_RELATIVE #define R_MASK 0xffULL +#elif defined(CONFIG_SANDBOX) +#define R_RELATIVE 8 +#define R_MASK 0xffffffffULL #else #error Need to add relocation awareness #endif

These constants are defined in arch-specific code but redefined here. Add a TODO to clean this up.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
lib/efi_loader/efi_runtime.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index fbf89c4a49..42b359bbd3 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -37,6 +37,10 @@ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); #define EFI_CACHELINE_SIZE 128 #endif
+/* + * TODO(sjg@chromium.org): These defines and structs should come from the elf. + * header for each arch (or a generic header) rather than being repeated here. + */ #if defined(CONFIG_ARM64) #define R_RELATIVE 1027 #define R_MASK 0xffffffffULL

This allows this feature to build within sandbox. This is for testing purposes only since it is not possible for sandbox to load native code.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Init the 'rows' and 'cols' vars to avoid a compiler error (gcc 4.8.4)
Changes in v2: None
lib/efi_loader/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 83d75c4fdc..97658f1665 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,6 +1,6 @@ config EFI_LOADER bool "Support running EFI Applications in U-Boot" - depends on (ARM || X86) && OF_LIBFDT + depends on (ARM || X86 || SANDBOX) && OF_LIBFDT # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB

We plan to run more than one EFI test. In order to avoid duplicating code, create functions which handle preparing for running the test and cleaning up afterwards.
Also shorten the awfully long variable names here.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add new patch to split out test init/uninit into functions
Changes in v2: None
cmd/bootefi.c | 92 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 26 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d670a541eb..2a5d66e798 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -297,6 +297,64 @@ exit: return ret; }
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST +/** + * bootefi_test_prepare() - prepare to run an EFI test + * + * This sets things up so we can call EFI functions. This involves preparing + * the 'gd' pointer and setting up the load ed image data structures. + * + * @image: Pointer to a struct which will hold the loaded image info + * @obj: Pointer to a struct which will hold the loaded image object + * @path: File path to the test being run (often just the test name with a + * backslash before it + * @test_func: Address of the test function that is being run + * @return 0 if OK, -ve on error + */ +static efi_status_t bootefi_test_prepare(struct efi_loaded_image *image, + struct efi_object *obj, + const char *path, ulong test_func) +{ + efi_status_t ret; + + memset(image, '\0', sizeof(*image)); + memset(obj, '\0', sizeof(*obj)); + /* Construct a dummy device path */ + bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + test_func, test_func); + bootefi_image_path = efi_dp_from_file(NULL, 0, path); + efi_setup_loaded_image(image, obj, bootefi_device_path, + bootefi_image_path); + /* + * gd lives in a fixed register which may get clobbered while we execute + * the payload. So save it here and restore it on every callback entry + */ + efi_save_gd(); + /* Initialize and populate our EFI object list */ + ret = efi_init_obj_list(); + if (ret) + return ret; + /* Transfer environment variable efi_selftest as load options */ + set_load_options(image, "efi_selftest"); + + return 0; +} + +/** + * bootefi_test_finish() - finish up after running an EFI test + * + * @image: Pointer to a struct which holds the loaded image info + * @obj: Pointer to a struct which holds the loaded image object + */ +static void bootefi_test_finish(struct efi_loaded_image *image, + struct efi_object *obj) +{ + efi_restore_gd(); + free(image->load_options); + list_del(&obj->link); +} +#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ + static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) { struct efi_device_path *device_path, *file_path; @@ -350,34 +408,16 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif #ifdef CONFIG_CMD_BOOTEFI_SELFTEST if (!strcmp(argv[1], "selftest")) { - struct efi_loaded_image loaded_image_info = {}; - struct efi_object loaded_image_info_obj = {}; - - /* Construct a dummy device path. */ - bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, - (uintptr_t)&efi_selftest, - (uintptr_t)&efi_selftest); - bootefi_image_path = efi_dp_from_file(NULL, 0, "\selftest"); - - efi_setup_loaded_image(&loaded_image_info, - &loaded_image_info_obj, - bootefi_device_path, bootefi_image_path); - /* - * gd lives in a fixed register which may get clobbered while we - * execute the payload. So save it here and restore it on every - * callback entry - */ - efi_save_gd(); - /* Initialize and populate EFI object list */ - if (efi_init_obj_list()) + struct efi_loaded_image image; + struct efi_object obj; + + if (bootefi_test_prepare(&image, &obj, "\test", + (uintptr_t)&efi_selftest)) return CMD_RET_FAILURE; - /* Transfer environment variable efi_selftest as load options */ - set_load_options(&loaded_image_info, "efi_selftest"); + /* Execute the test */ - r = efi_selftest(loaded_image_info_obj.handle, &systab); - efi_restore_gd(); - free(loaded_image_info.load_options); - list_del(&loaded_image_info_obj.link); + r = efi_selftest(obj.handle, &systab); + bootefi_test_finish(&image, &obj); return r != EFI_SUCCESS; } else #endif

This jumps to test code which can call directly into the EFI support. It does not need a separate image so it is easy to write tests with it.
This test can be executed without causing problems to the run-time environemnt (e.g. U-Boot does not need to reboot afterwards).
For now the test just outputs a message. To try it:
./sandbox/u-boot -c "bootefi test" U-Boot 2017.09-00204-g696c9855fe (Sep 17 2017 - 16:43:53 -0600)
DRAM: 128 MiB MMC: Using default environment
In: serial Out: serial Err: serial SCSI: Net: No ethernet found. IDE: Bus 0: not available Found 0 disks Hello, world! Test passed
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Rebase to master
Changes in v2: - Rebase to master
cmd/bootefi.c | 24 +++++++++++++++++++----- include/efi_loader.h | 3 +++ lib/efi_loader/Kconfig | 10 ++++++++++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_test.c | 17 +++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 lib/efi_loader/efi_test.c
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2a5d66e798..d85d17a9b9 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -297,7 +297,6 @@ exit: return ret; }
-#ifdef CONFIG_CMD_BOOTEFI_SELFTEST /** * bootefi_test_prepare() - prepare to run an EFI test * @@ -353,7 +352,6 @@ static void bootefi_test_finish(struct efi_loaded_image *image, free(image->load_options); list_del(&obj->link); } -#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) { @@ -388,6 +386,8 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) /* Interpreter command to boot an arbitrary EFI image from memory */ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + struct efi_loaded_image image; + struct efi_object obj; char *saddr, *sfdt; unsigned long addr, fdt_addr = 0; efi_status_t r; @@ -406,11 +406,25 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) memcpy((char *)addr, __efi_helloworld_begin, size); } else #endif + if (IS_ENABLED(CONFIG_BOOTEFI_TEST) && !strcmp(argv[1], "test")) { + int ret; + + if (bootefi_test_prepare(&image, &obj, "\test", + (ulong)&efi_test)) + return CMD_RET_FAILURE; + + ret = efi_test(&image, &systab); + bootefi_test_finish(&image, &obj); + if (ret) { + printf("Test failed: err=%d\n", ret); + return CMD_RET_FAILURE; + } + printf("Test passed\n"); + + return 0; + } #ifdef CONFIG_CMD_BOOTEFI_SELFTEST if (!strcmp(argv[1], "selftest")) { - struct efi_loaded_image image; - struct efi_object obj; - if (bootefi_test_prepare(&image, &obj, "\test", (uintptr_t)&efi_selftest)) return CMD_RET_FAILURE; diff --git a/include/efi_loader.h b/include/efi_loader.h index 831883287f..8bb2398c29 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -390,6 +390,9 @@ efi_status_t EFIAPI efi_set_variable(s16 *variable_name, void *efi_bootmgr_load(struct efi_device_path **device_path, struct efi_device_path **file_path);
+/* Perform EFI tests */ +int efi_test(efi_handle_t image_handle, struct efi_system_table *systab); + #else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */
/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 97658f1665..219fc3a51d 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -22,3 +22,13 @@ config EFI_LOADER_BOUNCE_BUFFER Some hardware does not support DMA to full 64bit addresses. For this hardware we can create a bounce buffer so that payloads don't have to worry about platform details. + +config BOOTEFI_TEST + bool "Provide a test for the EFI loader" + depends on EFI_LOADER && SANDBOX + default y + help + Provides a test of the EFI loader functionality accessed via the + command line ('bootefi test'). This runs within U-Boot so does not + need a separate EFI application to work. It aims to include coverage + of all EFI code which can be accessed within sandbox. diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 2722265ee3..44ea145d5b 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o obj-$(CONFIG_NET) += efi_net.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o +obj-$(CONFIG_BOOTEFI_TEST) += efi_test.o diff --git a/lib/efi_loader/efi_test.c b/lib/efi_loader/efi_test.c new file mode 100644 index 0000000000..3fdce78b05 --- /dev/null +++ b/lib/efi_loader/efi_test.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017, Google Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <efi_api.h> + +int efi_test(efi_handle_t image_handle, struct efi_system_table *systable) +{ + struct efi_simple_text_output_protocol *con_out = systable->con_out; + + con_out->output_string(con_out, L"Hello, world!\n"); + + return 0; +}

On 02/19/2018 04:48 PM, Simon Glass wrote:
This jumps to test code which can call directly into the EFI support. It does not need a separate image so it is easy to write tests with it.
This test can be executed without causing problems to the run-time environemnt (e.g. U-Boot does not need to reboot afterwards).
For now the test just outputs a message. To try it:
Please, explain what the use of the command shall be. We already have bootefi selftest. We shouldn't invent the wheel twice.
Best regards
Heinrich
./sandbox/u-boot -c "bootefi test" U-Boot 2017.09-00204-g696c9855fe (Sep 17 2017 - 16:43:53 -0600)
DRAM: 128 MiB MMC: Using default environment
In: serial Out: serial Err: serial SCSI: Net: No ethernet found. IDE: Bus 0: not available Found 0 disks Hello, world! Test passed
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v3:
- Rebase to master
Changes in v2:
Rebase to master
cmd/bootefi.c | 24 +++++++++++++++++++----- include/efi_loader.h | 3 +++ lib/efi_loader/Kconfig | 10 ++++++++++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_test.c | 17 +++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 lib/efi_loader/efi_test.c
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2a5d66e798..d85d17a9b9 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -297,7 +297,6 @@ exit: return ret; }
-#ifdef CONFIG_CMD_BOOTEFI_SELFTEST /**
- bootefi_test_prepare() - prepare to run an EFI test
@@ -353,7 +352,6 @@ static void bootefi_test_finish(struct efi_loaded_image *image, free(image->load_options); list_del(&obj->link); } -#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) { @@ -388,6 +386,8 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) /* Interpreter command to boot an arbitrary EFI image from memory */ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
- struct efi_loaded_image image;
- struct efi_object obj; char *saddr, *sfdt; unsigned long addr, fdt_addr = 0; efi_status_t r;
@@ -406,11 +406,25 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) memcpy((char *)addr, __efi_helloworld_begin, size); } else #endif
- if (IS_ENABLED(CONFIG_BOOTEFI_TEST) && !strcmp(argv[1], "test")) {
int ret;
if (bootefi_test_prepare(&image, &obj, "\\test",
(ulong)&efi_test))
return CMD_RET_FAILURE;
ret = efi_test(&image, &systab);
bootefi_test_finish(&image, &obj);
if (ret) {
printf("Test failed: err=%d\n", ret);
return CMD_RET_FAILURE;
}
printf("Test passed\n");
return 0;
- } #ifdef CONFIG_CMD_BOOTEFI_SELFTEST if (!strcmp(argv[1], "selftest")) {
struct efi_loaded_image image;
struct efi_object obj;
- if (bootefi_test_prepare(&image, &obj, "\test", (uintptr_t)&efi_selftest)) return CMD_RET_FAILURE;
diff --git a/include/efi_loader.h b/include/efi_loader.h index 831883287f..8bb2398c29 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -390,6 +390,9 @@ efi_status_t EFIAPI efi_set_variable(s16 *variable_name, void *efi_bootmgr_load(struct efi_device_path **device_path, struct efi_device_path **file_path);
+/* Perform EFI tests */ +int efi_test(efi_handle_t image_handle, struct efi_system_table *systab);
#else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */
/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 97658f1665..219fc3a51d 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -22,3 +22,13 @@ config EFI_LOADER_BOUNCE_BUFFER Some hardware does not support DMA to full 64bit addresses. For this hardware we can create a bounce buffer so that payloads don't have to worry about platform details.
+config BOOTEFI_TEST
- bool "Provide a test for the EFI loader"
- depends on EFI_LOADER && SANDBOX
- default y
- help
Provides a test of the EFI loader functionality accessed via the
command line ('bootefi test'). This runs within U-Boot so does not
need a separate EFI application to work. It aims to include coverage
of all EFI code which can be accessed within sandbox.
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 2722265ee3..44ea145d5b 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o obj-$(CONFIG_NET) += efi_net.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o +obj-$(CONFIG_BOOTEFI_TEST) += efi_test.o diff --git a/lib/efi_loader/efi_test.c b/lib/efi_loader/efi_test.c new file mode 100644 index 0000000000..3fdce78b05 --- /dev/null +++ b/lib/efi_loader/efi_test.c @@ -0,0 +1,17 @@ +/*
- Copyright (c) 2017, Google Inc. All rights reserved.
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <efi_api.h>
+int efi_test(efi_handle_t image_handle, struct efi_system_table *systable) +{
- struct efi_simple_text_output_protocol *con_out = systable->con_out;
- con_out->output_string(con_out, L"Hello, world!\n");
- return 0;
+}

Hi Heinrich,
On 19 February 2018 at 12:40, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 02/19/2018 04:48 PM, Simon Glass wrote:
This jumps to test code which can call directly into the EFI support. It does not need a separate image so it is easy to write tests with it.
This test can be executed without causing problems to the run-time environemnt (e.g. U-Boot does not need to reboot afterwards).
For now the test just outputs a message. To try it:
Please, explain what the use of the command shall be. We already have bootefi selftest. We shouldn't invent the wheel twice.
These are different wheels, With 'selftest' we build an EFI application and run it as a binary. With 'test' we just call into the U-Boot code. IMO the latter is much easier to debug and test since it is a single application - e.g. it can be run entirely within gdb.
Regards, Simon

Reorder the code a little so we can (in a future commit) use a common function for some of the init.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add new patch to reorder code in do_bootefi_exec()
Changes in v2: None
cmd/bootefi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d85d17a9b9..cdfa22ee4c 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -202,20 +202,23 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, assert(device_path && image_path); }
+ efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, + device_path, image_path); + /* Initialize and populate EFI object list */ ret = efi_init_obj_list(); if (ret) return ret;
- efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, - device_path, image_path); - /* * gd lives in a fixed register which may get clobbered while we execute * the payload. So save it here and restore it on every callback entry */ efi_save_gd();
+ /* Transfer environment variable bootargs as load options */ + set_load_options(&loaded_image_info, "bootargs"); + if (fdt && !fdt_check_header(fdt)) { /* Prepare fdt for payload */ fdt = copy_fdt(fdt); @@ -242,8 +245,6 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, efi_install_configuration_table(&fdt_guid, NULL); }
- /* Transfer environment variable bootargs as load options */ - set_load_options(&loaded_image_info, "bootargs"); /* Load the EFI payload */ entry = efi_load_pe(efi, &loaded_image_info); if (!entry) {

Add a new bootefi_run_prepare() function which holds common code used to set up U-Boot to run EFI code. Make use of this from the existing bootefi_test_prepare() function, as well as do_bootefi_exec().
Also shorten a few variable names.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add patch to create a function to set up for running EFI code
Changes in v2: None
cmd/bootefi.c | 96 ++++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 54 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index cdfa22ee4c..45f2b6c818 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -169,6 +169,33 @@ static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)( } #endif
+static efi_status_t bootefi_run_prepare(struct efi_loaded_image *image, + struct efi_object *obj, + const char *path, + struct efi_device_path *device_path, + struct efi_device_path *image_path) +{ + efi_status_t ret; + + efi_setup_loaded_image(image, obj, device_path, image_path); + + /* Initialize and populate EFI object list */ + ret = efi_init_obj_list(); + if (ret) + return ret; + + /* + * gd lives in a fixed register which may get clobbered while we execute + * the payload. So save it here and restore it on every callback entry + */ + efi_save_gd(); + + /* Transfer environment variable bootargs as load options */ + set_load_options(image, path); + + return 0; +} + /* * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. @@ -177,8 +204,8 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, struct efi_device_path *device_path, struct efi_device_path *image_path) { - struct efi_loaded_image loaded_image_info = {}; - struct efi_object loaded_image_info_obj = {}; + struct efi_loaded_image image; + struct efi_object obj; struct efi_device_path *memdp = NULL; ulong ret;
@@ -202,23 +229,8 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, assert(device_path && image_path); }
- efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, - device_path, image_path); - - /* Initialize and populate EFI object list */ - ret = efi_init_obj_list(); - if (ret) - return ret; - - /* - * gd lives in a fixed register which may get clobbered while we execute - * the payload. So save it here and restore it on every callback entry - */ - efi_save_gd(); - - /* Transfer environment variable bootargs as load options */ - set_load_options(&loaded_image_info, "bootargs"); - + ret = bootefi_run_prepare(&image, &obj, "bootargs", device_path, + image_path); if (fdt && !fdt_check_header(fdt)) { /* Prepare fdt for payload */ fdt = copy_fdt(fdt); @@ -246,7 +258,7 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, }
/* Load the EFI payload */ - entry = efi_load_pe(efi, &loaded_image_info); + entry = efi_load_pe(efi, &image); if (!entry) { ret = -ENOENT; goto exit; @@ -254,10 +266,10 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt,
if (memdp) { struct efi_device_path_memory *mdp = (void *)memdp; - mdp->memory_type = loaded_image_info.image_code_type; - mdp->start_address = (uintptr_t)loaded_image_info.image_base; + mdp->memory_type = image.image_code_type; + mdp->start_address = (uintptr_t)image.image_base; mdp->end_address = mdp->start_address + - loaded_image_info.image_size; + image.image_size; }
/* we don't support much: */ @@ -267,8 +279,8 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
- if (setjmp(&loaded_image_info.exit_jmp)) { - ret = loaded_image_info.exit_status; + if (setjmp(&image.exit_jmp)) { + ret = image.exit_status; goto exit; }
@@ -280,7 +292,7 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt,
/* Move into EL2 and keep running there */ armv8_switch_to_el2((ulong)entry, - (ulong)&loaded_image_info_obj.handle, + (ulong)&obj.handle, (ulong)&systab, 0, (ulong)efi_run_in_el2, ES_TO_AARCH64);
@@ -289,11 +301,11 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, } #endif
- ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry); + ret = efi_do_enter(obj.handle, &systab, entry);
exit: /* image has returned, loaded-image obj goes *poof*: */ - list_del(&loaded_image_info_obj.link); + list_del(&obj.link);
return ret; } @@ -315,29 +327,14 @@ static efi_status_t bootefi_test_prepare(struct efi_loaded_image *image, struct efi_object *obj, const char *path, ulong test_func) { - efi_status_t ret; - memset(image, '\0', sizeof(*image)); memset(obj, '\0', sizeof(*obj)); /* Construct a dummy device path */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, test_func, test_func); bootefi_image_path = efi_dp_from_file(NULL, 0, path); - efi_setup_loaded_image(image, obj, bootefi_device_path, - bootefi_image_path); - /* - * gd lives in a fixed register which may get clobbered while we execute - * the payload. So save it here and restore it on every callback entry - */ - efi_save_gd(); - /* Initialize and populate our EFI object list */ - ret = efi_init_obj_list(); - if (ret) - return ret; - /* Transfer environment variable efi_selftest as load options */ - set_load_options(image, "efi_selftest"); - - return 0; + return bootefi_run_prepare(image, obj, path, bootefi_device_path, + bootefi_image_path); }
/** @@ -360,15 +357,6 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) void *addr; efi_status_t r;
- /* Initialize and populate EFI object list */ - efi_init_obj_list(); - - /* - * gd lives in a fixed register which may get clobbered while we execute - * the payload. So save it here and restore it on every callback entry - */ - efi_save_gd(); - addr = efi_bootmgr_load(&device_path, &file_path); if (!addr) return 1;

This function can be used from do_bootefi_exec() so that we use mostly the same code for a normal EFI application and an EFI test.
Rename the function and use it in both places.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Add new patch to rename bootefi_test_finish() to bootefi_run_finish()
Changes in v2: None
cmd/bootefi.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 45f2b6c818..f2bcb420ba 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -196,6 +196,20 @@ static efi_status_t bootefi_run_prepare(struct efi_loaded_image *image, return 0; }
+/** + * bootefi_run_finish() - finish up after running an EFI test + * + * @image: Pointer to a struct which holds the loaded image info + * @obj: Pointer to a struct which holds the loaded image object + */ +static void bootefi_run_finish(struct efi_loaded_image *image, + struct efi_object *obj) +{ + efi_restore_gd(); + free(image->load_options); + list_del(&obj->link); +} + /* * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. @@ -304,8 +318,7 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt, ret = efi_do_enter(obj.handle, &systab, entry);
exit: - /* image has returned, loaded-image obj goes *poof*: */ - list_del(&obj.link); + bootefi_run_finish(&image, &obj);
return ret; } @@ -337,20 +350,6 @@ static efi_status_t bootefi_test_prepare(struct efi_loaded_image *image, bootefi_image_path); }
-/** - * bootefi_test_finish() - finish up after running an EFI test - * - * @image: Pointer to a struct which holds the loaded image info - * @obj: Pointer to a struct which holds the loaded image object - */ -static void bootefi_test_finish(struct efi_loaded_image *image, - struct efi_object *obj) -{ - efi_restore_gd(); - free(image->load_options); - list_del(&obj->link); -} - static int do_bootefi_bootmgr_exec(unsigned long fdt_addr) { struct efi_device_path *device_path, *file_path; @@ -403,7 +402,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_FAILURE;
ret = efi_test(&image, &systab); - bootefi_test_finish(&image, &obj); + bootefi_run_finish(&image, &obj); if (ret) { printf("Test failed: err=%d\n", ret); return CMD_RET_FAILURE; @@ -420,7 +419,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/* Execute the test */ r = efi_selftest(obj.handle, &systab); - bootefi_test_finish(&image, &obj); + bootefi_run_finish(&image, &obj); return r != EFI_SUCCESS; } else #endif

Hi Heinrich,
On 19 February 2018 at 08:48, Simon Glass sjg@chromium.org wrote:
A limitation of the EFI loader at present is that it does not build with sandbox. This makes it hard to write tests, since sandbox is used for most testing in U-Boot.
This series enables the EFI loader feature. It allows sandbox to build and run a trivial function which calls the EFI API to output a message.
This series is at u-boot-dm/efi-working
Changes in v3:
- Add new patch to init the 'rows' and 'cols' variables
- Return error value of efi_allocate_pages()
- Update function comment for write_smbios_table()
- Add comments on aligment
- Avoid adding a new call to efi_init_obj_list()
- Fix spelling of initalized
- Drop incorrect map_sysmem() in map_sysmem()
- Init the 'rows' and 'cols' vars to avoid a compiler error (gcc 4.8.4)
- Add new patch to split out test init/uninit into functions
- Rebase to master
- Add new patch to reorder code in do_bootefi_exec()
- Add patch to create a function to set up for running EFI code
- Add new patch to rename bootefi_test_finish() to bootefi_run_finish()
Changes in v2:
- Update return type of efi_smbios_register() to efi_status_t
- Use return value of efi_install_configuration_table
- Change return type of efi_init_obj_list() to efi_status_t
- Convert #ifdef CONFIG_GENERATE_SMBIOS_TABLE to if()
- Update commit message to dropping libfdt_env.h
- Update to use mapmem instead of a cast
- Rebase to master
Simon Glass (21): efi: Init the 'rows' and 'cols' variables efi: Update efi_smbios_register() to return error code efi: Move the init check inside efi_init_obj_list() efi: Add error checking for efi_init_obj_list() efi: Add a TODO to efi_init_obj_list() efi: Correct header order in efi_memory efi: sandbox: Adjust memory usage for sandbox sandbox: smbios: Update to support sandbox
There is still apparently a problem in this patch (or another) as I get a failure on the qemu test:
https://travis-ci.org/sglass68/u-boot/jobs/343095040
But I have been sitting on this for a while and wanted to get it out.
sandbox: Add a setjmp() implementation efi: sandbox: Add required linker sections efi: sandbox: Add distroboot support Define board_quiesce_devices() in a shared location Add a comment for board_quiesce_devices() efi: sandbox: Add relocation constants efi: Add a comment about duplicated ELF constants efi: sandbox: Enable EFI loader builder for sandbox efi: Split out test init/uninit into functions efi: sandbox: Add a simple 'bootefi test' command efi: Reorder code in do_bootefi_exec() efi: Create a function to set up for running EFI code efi: Rename bootefi_test_finish() to bootefi_run_finish()
arch/arm/include/asm/u-boot-arm.h | 1 - arch/sandbox/cpu/cpu.c | 13 ++ arch/sandbox/cpu/os.c | 17 +++ arch/sandbox/cpu/u-boot.lds | 29 +++++ arch/sandbox/include/asm/setjmp.h | 21 ++++ arch/sandbox/lib/Makefile | 2 +- arch/sandbox/lib/sections.c | 12 ++ arch/x86/include/asm/u-boot-x86.h | 1 - arch/x86/lib/bootm.c | 4 - cmd/bootefi.c | 203 +++++++++++++++++++----------- common/bootm.c | 4 + include/bootm.h | 8 ++ include/config_distro_bootcmd.h | 2 +- include/efi_loader.h | 12 +- include/os.h | 21 ++++ include/smbios.h | 5 +- lib/efi_loader/Kconfig | 12 +- lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_console.c | 2 +- lib/efi_loader/efi_memory.c | 36 +++--- lib/efi_loader/efi_runtime.c | 7 ++ lib/efi_loader/efi_smbios.c | 18 ++- lib/efi_loader/efi_test.c | 17 +++ lib/smbios.c | 32 +++-- 24 files changed, 367 insertions(+), 113 deletions(-) create mode 100644 arch/sandbox/include/asm/setjmp.h create mode 100644 arch/sandbox/lib/sections.c create mode 100644 lib/efi_loader/efi_test.c
-- 2.16.1.291.g4437f3f132-goog
Regards, Simon

On 02/19/2018 04:48 PM, Simon Glass wrote:
A limitation of the EFI loader at present is that it does not build with sandbox. This makes it hard to write tests, since sandbox is used for most testing in U-Boot.
This series enables the EFI loader feature. It allows sandbox to build and run a trivial function which calls the EFI API to output a message.
This series is at u-boot-dm/efi-working
Hello Simon,
it seems we have some overlap in our patch series, cf https://lists.denx.de/pipermail/u-boot/2018-February/320487.html
Best regards
Heinrich

On 02/19/2018 04:48 PM, Simon Glass wrote:
A limitation of the EFI loader at present is that it does not build with sandbox. This makes it hard to write tests, since sandbox is used for most testing in U-Boot.
This series enables the EFI loader feature. It allows sandbox to build and run a trivial function which calls the EFI API to output a message.
This series is at u-boot-dm/efi-working
Hello Alex,
could you, please, start building efi_next for v2018.05. Simon and I need a common basis for our patches.
There is a big overlap between the start of this patch series and https://lists.denx.de/pipermail/u-boot/2018-February/320487.html
Could you, please, review the two and give us your feedback.
Best regards
Heinrich
participants (3)
-
Heinrich Schuchardt
-
Peter Robinson
-
Simon Glass