[PATCH v2 00/19] efi: Support booting an OS with the EFI app on ARM

From: Simon Glass <sjg@chromium.org> The ARM EFI app does not successfully boot an OS at present. This series includes patches to allow it to boot an OS via extlinux: The main changes are: - Call exit-boot-services before jumping to the OS - Write the physical-memory info to the FDT - Tidy up some Kconfig options - Improve keyboard compatibility Note that QEMU 8.2 does not boot Ubuntu 24.04 with this series[1]. The kernel dies quite early with: ERROR:target/arm/internals.h:767:regime_is_user: code should not be reached Bail out! ERROR:target/arm/internals.h:767:regime_is_user: code should not be reached QEMU 9.2 resolves this problem. [1] https://lists.opensuse.org/archives/list/bugs@lists.opensuse.org/ message/XVO4M4LDEFOORP5M4ZFINZDX36DWO3G5/ Changes in v2: - Add a comment to serial_efi_get_key() about the 1ms delay Simon Glass (19): treewide: Correct paramters typo scripts: Add an option for the build directory efi: Move efi_store_memory_map() to the stub efi: Adjust serial to work better on real devices efi: Use the same format for all EFI_GUID() declarations efi: Add a few more GUIDs efi: Move memory-map dumping into a common file efi: Add a function to obtain the memory type as a string efi: Run happily without a video display efi: Rename efi_block_device driver efi: Exit EFI boot-services before starting the next app efi: Set the FDT address for QEMU efi: boot: Correct calculation of load address in app efi: Update the ARM app to boot from extlinux efi: arm: Expand app to use 512M of memory efi: arm: Add the memory map to the FDT efi: arm: Increase the cyclic timeout test: Provide a test for the ARM EFI app booting Ubuntu CI: Provide a QEMU instance for efi-arm_app64 .gitlab-ci.yml | 6 + arch/arm/include/asm/arch-mx6/mx6_plugin.S | 2 +- arch/arm/include/asm/arch-mx7/mx7_plugin.S | 2 +- board/efi/efi-arm_app/board.c | 30 ++++ board/efi/efi-arm_app/efi-arm_app.env | 1 + boot/bootm.c | 2 + cmd/efi.c | 119 +------------- configs/efi-arm_app64_defconfig | 4 + drivers/ddr/fsl/options.c | 2 +- drivers/ddr/marvell/axp/ddr3_spd.c | 2 +- drivers/serial/serial_efi.c | 37 ++++- drivers/video/efi.c | 8 +- include/efi.h | 46 +++++- include/efi_api.h | 178 +++++++++++---------- include/image.h | 2 +- lib/efi/Makefile | 1 + lib/efi/memory.c | 132 +++++++++++++++ lib/efi_client/efi.c | 48 ------ lib/efi_client/efi_app.c | 64 +++++++- lib/efi_client/stub.c | 57 +++++++ lib/efi_driver/efi_block_device.c | 2 +- lib/uuid.c | 4 + scripts/build-efi | 19 ++- scripts/build_helper.py | 1 + test/py/tests/test_distro.py | 22 ++- 25 files changed, 517 insertions(+), 274 deletions(-) create mode 100644 lib/efi/memory.c -- 2.43.0 base-commit: 97a083c86cfaab2268dc8a0f90aedbac6d419738 branch: loadn2

From: Simon Glass <sjg@chromium.org> This typo appears a handful of times in U-Boot. Fix it. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) arch/arm/include/asm/arch-mx6/mx6_plugin.S | 2 +- arch/arm/include/asm/arch-mx7/mx7_plugin.S | 2 +- drivers/ddr/fsl/options.c | 2 +- drivers/ddr/marvell/axp/ddr3_spd.c | 2 +- include/image.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/arch-mx6/mx6_plugin.S b/arch/arm/include/asm/arch-mx6/mx6_plugin.S index 4d12c6873b3..6209e20ee1e 100644 --- a/arch/arm/include/asm/arch-mx6/mx6_plugin.S +++ b/arch/arm/include/asm/arch-mx6/mx6_plugin.S @@ -108,7 +108,7 @@ mmu_disable_notreq: /* To return to ROM from plugin, we need to fill in these argument. * Here is what need to do: - * Need to construct the paramters for this function before return to ROM: + * Need to construct the parameters for this function before return to ROM: * plugin_download(void **start, size_t *bytes, UINT32 *ivt_offset) */ pop {r0-r4, lr} diff --git a/arch/arm/include/asm/arch-mx7/mx7_plugin.S b/arch/arm/include/asm/arch-mx7/mx7_plugin.S index b552542e281..1031e53feee 100644 --- a/arch/arm/include/asm/arch-mx7/mx7_plugin.S +++ b/arch/arm/include/asm/arch-mx7/mx7_plugin.S @@ -64,7 +64,7 @@ after_calling_rom___pu_irom_hwcnfg_setup: /* To return to ROM from plugin, we need to fill in these argument. * Here is what need to do: - * Need to construct the paramters for this function before return to ROM: + * Need to construct the parameters for this function before return to ROM: * plugin_download(void **start, size_t *bytes, UINT32 *ivt_offset) */ pop {r0-r4, lr} diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 852a5d0eca4..0d4ec7b140a 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -890,7 +890,7 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm, /* Memory Organization Parameters */ popts->registered_dimm_en = common_dimm->all_dimms_registered; - /* Operational Mode Paramters */ + /* Operational Mode Parameters */ /* Pick ECC modes */ popts->ecc_mode = 0; /* 0 = disabled, 1 = enabled */ diff --git a/drivers/ddr/marvell/axp/ddr3_spd.c b/drivers/ddr/marvell/axp/ddr3_spd.c index c169a8ea16b..8c3667531d2 100644 --- a/drivers/ddr/marvell/axp/ddr3_spd.c +++ b/drivers/ddr/marvell/axp/ddr3_spd.c @@ -976,7 +976,7 @@ int ddr3_dunit_setup(u32 ecc_ena, u32 hclk_time, u32 *ddr_width) #endif /* - * In case of mixed dimm and on-board devices setup paramters will + * In case of mixed dimm and on-board devices setup parameters will * be taken statically */ /*{0x00001494} - DDR SDRAM ODT Control (Low) Register */ diff --git a/include/image.h b/include/image.h index 6a4cb912bc4..7f3ca1088de 100644 --- a/include/image.h +++ b/include/image.h @@ -1110,7 +1110,7 @@ int image_setup_libfdt(struct bootm_headers *images, void *blob, bool lmb); * Set up the FDT to use for booting a kernel * * This performs ramdisk setup, sets up the FDT if required, and adds - * paramters to the FDT if libfdt is available. + * parameters to the FDT if libfdt is available. * * @param images Images information * Return: 0 if ok, <0 on failure -- 2.43.0

