From 87ef1987de3a47910b5b0a8fd84e1b928e56ceb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Stehl=C3=A9?= Date: Fri, 17 Jan 2025 18:13:26 +0100 Subject: [PATCH 1/7] lib: uuid: support more efi protocols in uuid_guid_get_str() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add more EFI protocols GUIDs to the translation table used by uuid_guid_get_str(). Signed-off-by: Vincent Stehlé Cc: Tom Rini --- lib/uuid.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/uuid.c b/lib/uuid.c index 97388f597a6..75658778044 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -119,6 +119,10 @@ static const struct { "Block IO", EFI_BLOCK_IO_PROTOCOL_GUID, }, + { + "Disk IO", + EFI_DISK_IO_PROTOCOL_GUID, + }, { "Simple File System", EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, @@ -127,6 +131,10 @@ static const struct { "Loaded Image", EFI_LOADED_IMAGE_PROTOCOL_GUID, }, + { + "Loaded Image Device Path", + EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID, + }, { "Graphics Output", EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, @@ -139,10 +147,18 @@ static const struct { "HII Database", EFI_HII_DATABASE_PROTOCOL_GUID, }, + { + "HII Config Access", + EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID, + }, { "HII Config Routing", EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, }, + { + "Load File", + EFI_LOAD_FILE_PROTOCOL_GUID, + }, { "Load File2", EFI_LOAD_FILE2_PROTOCOL_GUID, From 80908fee7705cd2edb2df94c3d124c44dd515582 Mon Sep 17 00:00:00 2001 From: Maks Mishin Date: Sun, 2 Feb 2025 20:59:40 +0300 Subject: [PATCH 2/7] efi_loader: Fix potential deref-after-null After having been compared to a NULL value at efi_disk.c:426, pointer 'part_info' is dereferenced at efi_disk.c:534. Signed-off-by: Maks Mishin Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 1f3de0a2339..5452640354e 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -531,7 +531,8 @@ static efi_status_t efi_disk_add_dev( /* Store first EFI system partition */ if (part && efi_system_partition.uclass_id == UCLASS_INVALID) { - if (part_info->bootable & PART_EFI_SYSTEM_PARTITION) { + if (part_info && + part_info->bootable & PART_EFI_SYSTEM_PARTITION) { efi_system_partition.uclass_id = desc->uclass_id; efi_system_partition.devnum = desc->devnum; efi_system_partition.part = part; From 530e869ff89d9575103637af201fe97864d4f577 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Fri, 14 Feb 2025 15:46:45 +0200 Subject: [PATCH 3/7] efi_loader: remove comparisons to string literals from runtime For EFI runtime services, we manage to preserve string literals by placing the .efi_runtime section just before .data and preserving it when marking the runtime memory by marking surrounding boottime code as runtime. This is ok for now but will break if we update any linker scripts and decouple .text and .runtime sections. So let's define the strings we used to compare in the appropriate section for runtime services Signed-off-by: Ilias Apalodimas Reviewed-by: Mark Kettenis --- lib/efi_loader/efi_var_mem.c | 3 ++- lib/efi_loader/efi_variable_tee.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index b265d95dd6b..31180df9e3a 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -19,6 +19,7 @@ */ static struct efi_var_file __efi_runtime_data *efi_var_buf; static struct efi_var_entry __efi_runtime_data *efi_current_var; +static const u16 __efi_runtime_rodata vtf[] = u"VarToFile"; /** * efi_var_mem_compare() - compare GUID and name with a variable @@ -331,7 +332,7 @@ efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor, if (timep) *timep = var->time; - if (!u16_strcmp(variable_name, u"VarToFile")) + if (!u16_strcmp(variable_name, vtf)) return efi_var_collect_mem(data, data_size, EFI_VARIABLE_NON_VOLATILE); old_size = *data_size; diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index 0d090d051dd..6a1fa39bb6f 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -41,6 +41,7 @@ static u16 mm_sp_id; extern struct efi_var_file __efi_runtime_data *efi_var_buf; static efi_uintn_t max_buffer_size; /* comm + var + func + data */ static efi_uintn_t max_payload_size; /* func + data */ +static const u16 __efi_runtime_rodata pk[] = u"PK"; struct mm_connection { struct udevice *tee; @@ -858,7 +859,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, if (alt_ret != EFI_SUCCESS) goto out; - if (!u16_strcmp(variable_name, u"PK")) + if (!u16_strcmp(variable_name, pk)) alt_ret = efi_init_secure_state(); out: free(comm_buf); From bd8bc53162edde1970c04c472a8058c69bd71f3d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 15 Feb 2025 16:22:06 +0100 Subject: [PATCH 4/7] efi_driver: create a parent device for all EFI block devices Up to now root has been the parent device for all block devices created via calling ConnectController(). This does not work well together with the implementation of bootstd. Add a dummy parent device for all EFI block devices. With this change EFI block devices are also accessible via commands like 'cat', 'load', and 'ls'. => dm tree Class Seq Probed Driver Name ----------------------------------------------------------- efi 0 [ + ] EFI block driver `-- efi blk 3 [ + ] efi_blk `-- efi.efiblk#0 partition 0 [ + ] blk_partition `-- efi.efiblk#0:1 => ls efiloader 0:1 13 hello.txt 7 u-boot.txt 2 file(s), 0 dir(s) => cat efiloader 0:1 hello.txt Hello world! => efidebug dh 0000000018df1700 (efi.efiblk#0:1) /VenHw(dbca4c98-6cb0-694d-0872-819c650cb7b8)/HD(1,MBR,0xd1535d21,0x1,0x7f) Block IO Simple File System Adjust the event dump unit test to consider the new event spy. Signed-off-by: Heinrich Schuchardt --- lib/efi_driver/efi_block_device.c | 29 ++++++++++++++++++++++++++++- test/py/tests/test_event_dump.py | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index d3c668dc183..070747de515 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -35,8 +35,10 @@ #include #include #include +#include #include #include +#include /** * struct efi_blk_plat - attributes of a block device @@ -118,13 +120,18 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, static efi_status_t efi_bl_create_block_device(efi_handle_t handle, void *interface) { - struct udevice *bdev = NULL, *parent = dm_root(); + struct udevice *bdev = NULL, *parent; efi_status_t ret; + int r; int devnum; char *name; struct efi_block_io *io = interface; struct efi_blk_plat *plat; + r = uclass_find_first_device(UCLASS_EFI_LOADER, &parent); + if (r) + return EFI_OUT_OF_RESOURCES; + devnum = blk_next_free_devnum(UCLASS_EFI_LOADER); if (devnum < 0) return EFI_OUT_OF_RESOURCES; @@ -221,6 +228,24 @@ efi_bl_init(struct efi_driver_binding_extended_protocol *this) return EFI_SUCCESS; } +/** + * efi_block_device_create() - create parent for EFI block devices + * + * Create a device that serves as parent for all block devices created via + * ConnectController(). + * + * Return: 0 for success + */ +static int efi_block_device_create(void) +{ + int ret; + struct udevice *dev; + + ret = device_bind_driver(gd->dm_root, "EFI block driver", "efi", &dev); + + return ret; +} + /* Block device driver operators */ static const struct blk_ops efi_blk_ops = { .read = efi_bl_read, @@ -249,3 +274,5 @@ U_BOOT_DRIVER(efi_block) = { .id = UCLASS_EFI_LOADER, .ops = &driver_ops, }; + +EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, efi_block_device_create); diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py index 45143c1c7d9..177b982e891 100644 --- a/test/py/tests/test_event_dump.py +++ b/test/py/tests/test_event_dump.py @@ -19,6 +19,7 @@ def test_event_dump(u_boot_console): EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*boot/vbe_request.c:.* EVT_FT_FIXUP bootmeth_vbe_simple_ft_fixup .*boot/vbe_simple_os.c:.* EVT_LAST_STAGE_INIT alloc_write_acpi_tables .*lib/acpi/acpi_table.c:.* +EVT_LAST_STAGE_INIT efi_block_device_create .*lib/efi_driver/efi_block_device.c:.* EVT_LAST_STAGE_INIT install_smbios_table .*lib/efi_loader/efi_smbios.c:.* EVT_MISC_INIT_F sandbox_early_getopt_check .*arch/sandbox/cpu/start.c:.* EVT_TEST h_adder_simple .*test/common/event.c:''' From 08573d7688a8c133bd4a7354cf928f96e778b42a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Feb 2025 12:12:39 +0100 Subject: [PATCH 5/7] lmb: avoid superfluous value check in lmb_map_update_notify() Instead of testing the value of parameter op at runtime use an enum to ensure that only valid values are used. Reviewed-by: Ilias Apalodimas Signed-off-by: Heinrich Schuchardt --- include/lmb.h | 12 ++++++++++++ lib/lmb.c | 23 +++++++---------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/include/lmb.h b/include/lmb.h index d9d7435a431..09297a4f530 100644 --- a/include/lmb.h +++ b/include/lmb.h @@ -31,6 +31,18 @@ #define LMB_NOOVERWRITE BIT(1) #define LMB_NONOTIFY BIT(2) +/** + * enum lmb_map_op - memory map operation + */ +enum lmb_map_op { + /** @LMB_MAP_OP_RESERVE: reserve memory */ + LMB_MAP_OP_RESERVE = 1, + /** @LMB_MAP_OP_FREE: free memory */ + LMB_MAP_OP_FREE, + /** @LMB_MAP_OP_ADD: add memory */ + LMB_MAP_OP_ADD, +}; + /** * struct lmb_region - Description of one region * @base: Base address of the region diff --git a/lib/lmb.c b/lib/lmb.c index 7ca44591e1d..7534a231c99 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -23,10 +23,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define MAP_OP_RESERVE (u8)0x1 -#define MAP_OP_FREE (u8)0x2 -#define MAP_OP_ADD (u8)0x3 - /* * The following low level LMB functions must not access the global LMB memory * map since they are also used to manage IOVA memory maps in iommu drivers like @@ -436,18 +432,13 @@ static bool lmb_should_notify(u32 flags) CONFIG_IS_ENABLED(EFI_LOADER); } -static int lmb_map_update_notify(phys_addr_t addr, phys_size_t size, u8 op, - u32 flags) +static int lmb_map_update_notify(phys_addr_t addr, phys_size_t size, + enum lmb_map_op op, u32 flags) { u64 efi_addr; u64 pages; efi_status_t status; - if (op != MAP_OP_RESERVE && op != MAP_OP_FREE && op != MAP_OP_ADD) { - log_err("Invalid map update op received (%d)\n", op); - return -1; - } - if (!lmb_should_notify(flags)) return 0; @@ -456,7 +447,7 @@ static int lmb_map_update_notify(phys_addr_t addr, phys_size_t size, u8 op, efi_addr &= ~EFI_PAGE_MASK; status = efi_add_memory_map_pg(efi_addr, pages, - op == MAP_OP_RESERVE ? + op == LMB_MAP_OP_RESERVE ? EFI_BOOT_SERVICES_DATA : EFI_CONVENTIONAL_MEMORY, false); @@ -642,7 +633,7 @@ long lmb_add(phys_addr_t base, phys_size_t size) if (ret) return ret; - return lmb_map_update_notify(base, size, MAP_OP_ADD, LMB_NONE); + return lmb_map_update_notify(base, size, LMB_MAP_OP_ADD, LMB_NONE); } long lmb_free_flags(phys_addr_t base, phys_size_t size, @@ -654,7 +645,7 @@ long lmb_free_flags(phys_addr_t base, phys_size_t size, if (ret < 0) return ret; - return lmb_map_update_notify(base, size, MAP_OP_FREE, flags); + return lmb_map_update_notify(base, size, LMB_MAP_OP_FREE, flags); } long lmb_free(phys_addr_t base, phys_size_t size) @@ -671,7 +662,7 @@ long lmb_reserve(phys_addr_t base, phys_size_t size, u32 flags) if (ret) return ret; - return lmb_map_update_notify(base, size, MAP_OP_RESERVE, flags); + return lmb_map_update_notify(base, size, LMB_MAP_OP_RESERVE, flags); } static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align, @@ -712,7 +703,7 @@ static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align, return 0; ret = lmb_map_update_notify(base, size, - MAP_OP_RESERVE, + LMB_MAP_OP_RESERVE, flags); if (ret) return ret; From 41d5734442c03439a534abfc2493d0ce9ca5000a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Feb 2025 12:12:40 +0100 Subject: [PATCH 6/7] lmb: move lmb_map_update_notify() to EFI When building with qemu_arm64_defconfig with CONFIG_CC_OPTIMIZE_FOR_DEBUG=y and CONFIG_EFI_LOADER=n an error undefined reference to efi_add_memory_map_pg occurs. Move the EFI dependent part of lmb_map_update_notify() to the EFI sub-system. Reported-by: Liya Huang <1425075683@qq.com> Acked-by: Liya Huang <1425075683@qq.com> Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 15 +++++++++++++++ lib/efi_loader/efi_memory.c | 27 +++++++++++++++++++++++++++ lib/lmb.c | 31 +++---------------------------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index dcae6a731a0..db3d20fd753 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -1263,6 +1263,21 @@ efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int */ void efi_add_known_memory(void); +/** + * efi_map_update_notify() - notify EFI of memory map changes + * + * @addr: start of memory area + * @size: size of memory area + * @op: type of change + * Return: 0 if change could be processed + */ +#ifdef CONFIG_EFI_LOADER +int efi_map_update_notify(phys_addr_t addr, phys_size_t size, + enum lmb_map_op op); +#else +#define efi_map_update_notify(addr, size, op) (0) +#endif + /** * efi_load_option_dp_join() - join device-paths for load option * diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 1212772471e..11d092dc289 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -865,3 +865,30 @@ int efi_memory_init(void) return 0; } + +int efi_map_update_notify(phys_addr_t addr, phys_size_t size, + enum lmb_map_op op) +{ + u64 efi_addr; + u64 pages; + efi_status_t status; + + efi_addr = (uintptr_t)map_sysmem(addr, 0); + pages = efi_size_in_pages(size + (efi_addr & EFI_PAGE_MASK)); + efi_addr &= ~EFI_PAGE_MASK; + + status = efi_add_memory_map_pg(efi_addr, pages, + op == LMB_MAP_OP_RESERVE ? + EFI_BOOT_SERVICES_DATA : + EFI_CONVENTIONAL_MEMORY, + false); + if (status != EFI_SUCCESS) { + log_err("LMB Map notify failure %lu\n", + status & ~EFI_ERROR_MASK); + return -1; + } + unmap_sysmem((void *)(uintptr_t)efi_addr); + + return 0; +} + diff --git a/lib/lmb.c b/lib/lmb.c index 7534a231c99..93fc1bea07c 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -426,37 +426,12 @@ long io_lmb_free(struct lmb *io_lmb, phys_addr_t base, phys_size_t size) static struct lmb lmb; -static bool lmb_should_notify(u32 flags) -{ - return !lmb.test && !(flags & LMB_NONOTIFY) && - CONFIG_IS_ENABLED(EFI_LOADER); -} - static int lmb_map_update_notify(phys_addr_t addr, phys_size_t size, enum lmb_map_op op, u32 flags) { - u64 efi_addr; - u64 pages; - efi_status_t status; - - if (!lmb_should_notify(flags)) - return 0; - - efi_addr = (uintptr_t)map_sysmem(addr, 0); - pages = efi_size_in_pages(size + (efi_addr & EFI_PAGE_MASK)); - efi_addr &= ~EFI_PAGE_MASK; - - status = efi_add_memory_map_pg(efi_addr, pages, - op == LMB_MAP_OP_RESERVE ? - EFI_BOOT_SERVICES_DATA : - EFI_CONVENTIONAL_MEMORY, - false); - if (status != EFI_SUCCESS) { - log_err("%s: LMB Map notify failure %lu\n", __func__, - status & ~EFI_ERROR_MASK); - return -1; - } - unmap_sysmem((void *)(uintptr_t)efi_addr); + if (CONFIG_IS_ENABLED(EFI_LOADER) && + !lmb.test && !(flags & LMB_NONOTIFY)) + return efi_map_update_notify(addr, size, op); return 0; } From 5ce629db2512d70f298bc1d422fefad63a74c7f5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Feb 2025 12:12:41 +0100 Subject: [PATCH 7/7] efi_loader: make efi_add_memory_map_pg() static The function is only used in the efi_memory.c module. Reviewed-by: Ilias Apalodimas Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 15 --------------- lib/efi_loader/efi_memory.c | 1 + 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index db3d20fd753..1d75d97ebbc 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -852,21 +852,6 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, /* Adds a range into the EFI memory map */ efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type); -/** - * efi_add_memory_map_pg() - add pages to the memory map - * - * @start: start address, must be a multiple of - * EFI_PAGE_SIZE - * @pages: number of pages to add - * @memory_type: type of memory added - * @overlap_conventional: region may only overlap free(conventional) - * memory - * Return: status code - */ -efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, - int memory_type, - bool overlap_conventional); - /* Called by board init to initialize the EFI drivers */ efi_status_t efi_driver_init(void); /* Called when a block device is added */ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 11d092dc289..6d00b186250 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -268,6 +268,7 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map, * memory * Return: status code */ +static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, int memory_type, bool overlap_conventional)