From: Simon Glass <sjg@chromium.org> When running in CI it is better to specify the build directory rather than provide a device. Add a --build-dir option. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) scripts/build-efi | 19 +++++++++++++------ scripts/build_helper.py | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/scripts/build-efi b/scripts/build-efi index bbc11c2fd2d..f4c96dad7bd 100755 --- a/scripts/build-efi +++ b/scripts/build-efi @@ -60,8 +60,10 @@ class BuildEfi: def __init__(self, args): self.helper = build_helper.Helper(args) self.helper.read_settings() - self.img = self.helper.get_setting('efi_image_file', 'efi.img') - self.build_dir = self.helper.get_setting("build_dir", '/tmp') + self.img_fname = self.helper.get_setting('efi_image_file', 'efi.img') + self.img = None + self.build_topdir = self.helper.get_setting("build_dir", '/tmp') + self.build_dir = None self.args = args self.imagedir = Path(self.helper.get_setting('image_dir', '~/dev')) @@ -146,13 +148,12 @@ class BuildEfi: print(f'Packaging {build}') fname = f'u-boot-{build_type}.efi' tools.write_file(f'{dst}/startup.nsh', f'fs0:{fname}', binary=False) - shutil.copy(f'{self.build_dir}/{build}/{fname}', dst) + shutil.copy(f'{self.build_dir}/{fname}', dst) def do_build(self, build): """Build U-Boot for the selected board""" - res = command.run_one('buildman', '-w', '-o', - f'{self.build_dir}/{build}', '--board', build, - '-I', raise_on_error=False) + res = command.run_one('buildman', '-w', '-o', self.build_dir, + '--board', build, '-I', raise_on_error=False) if res.return_code and res.return_code != 101: # Allow warnings raise ValueError( f'buildman exited with {res.return_code}: {res.combined}') @@ -164,6 +165,12 @@ class BuildEfi: build_type = 'payload' if args.payload else 'app' build = f'efi-{arch}_{build_type}{self.helper.bitness}' + if args.build_dir: + self.build_dir = args.build_dir + self.img = f'{self.build_dir}/{self.img_fname}' + else: + self.build_dir = f'{self.build_topdir}/{build}' + self.img = self.img_fname if not args.no_build: self.do_build(build) diff --git a/scripts/build_helper.py b/scripts/build_helper.py index 72d4a8734f9..21162e5643e 100644 --- a/scripts/build_helper.py +++ b/scripts/build_helper.py @@ -287,6 +287,7 @@ def add_common_args(parser): help='Select architecture (arm, x86) Default: arm') parser.add_argument('-B', '--no-build', action='store_true', help="Don't build; assume a build exists") + parser.add_argument('--build-dir', help='Directory to use for the build') parser.add_argument('-C', '--enable-console', action='store_true', help="Enable linux console (x86 only)") parser.add_argument('-d', '--disk', nargs='*', -- 2.43.0

From: Simon Glass <sjg@chromium.org> This function is not called from the app at present. Even if it were, it would be called later, after stdio is working, so there is no need to use printhex2() and the like. Move the function into the stub. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) include/efi.h | 11 --------- lib/efi_client/efi.c | 48 ------------------------------------ lib/efi_client/stub.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 59 deletions(-) diff --git a/include/efi.h b/include/efi.h index c7de1f82ac7..11966ffc417 100644 --- a/include/efi.h +++ b/include/efi.h @@ -666,17 +666,6 @@ void efi_puts(struct efi_priv *priv, const char *str); */ void efi_putc(struct efi_priv *priv, const char ch); -/** - * efi_store_memory_map() - Collect the memory-map info from EFI - * - * Collect the memory info and store it for later use, e.g. in calling - * exit_boot_services() - * - * @priv: Pointer to private EFI structure - * Returns: 0 if OK, non-zero on error - */ -int efi_store_memory_map(struct efi_priv *priv); - /** * efi_stub_exit_boot_services() - Handle the exit-boot-service procedure * diff --git a/lib/efi_client/efi.c b/lib/efi_client/efi.c index e670e1f7169..c5573dd67f9 100644 --- a/lib/efi_client/efi.c +++ b/lib/efi_client/efi.c @@ -191,51 +191,3 @@ void efi_free_pool(void *ptr) efi_free(priv, ptr); } - -int efi_store_memory_map(struct efi_priv *priv) -{ - struct efi_boot_services *boot = priv->sys_table->boottime; - efi_uintn_t size, desc_size; - efi_status_t ret; - - /* Get the memory map so we can switch off EFI */ - size = 0; - ret = boot->get_memory_map(&size, NULL, &priv->memmap_key, - &priv->memmap_desc_size, - &priv->memmap_version); - if (ret != EFI_BUFFER_TOO_SMALL) { - /* - * Note this function avoids using printf() since it is not - * available in the stub - */ - printhex2(EFI_BITS_PER_LONG); - putc(' '); - printhex2(ret); - puts(" No memory map\n"); - return ret; - } - /* - * Since doing a malloc() may change the memory map and also we want to - * be able to read the memory map in efi_call_exit_boot_services() - * below, after more changes have happened - */ - priv->memmap_alloc = size + 1024; - priv->memmap_size = priv->memmap_alloc; - priv->memmap_desc = efi_malloc(priv, size, &ret); - if (!priv->memmap_desc) { - printhex2(ret); - puts(" No memory for memory descriptor\n"); - return ret; - } - - ret = boot->get_memory_map(&priv->memmap_size, priv->memmap_desc, - &priv->memmap_key, &desc_size, - &priv->memmap_version); - if (ret) { - printhex2(ret); - puts(" Can't get memory map\n"); - return ret; - } - - return 0; -} diff --git a/lib/efi_client/stub.c b/lib/efi_client/stub.c index 27366937c18..01d62c3e5c9 100644 --- a/lib/efi_client/stub.c +++ b/lib/efi_client/stub.c @@ -127,6 +127,63 @@ static void efi_copy_code(struct efi_priv *priv) (ulong)_binary_u_boot_bin_start); } +/** + * efi_store_memory_map() - Collect the memory-map info from EFI + * + * Collect the memory info and store it for later use, e.g. in calling + * exit_boot_services() + * + * @priv: Pointer to private EFI structure + * Returns: 0 if OK, non-zero on error + */ +static int efi_store_memory_map(struct efi_priv *priv) +{ + struct efi_boot_services *boot = priv->sys_table->boottime; + efi_uintn_t size, desc_size; + efi_status_t ret; + + /* Get the memory map so we can switch off EFI */ + size = 0; + ret = boot->get_memory_map(&size, NULL, &priv->memmap_key, + &priv->memmap_desc_size, + &priv->memmap_version); + if (ret != EFI_BUFFER_TOO_SMALL) { + /* + * Note this function avoids using printf() since it is not + * available in the stub + */ + printhex2(EFI_BITS_PER_LONG); + putc(' '); + printhex2(ret); + puts(" No memory map\n"); + return ret; + } + /* + * Since doing a malloc() may change the memory map and also we want to + * be able to read the memory map in efi_call_exit_boot_services() + * below, after more changes have happened + */ + priv->memmap_alloc = size + 1024; + priv->memmap_size = priv->memmap_alloc; + priv->memmap_desc = efi_malloc(priv, size, &ret); + if (!priv->memmap_desc) { + printhex2(ret); + puts(" No memory for memory descriptor\n"); + return ret; + } + + ret = boot->get_memory_map(&priv->memmap_size, priv->memmap_desc, + &priv->memmap_key, &desc_size, + &priv->memmap_version); + if (ret) { + printhex2(ret); + puts(" Can't get memory map\n"); + return ret; + } + + return 0; +} + /** * efi_main() - Start an EFI image * -- 2.43.0

From: Simon Glass <sjg@chromium.org> The EFI serial driver checks for keypresses but does not allow other events to be processed. For devices which have a USB keyboard, the USB message must be processed before any keys can emerge for the serial driver to pick up. Add a periodic timer to the list of events. This allows the keyboard to work on Qualcomm laptops, for example. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Add a comment to serial_efi_get_key() about the 1ms delay drivers/serial/serial_efi.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c index 5733eaaf9d4..b506bb18ffb 100644 --- a/drivers/serial/serial_efi.c +++ b/drivers/serial/serial_efi.c @@ -19,7 +19,9 @@ struct serial_efi_priv { struct efi_simple_text_input_protocol *con_in; struct efi_simple_text_output_protocol *con_out; + struct efi_boot_services *boot; struct efi_input_key key; + struct efi_event *timer; bool have_key; }; @@ -31,12 +33,32 @@ int serial_efi_setbrg(struct udevice *dev, int baudrate) return 0; } +/** + * serial_efi_get_key() - Read a keystroke, waiting up to 1ms + * + * Checks for a key, while allowing the EFI system to process other events. + * + * Return: 0 if a keystroke was read, -EAGAIN if there is no keystroke yet, -EIO + * if reading the keystroke failed + */ static int serial_efi_get_key(struct serial_efi_priv *priv) { - int ret; + struct efi_simple_text_input_protocol *cin = priv->con_in; + struct efi_event *events[2] = {cin->wait_for_key, priv->timer}; + efi_uintn_t index; + efi_status_t ret; if (priv->have_key) return 0; + + ret = priv->boot->wait_for_event(2, events, &index); + if (ret) { + log_err("wait_for_event() failed\n"); + return -EAGAIN; + } + if (index) + return -EAGAIN; + ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key); if (ret == EFI_NOT_READY) return -EAGAIN; @@ -133,9 +155,22 @@ static int serial_efi_probe(struct udevice *dev) { struct efi_system_table *table = efi_get_sys_table(); struct serial_efi_priv *priv = dev_get_priv(dev); + struct efi_boot_services *boot = efi_get_boot(); + efi_status_t ret; priv->con_in = table->con_in; priv->con_out = table->con_out; + priv->con_in->reset(priv->con_in, true); + priv->boot = boot; + + ret = boot->create_event(EVT_TIMER, TPL_APPLICATION, NULL, NULL, + &priv->timer); + if (ret) + return -ECOMM; + ret = boot->set_timer(priv->timer, EFI_TIMER_PERIODIC, + 1000 * 1000 / 100 /* 1ms in 100ns units */); + if (ret) + return -ECOMM; return 0; } -- 2.43.0

From: Simon Glass <sjg@chromium.org> The declarations in efi_api.h are inconsistent. Tidy them up, so that the final 8 bytes appear on their own line aways. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) include/efi_api.h | 162 +++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 9b795c2a20d..d81a4d96694 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -217,26 +217,26 @@ enum efi_reset_type { #define CAPSULE_SUPPORT_DEPENDENCY 0x0000000000000002 #define EFI_CAPSULE_REPORT_GUID \ - EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \ - 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) + EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, \ + 0xb6, 0xec, 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) #define EFI_MEMORY_RANGE_CAPSULE_GUID \ - EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \ - 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72) + EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, \ + 0x97, 0x7a, 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72) #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \ - EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \ - 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a) + EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, \ + 0xbd, 0xa1, 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a) #define EFI_CONFORMANCE_PROFILES_TABLE_GUID \ - EFI_GUID(0x36122546, 0xf7ef, 0x4c8f, 0xbd, 0x9b, \ - 0xeb, 0x85, 0x25, 0xb5, 0x0c, 0x0b) + EFI_GUID(0x36122546, 0xf7ef, 0x4c8f, \ + 0xbd, 0x9b, 0xeb, 0x85, 0x25, 0xb5, 0x0c, 0x0b) #define EFI_CONFORMANCE_PROFILES_TABLE_VERSION 1 #define EFI_CONFORMANCE_PROFILE_EBBR_2_1_GUID \ - EFI_GUID(0xcce33c35, 0x74ac, 0x4087, 0xbc, 0xe7, \ - 0x8b, 0x29, 0xb0, 0x2e, 0xeb, 0x27) + EFI_GUID(0xcce33c35, 0x74ac, 0x4087, \ + 0xbc, 0xe7, 0x8b, 0x29, 0xb0, 0x2e, 0xeb, 0x27) struct efi_conformance_profiles_table { u16 version; @@ -315,8 +315,8 @@ struct efi_capsule_result_variable_fmp { #define EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO 0x2000 #define EFI_RT_PROPERTIES_TABLE_GUID \ - EFI_GUID(0xeb66918a, 0x7eef, 0x402a, 0x84, 0x2e, \ - 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9) + EFI_GUID(0xeb66918a, 0x7eef, 0x402a, \ + 0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9) #define EFI_RT_PROPERTIES_TABLE_VERSION 0x1 @@ -380,48 +380,48 @@ struct efi_runtime_services { /* EFI event group GUID definitions */ #define EFI_EVENT_GROUP_EXIT_BOOT_SERVICES \ - EFI_GUID(0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, \ - 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf) + EFI_GUID(0x27abf055, 0xb1b8, 0x4c26, \ + 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf) #define EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES \ - EFI_GUID(0x8be0e274, 0x3970, 0x4b44, 0x80, 0xc5, \ - 0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc) + EFI_GUID(0x8be0e274, 0x3970, 0x4b44, \ + 0x80, 0xc5, 0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc) #define EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE \ - EFI_GUID(0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, \ - 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96) + EFI_GUID(0x13fa7698, 0xc831, 0x49c7, \ + 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96) #define EFI_EVENT_GROUP_MEMORY_MAP_CHANGE \ - EFI_GUID(0x78bee926, 0x692f, 0x48fd, 0x9e, 0xdb, \ - 0x01, 0x42, 0x2e, 0xf0, 0xd7, 0xab) + EFI_GUID(0x78bee926, 0x692f, 0x48fd, \ + 0x9e, 0xdb, 0x01, 0x42, 0x2e, 0xf0, 0xd7, 0xab) #define EFI_EVENT_GROUP_READY_TO_BOOT \ - EFI_GUID(0x7ce88fb3, 0x4bd7, 0x4679, 0x87, 0xa8, \ - 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b) + EFI_GUID(0x7ce88fb3, 0x4bd7, 0x4679, \ + 0x87, 0xa8, 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b) #define EFI_EVENT_GROUP_AFTER_READY_TO_BOOT \ - EFI_GUID(0x3a2a00ad, 0x98b9, 0x4cdf, 0xa4, 0x78, \ - 0x70, 0x27, 0x77, 0xf1, 0xc1, 0xb) + EFI_GUID(0x3a2a00ad, 0x98b9, 0x4cdf, \ + 0xa4, 0x78, 0x70, 0x27, 0x77, 0xf1, 0xc1, 0xb) #define EFI_EVENT_GROUP_RESET_SYSTEM \ - EFI_GUID(0x62da6a56, 0x13fb, 0x485a, 0xa8, 0xda, \ - 0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b) + EFI_GUID(0x62da6a56, 0x13fb, 0x485a, \ + 0xa8, 0xda, 0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b) #define EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR \ - EFI_GUID(0xb4a40fe6, 0x9149, 0x4f29, 0x94, 0x47, \ - 0x49, 0x38, 0x7a, 0x7f, 0xab, 0x87) + EFI_GUID(0xb4a40fe6, 0x9149, 0x4f29, \ + 0x94, 0x47, 0x49, 0x38, 0x7a, 0x7f, 0xab, 0x87) /* EFI Configuration Table and GUID definitions */ #define NULL_GUID \ - EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + EFI_GUID(0x00000000, 0x0000, 0x0000, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) #define EFI_GLOBAL_VARIABLE_GUID \ - EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \ - 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) + EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, \ + 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) #define EFI_IMAGE_SECURITY_DATABASE_GUID \ - EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, \ - 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) + EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, \ + 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) #define EFI_FDT_GUID \ EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, \ @@ -432,7 +432,7 @@ struct efi_runtime_services { 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SMBIOS_TABLE_GUID \ - EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \ + EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \ 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) #define SMBIOS3_TABLE_GUID \ @@ -448,24 +448,24 @@ struct efi_runtime_services { 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d) #define EFI_TCG2_FINAL_EVENTS_TABLE_GUID \ - EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, \ - 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) + EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, \ + 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) #define EFI_RNG_PROTOCOL_GUID \ - EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, \ - 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) + EFI_GUID(0x3152bca5, 0xeade, 0x433d, \ + 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) #define EFI_DT_FIXUP_PROTOCOL_GUID \ - EFI_GUID(0xe617d64c, 0xfe08, 0x46da, 0xf4, 0xdc, \ - 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00) + EFI_GUID(0xe617d64c, 0xfe08, 0x46da, \ + 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00) #define EFI_TCG2_PROTOCOL_GUID \ - EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, \ - 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f) + EFI_GUID(0x607f766c, 0x7455, 0x42be, \ + 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f) #define RISCV_EFI_BOOT_PROTOCOL_GUID \ - EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, \ - 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf) + EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, \ + 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf) /** * struct efi_configuration_table - EFI Configuration Table @@ -2166,57 +2166,57 @@ struct efi_system_resource_table { /* Certificate types in signature database */ #define EFI_CERT_SHA1_GUID \ - EFI_GUID(0x826ca512, 0xcf10, 0x4ac9, 0xb1, 0x87, \ - 0xbe, 0x01, 0x49, 0x66, 0x31, 0xbd) + EFI_GUID(0x826ca512, 0xcf10, 0x4ac9, \ + 0xb1, 0x87, 0xbe, 0x01, 0x49, 0x66, 0x31, 0xbd) #define EFI_CERT_SHA224_GUID \ - EFI_GUID(0xb6e5233, 0xa65c, 0x44c9, 0x94, 0x07, \ - 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd) + EFI_GUID(0xb6e5233, 0xa65c, 0x44c9, \ + 0x94, 0x07, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd) #define EFI_CERT_SHA256_GUID \ - EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, \ - 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) + EFI_GUID(0xc1c41626, 0x504c, 0x4092, \ + 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) #define EFI_CERT_SHA384_GUID \ - EFI_GUID(0xff3e5307, 0x9fd0, 0x48c9, 0x85, 0xf1, \ - 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x01) + EFI_GUID(0xff3e5307, 0x9fd0, 0x48c9, \ + 0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x01) #define EFI_CERT_SHA512_GUID \ - EFI_GUID(0x93e0fae, 0xa6c4, 0x4f50, 0x9f, 0x1b, \ - 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a) + EFI_GUID(0x93e0fae, 0xa6c4, 0x4f50, \ + 0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a) #define EFI_CERT_RSA2048_GUID \ - EFI_GUID(0x3c5766e8, 0x269c, 0x4e34, 0xaa, 0x14, \ - 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6) + EFI_GUID(0x3c5766e8, 0x269c, 0x4e34, \ + 0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6) #define EFI_CERT_X509_GUID \ - EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, \ - 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) + EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, \ + 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) #define EFI_CERT_X509_SHA256_GUID \ - EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, \ - 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed) + EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, \ + 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed) #define EFI_CERT_X509_SHA384_GUID \ - EFI_GUID(0x7076876e, 0x80c2, 0x4ee6, \ + EFI_GUID(0x7076876e, 0x80c2, 0x4ee6, \ 0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b) #define EFI_CERT_X509_SHA512_GUID \ - EFI_GUID(0x446dbf63, 0x2502, 0x4cda, \ + EFI_GUID(0x446dbf63, 0x2502, 0x4cda, \ 0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d) #define EFI_CERT_TYPE_PKCS7_GUID \ - EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \ - 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) + EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, \ + 0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) #define EFI_LZMA_COMPRESSED \ - EFI_GUID(0xee4e5898, 0x3914, 0x4259, 0x9d, 0x6e, \ - 0xdc, 0x7b, 0xd7, 0x94, 0x03, 0xcf) + EFI_GUID(0xee4e5898, 0x3914, 0x4259, \ + 0x9d, 0x6e, 0xdc, 0x7b, 0xd7, 0x94, 0x03, 0xcf) #define EFI_DXE_SERVICES \ - EFI_GUID(0x05ad34ba, 0x6f02, 0x4214, 0x95, 0x2e, \ - 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9) + EFI_GUID(0x05ad34ba, 0x6f02, 0x4214, \ + 0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9) #define EFI_HOB_LIST \ - EFI_GUID(0x7739f24c, 0x93d7, 0x11d4, 0x9a, 0x3a, \ - 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + EFI_GUID(0x7739f24c, 0x93d7, 0x11d4, \ + 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) #define EFI_MEMORY_TYPE \ - EFI_GUID(0x4c19049f, 0x4137, 0x4dd3, 0x9c, 0x10, \ - 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa) + EFI_GUID(0x4c19049f, 0x4137, 0x4dd3, \ + 0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa) #define EFI_MEM_STATUS_CODE_REC \ - EFI_GUID(0x060cc026, 0x4c0d, 0x4dda, 0x8f, 0x41, \ - 0x59, 0x5f, 0xef, 0x00, 0xa5, 0x02) + EFI_GUID(0x060cc026, 0x4c0d, 0x4dda, \ + 0x8f, 0x41, 0x59, 0x5f, 0xef, 0x00, 0xa5, 0x02) #define EFI_GUID_EFI_ACPI1 \ - EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, \ - 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, \ + 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) /** * struct win_certificate_uefi_guid - A certificate that encapsulates @@ -2304,8 +2304,8 @@ struct efi_signature_list { * Firmware management protocol */ #define EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID \ - EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \ - 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7) + EFI_GUID(0x86c77a67, 0x0b97, 0x4633, \ + 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7) #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x0000000000000001 #define IMAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 @@ -2396,8 +2396,8 @@ struct efi_firmware_management_protocol { }; #define EFI_DISK_IO_PROTOCOL_GUID \ - EFI_GUID(0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, \ - 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + EFI_GUID(0xce345171, 0xba0b, 0x11d2, \ + 0x8e, 0x4f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) struct efi_disk { u64 revision; -- 2.43.0

From: Simon Glass <sjg@chromium.org> We can never hope to have a definitive list of GUIDs, but add four more, discovered when booting from QEMU on ARM. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) include/efi_api.h | 16 ++++++++++++++++ lib/uuid.c | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index d81a4d96694..dfc13588213 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -467,6 +467,22 @@ struct efi_runtime_services { EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, \ 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf) +#define EFI_GUIDED_SECTION_EXTRACTION \ + EFI_GUID(0xfc1bcdb0, 0x7d31, 0x49aa, \ + 0x93, 0x6a, 0xa4, 0x60, 0x0d, 0x9d, 0xd0, 0x83) + +#define EFI_DEBUG_IMAGE_INFO_TABLE \ + EFI_GUID(0x49152e77, 0x1ada, 0x4764, \ + 0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b) + +#define EFI_ACPI_MCFG_TABLE_GUID \ + EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, \ + 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) + +#define EFI_RNG_ALGORITHM_GUID \ + EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, \ + 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) + /** * struct efi_configuration_table - EFI Configuration Table * diff --git a/lib/uuid.c b/lib/uuid.c index bc07856884d..b5f486182f4 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -275,6 +275,10 @@ static const struct { { "EFI_MEMORY_TYPE", EFI_MEMORY_TYPE }, { "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC }, { "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 }, + { "CRC32 Guided Section Extraction", EFI_GUIDED_SECTION_EXTRACTION }, + { "Debug Image Info", EFI_DEBUG_IMAGE_INFO_TABLE }, + { "Memory Attribute", EFI_ACPI_MCFG_TABLE_GUID }, + { "Random-number-generator Algorithms", EFI_RNG_ALGORITHM_GUID }, #endif #endif /* !USE_HOSTCC */ }; -- 2.43.0

From: Simon Glass <sjg@chromium.org> The 'efi mem' command dumps out the memory map. This is useful within the app, even if commands are not enabled, so move it to a common file. Rename it from 'print' to 'dump' since most things that dump information use that word. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) cmd/efi.c | 119 +------------------------------------------ include/efi.h | 23 +++++++++ lib/efi/Makefile | 1 + lib/efi/memory.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 117 deletions(-) create mode 100644 lib/efi/memory.c diff --git a/cmd/efi.c b/cmd/efi.c index 53213be0a2f..91feec1c051 100644 --- a/cmd/efi.c +++ b/cmd/efi.c @@ -17,52 +17,6 @@ DECLARE_GLOBAL_DATA_PTR; -static const char *const type_name[] = { - "reserved", - "loader_code", - "loader_data", - "bs_code", - "bs_data", - "rt_code", - "rt_data", - "conv", - "unusable", - "acpi_reclaim", - "acpi_nvs", - "io", - "io_port", - "pal_code", -}; - -static struct attr_info { - u64 val; - const char *name; -} mem_attr[] = { - { EFI_MEMORY_UC, "uncached" }, - { EFI_MEMORY_WC, "write-coalescing" }, - { EFI_MEMORY_WT, "write-through" }, - { EFI_MEMORY_WB, "write-back" }, - { EFI_MEMORY_UCE, "uncached & exported" }, - { EFI_MEMORY_WP, "write-protect" }, - { EFI_MEMORY_RP, "read-protect" }, - { EFI_MEMORY_XP, "execute-protect" }, - { EFI_MEMORY_NV, "non-volatile" }, - { EFI_MEMORY_MORE_RELIABLE, "higher reliability" }, - { EFI_MEMORY_RO, "read-only" }, - { EFI_MEMORY_SP, "specific purpose" }, - { EFI_MEMORY_RUNTIME, "needs runtime mapping" } -}; - -/* Maximum different attribute values we can track */ -#define ATTR_SEEN_MAX 30 - -static inline bool is_boot_services(int type) -{ - return type == EFI_LOADER_CODE || type == EFI_LOADER_DATA || - type == EFI_BOOT_SERVICES_CODE || - type == EFI_BOOT_SERVICES_DATA; -} - static int h_cmp_entry(const void *v1, const void *v2) { const struct efi_mem_desc *desc1 = v1; @@ -119,7 +73,7 @@ static void *efi_build_mem_table(struct efi_mem_desc *desc_base, int size, continue; } - if (skip_bs && is_boot_services(desc->type)) + if (skip_bs && efi_mem_is_boot_services(desc->type)) type = EFI_CONVENTIONAL_MEMORY; memcpy(dest, desc, desc_size); @@ -149,75 +103,6 @@ static void *efi_build_mem_table(struct efi_mem_desc *desc_base, int size, return base; } -static void efi_print_mem_table(struct efi_mem_desc *desc, int desc_size, - bool skip_bs) -{ - u64 attr_seen[ATTR_SEEN_MAX]; - int attr_seen_count; - int upto, i; - u64 addr; - - printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical", - "Virtual", "Size", "Attributes"); - - /* Keep track of all the different attributes we have seen */ - attr_seen_count = 0; - addr = 0; - for (upto = 0; desc->type != EFI_MAX_MEMORY_TYPE; - upto++, desc = efi_get_next_mem_desc(desc, desc_size)) { - const char *name; - u64 size; - - if (skip_bs && is_boot_services(desc->type)) - continue; - if (desc->physical_start != addr) { - printf(" %-14s %010llx %10s %010llx\n", "<gap>", - addr, "", desc->physical_start - addr); - } - size = desc->num_pages << EFI_PAGE_SHIFT; - - name = desc->type < ARRAY_SIZE(type_name) ? - type_name[desc->type] : "<invalid>"; - printf("%2d %x:%-12s %010llx %010llx %010llx ", upto, - desc->type, name, desc->physical_start, - desc->virtual_start, size); - if (desc->attribute & EFI_MEMORY_RUNTIME) - putc('r'); - printf("%llx", desc->attribute & ~EFI_MEMORY_RUNTIME); - putc('\n'); - - for (i = 0; i < attr_seen_count; i++) { - if (attr_seen[i] == desc->attribute) - break; - } - if (i == attr_seen_count && i < ATTR_SEEN_MAX) - attr_seen[attr_seen_count++] = desc->attribute; - addr = desc->physical_start + size; - } - - printf("\nAttributes key:\n"); - for (i = 0; i < attr_seen_count; i++) { - u64 attr = attr_seen[i]; - bool first; - int j; - - printf("%c%llx: ", (attr & EFI_MEMORY_RUNTIME) ? 'r' : ' ', - attr & ~EFI_MEMORY_RUNTIME); - for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) { - if (attr & mem_attr[j].val) { - if (first) - first = false; - else - printf(", "); - printf("%s", mem_attr[j].name); - } - } - putc('\n'); - } - if (skip_bs) - printf("*Some areas are merged (use 'all' to see)\n"); -} - static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -264,7 +149,7 @@ static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc, goto done; } - efi_print_mem_table(desc, desc_size, skip_bs); + efi_dump_mem_table(desc, size, desc_size, skip_bs); free(desc); if (IS_ENABLED(CONFIG_EFI_APP)) free(orig); diff --git a/include/efi.h b/include/efi.h index 11966ffc417..e95bb2e7d96 100644 --- a/include/efi.h +++ b/include/efi.h @@ -733,6 +733,29 @@ static inline bool efi_use_host_arch(void) */ int efi_get_pxe_arch(void); +/** + * efi_mem_is_boot_services() - checks if the memory type relates to boot-time + * + * Return: true if loader code/data or boot-services code/data + */ +static inline bool efi_mem_is_boot_services(int type) +{ + return type == EFI_LOADER_CODE || type == EFI_LOADER_DATA || + type == EFI_BOOT_SERVICES_CODE || + type == EFI_BOOT_SERVICES_DATA; +} + +/** + * efi_dump_mem_table() - Dump out the EFI memory map + * + * @desc: List of descriptors to dump + * @size: Size of desc array in bytes + * @desc_size: Size of each description in @desc + * @skip_bs: true to skip boot-services allocations + */ +void efi_dump_mem_table(struct efi_mem_desc *desc, int size, int desc_size, + bool skip_bs); + /** * calculate_paths() - Calculate the device and image patch from strings * diff --git a/lib/efi/Makefile b/lib/efi/Makefile index 37816a93192..213c9910b39 100644 --- a/lib/efi/Makefile +++ b/lib/efi/Makefile @@ -5,4 +5,5 @@ obj-y += basename.o obj-y += device_path.o +obj-y += memory.o obj-y += run.o diff --git a/lib/efi/memory.c b/lib/efi/memory.c new file mode 100644 index 00000000000..2e9aa2df5e9 --- /dev/null +++ b/lib/efi/memory.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Functions shared by the app and stub + * + * Copyright (c) 2015 Google, Inc + * + * EFI information obtained here: + * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES + * + * Common EFI functions + */ + +#include <debug_uart.h> +#include <malloc.h> +#include <linux/err.h> +#include <linux/types.h> +#include <efi.h> +#include <efi_api.h> + +enum { + /* Maximum different attribute values we can track */ + ATTR_SEEN_MAX = 30, +}; + +static const char *const type_name[] = { + "reserved", + "loader_code", + "loader_data", + "bs_code", + "bs_data", + "rt_code", + "rt_data", + "conv", + "unusable", + "acpi_reclaim", + "acpi_nvs", + "io", + "io_port", + "pal_code", +}; + +static struct attr_info { + u64 val; + const char *name; +} mem_attr[] = { + { EFI_MEMORY_UC, "uncached" }, + { EFI_MEMORY_WC, "write-coalescing" }, + { EFI_MEMORY_WT, "write-through" }, + { EFI_MEMORY_WB, "write-back" }, + { EFI_MEMORY_UCE, "uncached & exported" }, + { EFI_MEMORY_WP, "write-protect" }, + { EFI_MEMORY_RP, "read-protect" }, + { EFI_MEMORY_XP, "execute-protect" }, + { EFI_MEMORY_NV, "non-volatile" }, + { EFI_MEMORY_MORE_RELIABLE, "higher reliability" }, + { EFI_MEMORY_RO, "read-only" }, + { EFI_MEMORY_SP, "specific purpose" }, + { EFI_MEMORY_RUNTIME, "needs runtime mapping" } +}; + +void efi_dump_mem_table(struct efi_mem_desc *desc, int size, int desc_size, + bool skip_bs) +{ + u64 attr_seen[ATTR_SEEN_MAX]; + struct efi_mem_desc *end; + int attr_seen_count; + int upto, i; + u64 addr; + + printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical", + "Virtual", "Size", "Attributes"); + + /* Keep track of all the different attributes we have seen */ + end = (struct efi_mem_desc *)((ulong)desc + size); + attr_seen_count = 0; + addr = 0; + for (upto = 0; desc < end; + upto++, desc = efi_get_next_mem_desc(desc, desc_size)) { + const char *name; + u64 size; + + if (skip_bs && efi_mem_is_boot_services(desc->type)) + continue; + if (desc->physical_start != addr) { + printf(" %-14s %010llx %10s %010llx\n", "<gap>", + addr, "", desc->physical_start - addr); + } + size = desc->num_pages << EFI_PAGE_SHIFT; + + name = desc->type < ARRAY_SIZE(type_name) ? + type_name[desc->type] : "<invalid>"; + printf("%2d %x:%-12s %010llx %010llx %010llx ", upto, + desc->type, name, desc->physical_start, + desc->virtual_start, size); + if (desc->attribute & EFI_MEMORY_RUNTIME) + putc('r'); + printf("%llx", desc->attribute & ~EFI_MEMORY_RUNTIME); + putc('\n'); + + for (i = 0; i < attr_seen_count; i++) { + if (attr_seen[i] == desc->attribute) + break; + } + if (i == attr_seen_count && i < ATTR_SEEN_MAX) + attr_seen[attr_seen_count++] = desc->attribute; + addr = desc->physical_start + size; + } + + printf("\nAttributes key:\n"); + for (i = 0; i < attr_seen_count; i++) { + u64 attr = attr_seen[i]; + bool first; + int j; + + printf("%c%llx: ", (attr & EFI_MEMORY_RUNTIME) ? 'r' : ' ', + attr & ~EFI_MEMORY_RUNTIME); + for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) { + if (attr & mem_attr[j].val) { + if (first) + first = false; + else + printf(", "); + printf("%s", mem_attr[j].name); + } + } + putc('\n'); + } + if (skip_bs) + printf("*Some areas are merged (use 'all' to see)\n"); +} -- 2.43.0

From: Simon Glass <sjg@chromium.org> It is sometimes useful to display the memory type in logs, etc. Add a function to convert it to a string, which is more user-friendly than a number. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) include/efi.h | 7 +++++++ lib/efi/memory.c | 12 +++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/efi.h b/include/efi.h index e95bb2e7d96..e558c1f6a38 100644 --- a/include/efi.h +++ b/include/efi.h @@ -745,6 +745,13 @@ static inline bool efi_mem_is_boot_services(int type) type == EFI_BOOT_SERVICES_DATA; } +/** + * efi_mem_type_name() - Get the name of a memory type + * + * Return: Name, or "<invalid>" if the type is not known + */ +const char *efi_mem_type_name(enum efi_memory_type type); + /** * efi_dump_mem_table() - Dump out the EFI memory map * diff --git a/lib/efi/memory.c b/lib/efi/memory.c index 2e9aa2df5e9..a646f9852e8 100644 --- a/lib/efi/memory.c +++ b/lib/efi/memory.c @@ -58,6 +58,11 @@ static struct attr_info { { EFI_MEMORY_RUNTIME, "needs runtime mapping" } }; +const char *efi_mem_type_name(enum efi_memory_type type) +{ + return type < ARRAY_SIZE(type_name) ? type_name[type] : "<invalid>"; +} + void efi_dump_mem_table(struct efi_mem_desc *desc, int size, int desc_size, bool skip_bs) { @@ -76,7 +81,6 @@ void efi_dump_mem_table(struct efi_mem_desc *desc, int size, int desc_size, addr = 0; for (upto = 0; desc < end; upto++, desc = efi_get_next_mem_desc(desc, desc_size)) { - const char *name; u64 size; if (skip_bs && efi_mem_is_boot_services(desc->type)) @@ -87,11 +91,9 @@ void efi_dump_mem_table(struct efi_mem_desc *desc, int size, int desc_size, } size = desc->num_pages << EFI_PAGE_SHIFT; - name = desc->type < ARRAY_SIZE(type_name) ? - type_name[desc->type] : "<invalid>"; printf("%2d %x:%-12s %010llx %010llx %010llx ", upto, - desc->type, name, desc->physical_start, - desc->virtual_start, size); + desc->type, efi_mem_type_name(desc->type), + desc->physical_start, desc->virtual_start, size); if (desc->attribute & EFI_MEMORY_RUNTIME) putc('r'); printf("%llx", desc->attribute & ~EFI_MEMORY_RUNTIME); -- 2.43.0

From: Simon Glass <sjg@chromium.org> It is common to run the EFI app without a display, e.g. for testing. Drop the unwanted warnings about this: EFI graphics output protocol not found (err=-524) No video mode configured in EFI! Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) drivers/video/efi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/video/efi.c b/drivers/video/efi.c index eb084b31a41..1fe76f27bcc 100644 --- a/drivers/video/efi.c +++ b/drivers/video/efi.c @@ -172,8 +172,8 @@ static int save_vesa_mode(struct vesa_mode_info *vesa, else ret = get_mode_from_entry(vesa, &priv->fb, &info); if (ret) { - printf("EFI graphics output protocol not found (err=%dE)\n", - ret); + log_debug("EFI graphics output protocol not found (err=%dE)\n", + ret); return ret; } @@ -257,7 +257,9 @@ static int efi_video_probe(struct udevice *dev) return 0; err: - printf("No video mode configured in EFI!\n"); + if (ret != -ENOTSUPP) + printf("No video mode configured in EFI!\n"); + return ret; } -- 2.43.0

From: Simon Glass <sjg@chromium.org> This driver name conflicts with another driver in U-Boot. Rename it. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) lib/efi_driver/efi_block_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 070747de515..09f6afbb814 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -269,7 +269,7 @@ static const struct efi_driver_ops driver_ops = { }; /* Identify as EFI driver */ -U_BOOT_DRIVER(efi_block) = { +U_BOOT_DRIVER(efi_block_drv) = { .name = "EFI block driver", .id = UCLASS_EFI_LOADER, .ops = &driver_ops, -- 2.43.0

From: Simon Glass <sjg@chromium.org> When the app is booting a kernel without using EFI, it must first exit the boot services provided by EFI. Add a hook for this, using bootm_final() Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) board/efi/efi-arm_app/board.c | 30 ++++++++++++++++++++++++++++++ include/efi.h | 11 +++++++++++ lib/efi_client/efi_app.c | 12 ++++++++++++ 3 files changed, 53 insertions(+) diff --git a/board/efi/efi-arm_app/board.c b/board/efi/efi-arm_app/board.c index 239e1fbaba4..ce6c3e78ebc 100644 --- a/board/efi/efi-arm_app/board.c +++ b/board/efi/efi-arm_app/board.c @@ -3,6 +3,9 @@ * Copyright (c) 2015 Google, Inc */ +#include <bootm.h> +#include <efi.h> +#include <event.h> #include <init.h> struct mm_region *mem_map; @@ -16,3 +19,30 @@ int board_init(void) { return 0; } + +int board_exit_boot_services(void *ctx, struct event *evt) +{ + struct efi_priv *priv = efi_get_priv(); + struct efi_mem_desc *desc; + int desc_size; + uint version; + int size; + uint key; + int ret; + + printf("Exiting EFI\n"); + ret = efi_get_mmap(&desc, &size, &key, &desc_size, &version); + if (ret) { + printf("efi: Failed to get memory map\n"); + return -EFAULT; + } + + ret = efi_app_exit_boot_services(priv, key); + if (ret) + return ret; + + /* no console output after here as there are no EFI drivers! */ + + return 0; +} +EVENT_SPY_FULL(EVT_BOOTM_FINAL, board_exit_boot_services); diff --git a/include/efi.h b/include/efi.h index e558c1f6a38..9ff945ae1c3 100644 --- a/include/efi.h +++ b/include/efi.h @@ -675,6 +675,17 @@ void efi_putc(struct efi_priv *priv, const char ch); */ int efi_stub_exit_boot_services(void); +/** + * efi_app_exit_boot_services() - Handle the exit-boot-service procedure + * + * Tell EFI we don't want their boot services anymore + * + * This is only available in the app + * + * Return: 0 if OK, non-zero on error + */ +int efi_app_exit_boot_services(struct efi_priv *priv, uint key); + /** * efi_get_mmap() - Get the memory map from EFI * diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 9b895f144aa..ea53c3c1678 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -276,6 +276,18 @@ int board_fixup_os(void *ctx, struct event *evt) } EVENT_SPY_FULL(EVT_BOOT_OS_ADDR, board_fixup_os); +int efi_app_exit_boot_services(struct efi_priv *priv, uint key) +{ + const struct efi_boot_services *boot = priv->boot; + int ret; + + ret = boot->exit_boot_services(priv->parent_image, key); + if (ret) + return ret; + + return 0; +} + static const struct udevice_id efi_sysreset_ids[] = { { .compatible = "efi,reset" }, { } -- 2.43.0

From: Simon Glass <sjg@chromium.org> When running under QEMU the FDT is available at the start of RAM. Set fdt_addr to this address, so that the FDT can be passed onto the OS. If the OS provides its own devicetree, that is used instead of the QEMU one. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) board/efi/efi-arm_app/efi-arm_app.env | 1 + 1 file changed, 1 insertion(+) diff --git a/board/efi/efi-arm_app/efi-arm_app.env b/board/efi/efi-arm_app/efi-arm_app.env index b28c15556de..3b839f5710c 100644 --- a/board/efi/efi-arm_app/efi-arm_app.env +++ b/board/efi/efi-arm_app/efi-arm_app.env @@ -6,6 +6,7 @@ */ /* common console settings */ +fdt_addr=40000000 stdin=serial stdout=serial,vidconsole stderr=serial,vidconsole -- 2.43.0

From: Simon Glass <sjg@chromium.org> The conversion to using an event was not done correctly, with the result that it has no effect. Fix it, by passing in the length and actually using the returned address. Signed-off-by: Simon Glass <sjg@chromium.org> Fixes: 207bf34de79 ("boot: efi: Use an event to relocate the OS") --- (no changes since v1) boot/bootm.c | 2 ++ lib/efi_client/efi_app.c | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/boot/bootm.c b/boot/bootm.c index 715b78da336..d9bcb748cb1 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -1179,11 +1179,13 @@ int bootm_run_states(struct bootm_info *bmi, int states) struct event_os_load data; data.addr = images->os.load; + data.size = images->os.image_len; log_debug("notify EVT_BOOT_OS_ADDR\n"); ret = event_notify(EVT_BOOT_OS_ADDR, &data, sizeof(data)); if (ret) goto err; + images->os.load = data.addr; } ret = bootm_load_os(bmi, 0); if (ret && ret != BOOTM_ERR_OVERLAP) diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index ea53c3c1678..37f8e95d481 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -244,7 +244,6 @@ static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type) int board_fixup_os(void *ctx, struct event *evt) { int pages; - ulong load_addr; u64 addr; efi_status_t status; struct efi_priv *priv = efi_get_priv(); @@ -264,8 +263,8 @@ int board_fixup_os(void *ctx, struct event *evt) /* That failed, so try allocating anywhere there's enough room */ status = boot->allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA, pages, &addr); if (status) { - printf("Failed to alloc %lx bytes at %lx: %lx\n", os_load->size, - load_addr, status); + printf("Failed to alloc %lx bytes: %lx\n", os_load->size, + status); return -EFAULT; } -- 2.43.0

From: Simon Glass <sjg@chromium.org> When extlinux is used, the boot partition is often 2, which is ignored. Use the 'bootflow scan' -p flag to resolve this. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) configs/efi-arm_app64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/efi-arm_app64_defconfig b/configs/efi-arm_app64_defconfig index cb7f31f10c0..844a0c28776 100644 --- a/configs/efi-arm_app64_defconfig +++ b/configs/efi-arm_app64_defconfig @@ -14,6 +14,7 @@ CONFIG_FIT=y CONFIG_BOOTSTD_FULL=y CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y +CONFIG_BOOTCOMMAND="bootflow scan -lbp" CONFIG_SYS_PBSIZE=532 CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_LOG=y -- 2.43.0

From: Simon Glass <sjg@chromium.org> When booting an OS with a large ramdisk, we need enough memory to load it. Expand the app's memory to 512M to allow this. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) configs/efi-arm_app64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/efi-arm_app64_defconfig b/configs/efi-arm_app64_defconfig index 844a0c28776..3e00abb46c9 100644 --- a/configs/efi-arm_app64_defconfig +++ b/configs/efi-arm_app64_defconfig @@ -10,6 +10,7 @@ CONFIG_DEBUG_UART=y CONFIG_TARGET_EFI_ARM_APP64=y CONFIG_EFI_CLIENT=y CONFIG_EFI_APP_64BIT=y +CONFIG_EFI_RAM_SIZE=0x20000000 CONFIG_FIT=y CONFIG_BOOTSTD_FULL=y CONFIG_SHOW_BOOT_PROGRESS=y -- 2.43.0

From: Simon Glass <sjg@chromium.org> Before booting using extlinux we must add the memory map to the FDT. Provide a ft_system_setup() function to handle this. To determine the memory size, scan the memory map looking for entries that look like real memory. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) configs/efi-arm_app64_defconfig | 1 + lib/efi_client/efi_app.c | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/configs/efi-arm_app64_defconfig b/configs/efi-arm_app64_defconfig index 3e00abb46c9..ad7874d9441 100644 --- a/configs/efi-arm_app64_defconfig +++ b/configs/efi-arm_app64_defconfig @@ -14,6 +14,7 @@ CONFIG_EFI_RAM_SIZE=0x20000000 CONFIG_FIT=y CONFIG_BOOTSTD_FULL=y CONFIG_SHOW_BOOT_PROGRESS=y +CONFIG_OF_SYSTEM_SETUP=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTCOMMAND="bootflow scan -lbp" CONFIG_SYS_PBSIZE=532 diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 37f8e95d481..75ebe3a9719 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -287,6 +287,53 @@ int efi_app_exit_boot_services(struct efi_priv *priv, uint key) return 0; } +int ft_system_setup(void *fdt, struct bd_info *bd) +{ + struct efi_mem_desc *map, *desc, *end; + u64 ram_start, ram_end; + int desc_size; + int ret, upto; + uint version; + int size; + uint key; + + ret = efi_get_mmap(&map, &size, &key, &desc_size, &version); + if (ret) + return log_msg_ret("erm", ret); + + efi_dump_mem_table(map, size, desc_size, false); + ram_start = -1ULL; + ram_end = -1ULL; + end = (void *)map + size; + for (upto = 0, desc = map; desc < end; + desc = efi_get_next_mem_desc(desc, desc_size), upto++) { + u64 base = desc->physical_start, limit; + + if (!efi_mem_is_boot_services(desc->type) && + desc->type != EFI_CONVENTIONAL_MEMORY) + continue; + + if (ram_start == -1ULL) + ram_start = base; + limit = base + (desc->num_pages << EFI_PAGE_SHIFT); + log_debug("%d: %s: %llx limit %llx\n", upto, + efi_mem_type_name(desc->type), base, limit); + if (ram_end == -1ULL || limit > ram_end) + ram_end = limit; + } + + log_info("RAM extends from %llx to %llx\n", ram_start, ram_end); + ret = fdt_fixup_memory(fdt, ram_start, ram_end - ram_start); + if (ret) { + printf("failed fixup memory\n"); + return ret; + } + + free(map); + + return 0; +} + static const struct udevice_id efi_sysreset_ids[] = { { .compatible = "efi,reset" }, { } -- 2.43.0

From: Simon Glass <sjg@chromium.org> The video sync sometimes takes 8ms on this board when running under emulation, so increase the limit to 15ms. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) configs/efi-arm_app64_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/efi-arm_app64_defconfig b/configs/efi-arm_app64_defconfig index ad7874d9441..7e7a033311c 100644 --- a/configs/efi-arm_app64_defconfig +++ b/configs/efi-arm_app64_defconfig @@ -20,6 +20,7 @@ CONFIG_BOOTCOMMAND="bootflow scan -lbp" CONFIG_SYS_PBSIZE=532 CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_LOG=y +CONFIG_CYCLIC_MAX_CPU_TIME_US=15000 CONFIG_BOARD_EARLY_INIT_R=y CONFIG_CMD_BOOTZ=y CONFIG_CMD_MEMINFO=y -- 2.43.0

From: Simon Glass <sjg@chromium.org> Build the app and use it to boot Ubuntu 2025.04 so that we can ensure this continues to work. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) test/py/tests/test_distro.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/py/tests/test_distro.py b/test/py/tests/test_distro.py index a10a43c48f9..17190b7205b 100644 --- a/test/py/tests/test_distro.py +++ b/test/py/tests/test_distro.py @@ -3,6 +3,7 @@ # Written by Simon Glass <simon.glass@canonical.com> import pytest +import utils # Enable early console so that the test can see if something goes wrong CONSOLE = 'earlycon=uart8250,io,0x3f8 console=uart8250,io,0x3f8' @@ -10,7 +11,7 @@ CONSOLE = 'earlycon=uart8250,io,0x3f8 console=uart8250,io,0x3f8' @pytest.mark.boardspec('qemu-x86_64') @pytest.mark.role('qemu-x86_64') def test_distro(ubman): - """Test that of-platdata can be generated and used in sandbox""" + """Test booting into Ubuntu 24.04""" with ubman.log.section('boot'): ubman.run_command('boot', wait_for_prompt=False) @@ -74,3 +75,22 @@ def test_distro_script(ubman): ubman.expect(['Colibri-iMX8X_Reference-Multimedia-Image']) ubman.restart_uboot() + +@pytest.mark.boardspec('efi-arm_app64') +@pytest.mark.role('efi-aarch64') +def test_distro_arm_app(ubman): + """Test that the ARM EFI app can boot into Ubuntu 25.04""" + # with ubman.log.section('build'): + # utils.run_and_log(ubman, ['scripts/build-efi', '-a', 'arm']) + with ubman.log.section('boot'): + ubman.run_command('boot', wait_for_prompt=False) + + ubman.expect(["Booting bootflow 'efi_media.bootdev.part_2' with extlinux"]) + ubman.expect(['Exiting EFI']) + ubman.expect(['Booting Linux on physical CPU']) + + with ubman.log.section('initrd'): + ubman.expect(['Starting systemd-udevd']) + ubman.expect(['Welcome to Ubuntu 25.04!']) + + ubman.restart_uboot() -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add a new board which can run the EFI app and boot an OS. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) .gitlab-ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c96c7f80cd..a8dbf1970a2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -866,3 +866,9 @@ play: variables: ROLE: play <<: *lab_dfn + +efi-aarch64: + variables: + ROLE: efi-aarch64 + TEST_PY_TEST_SPEC: "and not sleep" + <<: *lab_dfn -- 2.43.0
participants (1)
-
Simon Glass