From 864106f3c477052dae932d80a89522532efe76fe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:00 -0700 Subject: [PATCH 01/30] bloblist: Make BLOBLIST_ALLOC the default We want to encourage people to use an allocated bloblist since it is more flexible than a fixed one. Make this the default, being sure not to change existing users. The unit tests require BLOBLIST_FIXED so add a dependency in the Makefile to avoid build errors. All sandbox builds require BLOBLIST_FIXED so make that the default for sandbox. Signed-off-by: Simon Glass --- common/Kconfig | 2 ++ configs/chromebook_bob_defconfig | 1 + configs/chromebook_coral_defconfig | 1 + configs/chromebook_kevin_defconfig | 1 + configs/chromebook_samus_tpl_defconfig | 1 + configs/qemu-x86_64_defconfig | 1 + test/common/Makefile | 4 ++++ 7 files changed, 11 insertions(+) diff --git a/common/Kconfig b/common/Kconfig index 0e8c44f3f74..7685914fa6f 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1047,6 +1047,8 @@ if BLOBLIST choice prompt "Bloblist location" + default BLOBLIST_FIXED if SANDBOX + default BLOBLIST_ALLOC help Select the location of the bloblist, via various means. diff --git a/configs/chromebook_bob_defconfig b/configs/chromebook_bob_defconfig index decac2e1935..072311465d9 100644 --- a/configs/chromebook_bob_defconfig +++ b/configs/chromebook_bob_defconfig @@ -36,6 +36,7 @@ CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-gru-bob.dtb" CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOARD_EARLY_INIT_R=y CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0x100000 CONFIG_BLOBLIST_SIZE=0x1000 CONFIG_SPL_MAX_SIZE=0x1e000 diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig index 0fb73049738..b1999b4ef20 100644 --- a/configs/chromebook_coral_defconfig +++ b/configs/chromebook_coral_defconfig @@ -44,6 +44,7 @@ CONFIG_LOGF_FUNC=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BLOBLIST=y # CONFIG_TPL_BLOBLIST is not set +CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0x100000 CONFIG_BLOBLIST_SIZE=0x30000 CONFIG_SPL_NO_BSS_LIMIT=y diff --git a/configs/chromebook_kevin_defconfig b/configs/chromebook_kevin_defconfig index 5bbea6c42a8..13c0998dbab 100644 --- a/configs/chromebook_kevin_defconfig +++ b/configs/chromebook_kevin_defconfig @@ -37,6 +37,7 @@ CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-gru-kevin.dtb" CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOARD_EARLY_INIT_R=y CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0x100000 CONFIG_BLOBLIST_SIZE=0x1000 CONFIG_SPL_MAX_SIZE=0x1e000 diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig index fc524da5480..42337d7a11e 100644 --- a/configs/chromebook_samus_tpl_defconfig +++ b/configs/chromebook_samus_tpl_defconfig @@ -34,6 +34,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_MISC_INIT_R=y CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0xff7c0000 CONFIG_BLOBLIST_SIZE=0x1000 CONFIG_SPL_NO_BSS_LIMIT=y diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 812b20687e5..f93721fceb8 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -34,6 +34,7 @@ CONFIG_SPL_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_PCI_INIT_R=y CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0x10000 CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_SPL_BOARD_INIT=y diff --git a/test/common/Makefile b/test/common/Makefile index 53c4f16164d..95bd00741a3 100644 --- a/test/common/Makefile +++ b/test/common/Makefile @@ -1,9 +1,13 @@ # SPDX-License-Identifier: GPL-2.0+ obj-y += cmd_ut_common.o obj-$(CONFIG_AUTOBOOT) += test_autoboot.o + ifneq ($(CONFIG_$(XPL_)BLOBLIST),) +ifdef CONFIG_BLOBLIST_FIXED obj-$(CONFIG_$(XPL_)CMDLINE) += bloblist.o endif +endif + obj-$(CONFIG_CYCLIC) += cyclic.o obj-$(CONFIG_EVENT_DYNAMIC) += event.o obj-y += cread.o From c487381d50b280a0dce09e00cd29620be9598c90 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:01 -0700 Subject: [PATCH 02/30] abuf: Provide a way to get the buffer address In many cases it is useful to get the address of a buffer, e.g. when booting from it. Add a function to handle this. Signed-off-by: Simon Glass --- include/abuf.h | 8 ++++++++ lib/abuf.c | 6 ++++++ test/lib/abuf.c | 4 +++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/abuf.h b/include/abuf.h index be98ec78c86..76e314b9a47 100644 --- a/include/abuf.h +++ b/include/abuf.h @@ -42,6 +42,14 @@ static inline size_t abuf_size(const struct abuf *abuf) return abuf->size; } +/** + * abuf_addr() - Get the address of a buffer's data + * + * @abuf: Buffer to check + * Return: address of buffer + */ +ulong abuf_addr(const struct abuf *abuf); + /** * abuf_set() - set the (unallocated) data in a buffer * diff --git a/lib/abuf.c b/lib/abuf.c index 937c3df351e..8156177c773 100644 --- a/lib/abuf.c +++ b/lib/abuf.c @@ -26,6 +26,12 @@ void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) { abuf_set(abuf, map_sysmem(addr, size), size); } + +ulong abuf_addr(const struct abuf *abuf) +{ + return map_to_sysmem(abuf->data); +} + #else /* copied from lib/string.c for convenience */ static char *memdup(const void *src, size_t len) diff --git a/test/lib/abuf.c b/test/lib/abuf.c index 7c0481ab610..5d61f9261c6 100644 --- a/test/lib/abuf.c +++ b/test/lib/abuf.c @@ -46,7 +46,7 @@ static int lib_test_abuf_set(struct unit_test_state *uts) } LIB_TEST(lib_test_abuf_set, 0); -/* Test abuf_map_sysmem() */ +/* Test abuf_map_sysmem() and abuf_addr() */ static int lib_test_abuf_map_sysmem(struct unit_test_state *uts) { struct abuf buf; @@ -60,6 +60,8 @@ static int lib_test_abuf_map_sysmem(struct unit_test_state *uts) ut_asserteq(TEST_DATA_LEN, buf.size); ut_asserteq(false, buf.alloced); + ut_asserteq(addr, abuf_addr(&buf)); + return 0; } LIB_TEST(lib_test_abuf_map_sysmem, 0); From d887432807af8bdc943e7c8caa2a528dc516f6b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:02 -0700 Subject: [PATCH 03/30] abuf: Allow use in host tools Some header files included on the host are moving to use abuf, so adjust the header-inclusion to bring in size_t correctly. Signed-off-by: Simon Glass --- include/abuf.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/abuf.h b/include/abuf.h index 76e314b9a47..de21cefade4 100644 --- a/include/abuf.h +++ b/include/abuf.h @@ -9,7 +9,11 @@ #ifndef __ABUF_H #define __ABUF_H +#ifdef USE_HOSTCC +#include +#else #include +#endif /** * struct abuf - buffer that can be allocated and freed From 7ba7c1dd86cf212c7d489dbf0a07301d1a3b4d2c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:03 -0700 Subject: [PATCH 04/30] abuf: Provide a constant buffer Add a new initialiser which can accept a constant pointer. Signed-off-by: Simon Glass --- include/abuf.h | 13 +++++++++++++ lib/abuf.c | 6 ++++++ test/lib/abuf.c | 22 ++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/include/abuf.h b/include/abuf.h index de21cefade4..62ff6499a0c 100644 --- a/include/abuf.h +++ b/include/abuf.h @@ -157,6 +157,19 @@ void abuf_init_move(struct abuf *abuf, void *data, size_t size); */ void abuf_init_set(struct abuf *abuf, void *data, size_t size); +/** + * abuf_init_const() - Set up a new const abuf + * + * Inits a new abuf and sets up its (unallocated) data. The only current + * difference between this and abuf_init_set() is the 'data' parameter is a + * const pointer. At some point a flag could be used to indicate const-ness. + * + * @abuf: abuf to set up + * @data: New contents of abuf + * @size: New size of abuf + */ +void abuf_init_const(struct abuf *abuf, const void *data, size_t size); + /** * abuf_uninit() - Free any memory used by an abuf * diff --git a/lib/abuf.c b/lib/abuf.c index 8156177c773..61adf7fc6b1 100644 --- a/lib/abuf.c +++ b/lib/abuf.c @@ -119,6 +119,12 @@ void abuf_init_set(struct abuf *abuf, void *data, size_t size) abuf_set(abuf, data, size); } +void abuf_init_const(struct abuf *abuf, const void *data, size_t size) +{ + /* for now there is no flag indicating that the abuf data is constant */ + abuf_init_set(abuf, (void *)data, size); +} + void abuf_init_move(struct abuf *abuf, void *data, size_t size) { abuf_init_set(abuf, data, size); diff --git a/test/lib/abuf.c b/test/lib/abuf.c index 5d61f9261c6..b38690fe1a9 100644 --- a/test/lib/abuf.c +++ b/test/lib/abuf.c @@ -46,6 +46,28 @@ static int lib_test_abuf_set(struct unit_test_state *uts) } LIB_TEST(lib_test_abuf_set, 0); +/* Test abuf_init_const() */ +static int lib_test_abuf_init_const(struct unit_test_state *uts) +{ + struct abuf buf; + ulong start; + void *ptr; + + start = ut_check_free(); + + ptr = map_sysmem(0x100, 0); + + abuf_init_const(&buf, ptr, 10); + ut_asserteq_ptr(ptr, buf.data); + ut_asserteq(10, buf.size); + + /* No memory should have been allocated */ + ut_assertok(ut_check_delta(start)); + + return 0; +} +LIB_TEST(lib_test_abuf_init_const, 0); + /* Test abuf_map_sysmem() and abuf_addr() */ static int lib_test_abuf_map_sysmem(struct unit_test_state *uts) { From 8b89d901465bd00358c761f0b64e05efed8a333a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:04 -0700 Subject: [PATCH 05/30] cpu: Provide a way to get the physical-address size This concept exists on x86. Declare it as a generic function so that the value can be accessed by UPL. Signed-off-by: Simon Glass --- arch/x86/include/asm/cpu.h | 9 --------- arch/x86/lib/bdinfo.c | 1 + include/cpu.h | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 8c1ef4c8cc1..fd389d4024c 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -284,15 +284,6 @@ u32 cpu_get_family_model(void); */ u32 cpu_get_stepping(void); -/** - * cpu_phys_address_size() - Get the physical address size in bits - * - * This is 32 for older CPUs but newer ones may support 36. - * - * Return: address size (typically 32 or 36) - */ -int cpu_phys_address_size(void); - void board_final_init(void); void board_final_cleanup(void); diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index 2a78f578dee..bd2cf0b9fcb 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -5,6 +5,7 @@ * Copyright 2021 Google LLC */ +#include #include #include #include diff --git a/include/cpu.h b/include/cpu.h index 0018910d61f..d0cd104c05a 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -179,4 +179,18 @@ struct udevice *cpu_get_current_dev(void); * @return 0 if OK, -ve on error */ int cpu_release_core(const struct udevice *dev, phys_addr_t addr); + +/** + * cpu_phys_address_size() - Get the physical-address size for the CPU + * + * x86 CPUs have a setting which indicates how many bits of address space are + * available on the CPU. This is 32 for older CPUs but newer ones may support 36 + * or more. + * + * For non-x86 CPUs the result may simply be 32 for 32-bit CPUS or 64 for 64-bit + * + * Return: address size (typically 32 or 36) + */ +int cpu_phys_address_size(void); + #endif From 4219fd9a705dba1c066e02824514b9e4b13b8acf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:05 -0700 Subject: [PATCH 06/30] serial: Support info() method in ns16550 xPL with UPL UPL needs to pass the serial details onto the next stage, so adjust the condition to support this. Signed-off-by: Simon Glass --- drivers/serial/ns16550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index c3b884b6d00..039da835f5f 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -464,7 +464,7 @@ int ns16550_serial_getinfo(struct udevice *dev, struct serial_device_info *info) struct ns16550_plat *plat = com_port->plat; /* save code size */ - if (!not_xpl()) + if (!not_xpl() && !CONFIG_IS_ENABLED(UPL_OUT)) return -ENOSYS; info->type = SERIAL_CHIP_16550_COMPATIBLE; From 26001ee047d071214c3dff7603c8d956ba172d6d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:06 -0700 Subject: [PATCH 07/30] mkimage: Update map_to_sysmem() to match its prototype Update the version of this function in mkimage so that it uses a const pointer, as is done in the mapmem.h header file. Signed-off-by: Simon Glass --- tools/mkimage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mkimage.h b/tools/mkimage.h index d92a3ff8117..15741f250fd 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -37,7 +37,7 @@ static inline void *map_sysmem(ulong paddr, unsigned long len) return (void *)(uintptr_t)paddr; } -static inline ulong map_to_sysmem(void *ptr) +static inline ulong map_to_sysmem(const void *ptr) { return (ulong)(uintptr_t)ptr; } From 78bff2ebba9994a61ec8c0592d88ddb1d34c795b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:07 -0700 Subject: [PATCH 08/30] x86: Enable meminfo command Enable this command for x86 boards as it is quite useful for seeing where memory is. Signed-off-by: Simon Glass --- cmd/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index 93efeaec6f4..4bc8b9100de 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -892,14 +892,14 @@ config MD5SUM_VERIFY config CMD_MEMINFO bool "meminfo" - default y if SANDBOX + default y if SANDBOX || X86 help Display memory information. config CMD_MEMINFO_MAP bool "- with memory map" depends on CMD_MEMINFO - default y if SANDBOX + default y if SANDBOX || X86 help Shows a memory map, in addition to just the DRAM size. This allows seeing where U-Boot's memory area is, at the top of DRAM, as well as From 9b35dbc93fd40daadf137ee430641d62b6b4d4b0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:08 -0700 Subject: [PATCH 09/30] x86: Show the timestamp counter with bdinfo Add a line to the 'bdinfo' command which shows the current value of the TSC. Signed-off-by: Simon Glass --- arch/x86/lib/bdinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index bd2cf0b9fcb..4b016d4a0fc 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -33,6 +33,8 @@ void arch_print_bdinfo(void) bdinfo_print_num_l(" high start", gd->arch.table_start_high); bdinfo_print_num_l(" high end", gd->arch.table_end_high); + bdinfo_print_num_ll("tsc", rdtsc()); + if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo(); } From 6c6591c823e5a01b42ef52526656119e19fb756d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:09 -0700 Subject: [PATCH 10/30] ofnode: Use 4K for a default tree-size At some point it would be nice to have the ofnode API automatically expand the tree as required, to accommodate new nodes. For now, expand the default size so that UPL can be supported. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index c8161827d1c..98483c0f523 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -118,7 +118,7 @@ int oftree_new(oftree *treep) return log_msg_ret("liv", ret); tree = oftree_from_np(root); } else { - const int size = 1024; + const int size = 4096; void *fdt; ret = check_tree_count(); From 8b2561bf9f548f78ddf4dca05126a3bd5d1a3f94 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:10 -0700 Subject: [PATCH 11/30] ofnode: Indicate when out of space in a few places Update ofnode_add_subnode() and ofnode_add_prop() to return a suitable error when space is exhausted in the FDT. This makes it easier to see what is going wrong. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/core/ofnode.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 98483c0f523..83c60069cb3 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1710,9 +1710,10 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname, int ofnode_write_prop(ofnode node, const char *propname, const void *value, int len, bool copy) { + int ret; + if (of_live_active()) { void *newval; - int ret; if (copy) { newval = malloc(len); @@ -1726,8 +1727,12 @@ int ofnode_write_prop(ofnode node, const char *propname, const void *value, free(newval); return ret; } else { - return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node), - propname, value, len); + ret = fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname, value, len); + if (ret) + return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL; + + return 0; } } @@ -2015,7 +2020,7 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) ret = -EEXIST; } if (offset < 0) - return -EINVAL; + return offset == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL; subnode = noffset_to_ofnode(node, offset); } From 957869414077efa66ca866e9fcced34ec9678a38 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:11 -0700 Subject: [PATCH 12/30] ofnode: Update of_add_subnode() to indicate name is alloced This function allocates memory for the node name, so mention this in the function comment. Signed-off-by: Simon Glass --- include/dm/ofnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 890f0e6cf40..c5f0a6d6788 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -1809,7 +1809,7 @@ static inline int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset, * of_add_subnode() - add a new subnode to a node * * @parent: parent node to add to - * @name: name of subnode + * @name: name of subnode (allocated by this function) * @nodep: returns pointer to new subnode (valid if the function returns 0 * or -EEXIST) * Returns 0 if OK, -EEXIST if already exists, -ENOMEM if out of memory, other From dc39ce8d90770a9abf9d464f7d29624361173c78 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:12 -0700 Subject: [PATCH 13/30] boot: Rename fit_image_get_data() This function can only be used with FITs that use embedded data. Rename it so this is clear. Signed-off-by: Simon Glass Acked-by: Heinrich Schuchardt --- arch/arm/cpu/armv8/sec_firmware.c | 4 ++-- arch/arm/mach-k3/r5/sysfw-loader.c | 2 +- arch/x86/lib/bootm.c | 6 +++--- boot/image-fit.c | 10 +++++----- common/spl/spl_fit.c | 2 +- common/splash_source.c | 4 +++- common/update.c | 2 +- include/image.h | 4 ++-- tools/image-host.c | 4 ++-- 9 files changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c index 44372cbe4a1..b7c73f288bd 100644 --- a/arch/arm/cpu/armv8/sec_firmware.c +++ b/arch/arm/cpu/armv8/sec_firmware.c @@ -128,8 +128,8 @@ static int sec_firmware_check_copy_loadable(const void *sec_firmware_img, return -EINVAL; } - if (fit_image_get_data(sec_firmware_img, ld_node_off, - &data, &size)) { + if (fit_image_get_emb_data(sec_firmware_img, ld_node_off, + &data, &size)) { printf("SEC Loadable: Can't get subimage data/size"); return -ENOENT; } diff --git a/arch/arm/mach-k3/r5/sysfw-loader.c b/arch/arm/mach-k3/r5/sysfw-loader.c index 188731e673d..c323d2f78f8 100644 --- a/arch/arm/mach-k3/r5/sysfw-loader.c +++ b/arch/arm/mach-k3/r5/sysfw-loader.c @@ -115,7 +115,7 @@ static int fit_get_data_by_name(const void *fit, int images, const char *name, if (node_offset < 0) return -ENOENT; - return fit_image_get_data(fit, node_offset, addr, size); + return fit_image_get_emb_data(fit, node_offset, addr, size); } static void k3_start_system_controller(int rproc_id, bool rproc_loaded, diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 0cf3824d203..90c0376ca83 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -104,9 +104,9 @@ static int boot_prep_linux(struct bootm_headers *images) is_zimage = 1; #if defined(CONFIG_FIT) } else if (images->fit_uname_os && is_zimage) { - ret = fit_image_get_data(images->fit_hdr_os, - images->fit_noffset_os, - (const void **)&data, &len); + ret = fit_image_get_emb_data(images->fit_hdr_os, + images->fit_noffset_os, + (const void **)&data, &len); if (ret) { puts("Can't get image data/size!\n"); goto error; diff --git a/boot/image-fit.c b/boot/image-fit.c index db7fb61bca9..7ad6e51d8ed 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -902,13 +902,13 @@ int fit_image_get_entry(const void *fit, int noffset, ulong *entry) } /** - * fit_image_get_data - get data property and its size for a given component image node + * fit_image_get_emb_data - get data property and its size for a given component image node * @fit: pointer to the FIT format image header * @noffset: component image node offset * @data: double pointer to void, will hold data property's data address * @size: pointer to size_t, will hold data property's data size * - * fit_image_get_data() finds data property in a given component image node. + * fit_image_get_emb_data() finds data property in a given component image node. * If the property is found its data start address and size are returned to * the caller. * @@ -916,8 +916,8 @@ int fit_image_get_entry(const void *fit, int noffset, ulong *entry) * 0, on success * -1, on failure */ -int fit_image_get_data(const void *fit, int noffset, - const void **data, size_t *size) +int fit_image_get_emb_data(const void *fit, int noffset, const void **data, + size_t *size) { int len; @@ -1074,7 +1074,7 @@ int fit_image_get_data_and_size(const void *fit, int noffset, *size = len; } } else { - ret = fit_image_get_data(fit, noffset, data, size); + ret = fit_image_get_emb_data(fit, noffset, data, size); } return ret; diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ac8462577ff..64c4349b138 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -289,7 +289,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, src = src_ptr + overhead; } else { /* Embedded data */ - if (fit_image_get_data(fit, node, &data, &length)) { + if (fit_image_get_emb_data(fit, node, &data, &length)) { puts("Cannot get image data/size\n"); return -ENOENT; } diff --git a/common/splash_source.c b/common/splash_source.c index f43e7cc1be7..5ac32a2f995 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -396,7 +396,9 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) /* Extract the splash data from FIT */ /* 1. Test if splash is in FIT internal data. */ - if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, &internal_splash_size)) + if (!fit_image_get_emb_data(fit_header, node_offset, + &internal_splash_data, + &internal_splash_size)) memmove((void *)(uintptr_t)bmp_load_addr, internal_splash_data, internal_splash_size); /* 2. Test if splash is in FIT external data with fixed position. */ else if (!fit_image_get_data_position(fit_header, node_offset, &external_splash_addr)) diff --git a/common/update.c b/common/update.c index 6801b49479d..d149ca18e78 100644 --- a/common/update.c +++ b/common/update.c @@ -200,7 +200,7 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr, { const void *data; - if (fit_image_get_data(fit, noffset, &data, (size_t *)size)) + if (fit_image_get_emb_data(fit, noffset, &data, (size_t *)size)) return 1; if (fit_image_get_load(fit, noffset, (ulong *)fladdr)) diff --git a/include/image.h b/include/image.h index ab96510f62c..e54e2190af5 100644 --- a/include/image.h +++ b/include/image.h @@ -1160,8 +1160,8 @@ int fit_image_get_type(const void *fit, int noffset, uint8_t *type); int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp); int fit_image_get_load(const void *fit, int noffset, ulong *load); int fit_image_get_entry(const void *fit, int noffset, ulong *entry); -int fit_image_get_data(const void *fit, int noffset, - const void **data, size_t *size); +int fit_image_get_emb_data(const void *fit, int noffset, const void **data, + size_t *size); int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset); int fit_image_get_data_position(const void *fit, int noffset, int *data_position); diff --git a/tools/image-host.c b/tools/image-host.c index 5e01b853c50..007a94f72d5 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -574,7 +574,7 @@ int fit_image_cipher_data(const char *keydir, void *keydest, } /* Get image data and data length */ - if (fit_image_get_data(fit, image_noffset, &data, &size)) { + if (fit_image_get_emb_data(fit, image_noffset, &data, &size)) { fprintf(stderr, "Can't get image data/size\n"); return -1; } @@ -654,7 +654,7 @@ int fit_image_add_verification_data(const char *keydir, const char *keyfile, int noffset; /* Get image data and data length */ - if (fit_image_get_data(fit, image_noffset, &data, &size)) { + if (fit_image_get_emb_data(fit, image_noffset, &data, &size)) { fprintf(stderr, "Can't get image data/size\n"); return -1; } From c83e71064e9b85743a79978c79b01a0f2dc1e90b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:13 -0700 Subject: [PATCH 14/30] boot: Rename fit_image_get_data_and_size() This function is really just getting the data. The size comes along for the ride. In fact this function is only reliable way to obtain the data for an image in a FIT, since the FIT may use external data. Rename it to fit_image_get_data() Signed-off-by: Simon Glass --- boot/image-board.c | 4 ++-- boot/image-fit.c | 20 +++++++++----------- cmd/ximg.c | 3 +-- include/image.h | 4 ++-- tools/fit_image.c | 2 +- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/boot/image-board.c b/boot/image-board.c index b726bd6b303..458153b40bd 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -1083,8 +1083,8 @@ fallback: } /* get script subimage data address and length */ - if (fit_image_get_data_and_size(fit_hdr, noffset, - &fit_data, &fit_len)) { + if (fit_image_get_data(fit_hdr, noffset, &fit_data, + &fit_len)) { puts("Could not find script subimage data\n"); return 1; } diff --git a/boot/image-fit.c b/boot/image-fit.c index 7ad6e51d8ed..70080d1a6c0 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -509,7 +509,7 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) fit_image_get_comp(fit, image_noffset, &comp); printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); - ret = fit_image_get_data_and_size(fit, image_noffset, &data, &size); + ret = fit_image_get_data(fit, image_noffset, &data, &size); if (!tools_build()) { printf("%s Data Start: ", p); @@ -1031,14 +1031,14 @@ int fit_image_get_data_size_unciphered(const void *fit, int noffset, } /** - * fit_image_get_data_and_size - get data and its size including + * fit_image_get_data - get data and its size including * both embedded and external data * @fit: pointer to the FIT format image header * @noffset: component image node offset * @data: double pointer to void, will hold data property's data address * @size: pointer to size_t, will hold data property's data size * - * fit_image_get_data_and_size() finds data and its size including + * fit_image_get_data() finds data and its size including * both embedded and external data. If the property is found * its data start address and size are returned to the caller. * @@ -1046,8 +1046,8 @@ int fit_image_get_data_size_unciphered(const void *fit, int noffset, * 0, on success * otherwise, on failure */ -int fit_image_get_data_and_size(const void *fit, int noffset, - const void **data, size_t *size) +int fit_image_get_data(const void *fit, int noffset, const void **data, + size_t *size) { bool external_data = false; int offset; @@ -1432,7 +1432,7 @@ int fit_image_verify(const void *fit, int image_noffset) goto err; } /* Get image data and data length */ - if (fit_image_get_data_and_size(fit, image_noffset, &data, &size)) { + if (fit_image_get_data(fit, image_noffset, &data, &size)) { err_msg = "Can't get image data/size"; goto err; } @@ -1781,8 +1781,7 @@ int fit_conf_find_compat(const void *fit, const void *fdt) } /* search in this config's kernel FDT */ - if (fit_image_get_data_and_size(fit, kfdt_noffset, - &fdt, &sz)) { + if (fit_image_get_data(fit, kfdt_noffset, &fdt, &sz)) { debug("Failed to get fdt \"%s\".\n", kfdt_name); continue; } @@ -1941,7 +1940,7 @@ static int fit_get_data_tail(const void *fit, int noffset, if (!fit_image_verify(fit, noffset)) return -EINVAL; - if (fit_image_get_data_and_size(fit, noffset, data, size)) + if (fit_image_get_data(fit, noffset, data, size)) return -ENOENT; if (!fit_get_desc(fit, noffset, &desc)) @@ -2198,8 +2197,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); /* get image data address and length */ - if (fit_image_get_data_and_size(fit, noffset, - (const void **)&buf, &size)) { + if (fit_image_get_data(fit, noffset, (const void **)&buf, &size)) { printf("Could not find %s subimage data!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); return -ENOENT; diff --git a/cmd/ximg.c b/cmd/ximg.c index 1c96f5a0a1f..29d7c3279b3 100644 --- a/cmd/ximg.c +++ b/cmd/ximg.c @@ -161,8 +161,7 @@ do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } /* get subimage/external data address and length */ - if (fit_image_get_data_and_size(fit_hdr, noffset, - &fit_data, &fit_len)) { + if (fit_image_get_data(fit_hdr, noffset, &fit_data, &fit_len)) { puts("Could not find script subimage data\n"); return 1; } diff --git a/include/image.h b/include/image.h index e54e2190af5..50c44118ebc 100644 --- a/include/image.h +++ b/include/image.h @@ -1168,8 +1168,8 @@ int fit_image_get_data_position(const void *fit, int noffset, int fit_image_get_data_size(const void *fit, int noffset, int *data_size); int fit_image_get_data_size_unciphered(const void *fit, int noffset, size_t *data_size); -int fit_image_get_data_and_size(const void *fit, int noffset, - const void **data, size_t *size); +int fit_image_get_data(const void *fit, int noffset, const void **data, + size_t *size); /** * fit_image_get_phase() - Get the phase from a FIT image diff --git a/tools/fit_image.c b/tools/fit_image.c index 0fccfbb4ebd..caed8d5f901 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -876,7 +876,7 @@ static int fit_image_extract( int ret; /* get the data address and size of component at offset "image_noffset" */ - ret = fit_image_get_data_and_size(fit, image_noffset, &file_data, &file_size); + ret = fit_image_get_data(fit, image_noffset, &file_data, &file_size); if (ret) { fprintf(stderr, "Could not get component information\n"); return ret; From 1604b4254b1044916414db9f9f5bc12431ce258f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:14 -0700 Subject: [PATCH 15/30] boot: Use fit_image_get_data() to get data Use this function instead of fit_image_get_emb_data() data, since it works will FITs that use external data. Signed-off-by: Simon Glass --- arch/arm/cpu/armv8/sec_firmware.c | 4 ++-- arch/arm/mach-k3/r5/sysfw-loader.c | 2 +- arch/x86/lib/bootm.c | 6 +++--- common/splash_source.c | 19 ++++--------------- common/update.c | 2 +- 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c index b7c73f288bd..44372cbe4a1 100644 --- a/arch/arm/cpu/armv8/sec_firmware.c +++ b/arch/arm/cpu/armv8/sec_firmware.c @@ -128,8 +128,8 @@ static int sec_firmware_check_copy_loadable(const void *sec_firmware_img, return -EINVAL; } - if (fit_image_get_emb_data(sec_firmware_img, ld_node_off, - &data, &size)) { + if (fit_image_get_data(sec_firmware_img, ld_node_off, + &data, &size)) { printf("SEC Loadable: Can't get subimage data/size"); return -ENOENT; } diff --git a/arch/arm/mach-k3/r5/sysfw-loader.c b/arch/arm/mach-k3/r5/sysfw-loader.c index c323d2f78f8..188731e673d 100644 --- a/arch/arm/mach-k3/r5/sysfw-loader.c +++ b/arch/arm/mach-k3/r5/sysfw-loader.c @@ -115,7 +115,7 @@ static int fit_get_data_by_name(const void *fit, int images, const char *name, if (node_offset < 0) return -ENOENT; - return fit_image_get_emb_data(fit, node_offset, addr, size); + return fit_image_get_data(fit, node_offset, addr, size); } static void k3_start_system_controller(int rproc_id, bool rproc_loaded, diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 90c0376ca83..b37f42f5db6 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -104,9 +104,9 @@ static int boot_prep_linux(struct bootm_headers *images) is_zimage = 1; #if defined(CONFIG_FIT) } else if (images->fit_uname_os && is_zimage) { - ret = fit_image_get_emb_data(images->fit_hdr_os, - images->fit_noffset_os, - (const void **)&data, &len); + ret = fit_image_get_data(images->fit_hdr_os, + images->fit_noffset_os, + (const void **)&data, &len); if (ret) { puts("Can't get image data/size!\n"); goto error; diff --git a/common/splash_source.c b/common/splash_source.c index 5ac32a2f995..2df78a4f2d7 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -395,21 +395,10 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) } /* Extract the splash data from FIT */ - /* 1. Test if splash is in FIT internal data. */ - if (!fit_image_get_emb_data(fit_header, node_offset, - &internal_splash_data, - &internal_splash_size)) - memmove((void *)(uintptr_t)bmp_load_addr, internal_splash_data, internal_splash_size); - /* 2. Test if splash is in FIT external data with fixed position. */ - else if (!fit_image_get_data_position(fit_header, node_offset, &external_splash_addr)) - is_splash_external = true; - /* 3. Test if splash is in FIT external data with offset. */ - else if (!fit_image_get_data_offset(fit_header, node_offset, &external_splash_addr)) { - /* Align data offset to 4-byte boundary */ - fit_size = ALIGN(fdt_totalsize(fit_header), 4); - /* External splash offset means the offset by end of FIT header */ - external_splash_addr += location->offset + fit_size; - is_splash_external = true; + if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, + &internal_splash_size)) { + memmove((void *)(uintptr_t)bmp_load_addr, internal_splash_data, + internal_splash_size); } else { printf("Failed to get splash image from FIT\n"); return -ENODATA; diff --git a/common/update.c b/common/update.c index d149ca18e78..6801b49479d 100644 --- a/common/update.c +++ b/common/update.c @@ -200,7 +200,7 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr, { const void *data; - if (fit_image_get_emb_data(fit, noffset, &data, (size_t *)size)) + if (fit_image_get_data(fit, noffset, &data, (size_t *)size)) return 1; if (fit_image_get_load(fit, noffset, (ulong *)fladdr)) From 5e0c63d04cc5d55d3977f18ca292aa50825bbfac Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:15 -0700 Subject: [PATCH 16/30] test: Fix inpected typo in upl test Fix a typo in the test comment. Signed-off-by: Simon Glass --- test/py/tests/test_upl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/py/tests/test_upl.py b/test/py/tests/test_upl.py index 3164bda6b71..90125c4dc1b 100644 --- a/test/py/tests/test_upl.py +++ b/test/py/tests/test_upl.py @@ -17,7 +17,7 @@ def test_upl_handoff(u_boot_console): proper and runs a test to check that the parameters are correct. The entire FIT is loaded into memory in SPL (in upl_load_from_image()) so - that it can be inpected in upl_test_info_norun + that it can be inspected in upl_test_info_norun """ cons = u_boot_console ram = os.path.join(cons.config.build_dir, 'ram.bin') From 24768a23a9b36fe2ae9814c166dc8912f981ff3b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:16 -0700 Subject: [PATCH 17/30] emulation: fdt: Relax condition for OF_HAS_PRIOR_STAGE QEMU always gets its devicetree from the OF_BOARD mechanism so we should not depend on !BLOBLIST here. It's not clear why we need to have any relationship with BLOBLIST so let's remove the entire condition. Signed-off-by: Simon Glass Fixes: 2b71470628c dts: OF_HAS_PRIOR_STAGE should depend on !BLOBLIST Reviewed-by: Tom Rini --- dts/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/dts/Kconfig b/dts/Kconfig index ffd50c04846..6a5141b56e9 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -183,7 +183,6 @@ config OF_BOARD config OF_HAS_PRIOR_STAGE bool - depends on !BLOBLIST help Indicates that a prior stage of the firmware (before U-Boot proper) makes use of device tree and this board normally boots with that prior From 53d5a221632eeef7483d250fdde09bde6cb54df9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:17 -0700 Subject: [PATCH 18/30] emulation: Use bloblist to hold tables QEMU can have its own internal ACPI and SMBIOS tables. At present U-Boot copies out the SMBIOS tables but points directly to the ACPI ones. The ACPI tables are not aligned on a 4KB boundary, which means that UPL cannot use them directly, since it uses a reserved-memory node for the tables and that it assumed (by EDK2) to be 4KB-aligned. On x86, QEMU provides the tables in a mapped memory region and U-Boot makes use of these directly, thus making it difficult to use any common code. Adjust the logic to fit within the existing table-generation code. Use a bloblist always and ensure that the ACPI tables is placed in an aligned region. Set a size of 8K for QEMU. This does not actually put all the tables in one place, for QEMU, since it currently adds a pointer to the tables in QFW. On ARM, enable bloblist so that SMBIOS tables can be added to the bloblist. Signed-off-by: Simon Glass --- arch/x86/lib/tables.c | 2 +- configs/qemu-x86_64_defconfig | 1 - configs/qemu_arm64_defconfig | 2 ++ configs/qemu_arm_defconfig | 2 ++ drivers/misc/qfw_acpi.c | 37 ++++++++++++++++++++++++++-- drivers/misc/qfw_smbios.c | 45 ++++++++++++++++------------------- lib/Kconfig | 1 + lib/Makefile | 5 ++++ 8 files changed, 67 insertions(+), 28 deletions(-) diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 45a70e92763..5fc7dc75377 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -61,7 +61,7 @@ static struct table_info table_list[] = { #ifdef CONFIG_GENERATE_ACPI_TABLE { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, #endif -#if defined(CONFIG_GENERATE_SMBIOS_TABLE) && !defined(CONFIG_QFW_SMBIOS) +#ifdef CONFIG_GENERATE_SMBIOS_TABLE { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, 0x1000, 0x100}, #endif }; diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index f93721fceb8..3c0fc7a34fe 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -33,7 +33,6 @@ CONFIG_LOGF_FUNC=y CONFIG_SPL_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_PCI_INIT_R=y -CONFIG_BLOBLIST=y CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0x10000 CONFIG_SPL_NO_BSS_LIMIT=y diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig index 06ac6fed3bc..e760e987c47 100644 --- a/configs/qemu_arm64_defconfig +++ b/configs/qemu_arm64_defconfig @@ -26,6 +26,8 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_PCI_INIT_R=y +CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_SIZE_RELOC=0x2000 CONFIG_CMD_SMBIOS=y CONFIG_CMD_BOOTZ=y CONFIG_CMD_BOOTEFI_SELFTEST=y diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig index e164407d494..d8e916dd2b3 100644 --- a/configs/qemu_arm_defconfig +++ b/configs/qemu_arm_defconfig @@ -27,6 +27,8 @@ CONFIG_USE_PREBOOT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_PCI_INIT_R=y +CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_SIZE_RELOC=0x2000 CONFIG_CMD_BOOTEFI_SELFTEST=y CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_DFU=y diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c index 7ffed1e8c02..0d0cf764689 100644 --- a/drivers/misc/qfw_acpi.c +++ b/drivers/misc/qfw_acpi.c @@ -7,6 +7,7 @@ #define LOG_CATEGORY UCLASS_QFW #include +#include #include #include #include @@ -160,6 +161,15 @@ ulong write_acpi_tables(ulong addr) struct bios_linker_entry *entry; uint32_t size; struct udevice *dev; + struct acpi_ctx *ctx; + + ctx = malloc(sizeof(*ctx)); + if (!ctx) { + printf("error: out of memory for acpi ctx\n"); + return addr; + } + + acpi_setup_ctx(ctx, addr); ret = qfw_get_dev(&dev); if (ret) { @@ -257,6 +267,29 @@ ulong acpi_get_rsdp_addr(void) return file->addr; } +void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, + struct acpi_xsdt *xsdt) +{ + memset(rsdp, 0, sizeof(struct acpi_rsdp)); + + memcpy(rsdp->signature, RSDP_SIG, 8); + memcpy(rsdp->oem_id, OEM_ID, 6); + + if (rsdt) + rsdp->rsdt_address = nomap_to_sysmem(rsdt); + + if (xsdt) + rsdp->xsdt_address = nomap_to_sysmem(xsdt); + + rsdp->length = sizeof(struct acpi_rsdp); + rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; + + /* Calculate checksums */ + rsdp->checksum = table_compute_checksum(rsdp, 20); + rsdp->ext_checksum = table_compute_checksum(rsdp, + sizeof(struct acpi_rsdp)); +} + #ifndef CONFIG_X86 static int evt_write_acpi_tables(void) { @@ -264,9 +297,9 @@ static int evt_write_acpi_tables(void) void *ptr; /* Reserve 64K for ACPI tables, aligned to a 4K boundary */ - ptr = memalign(SZ_4K, SZ_64K); + ptr = bloblist_add(BLOBLISTT_ACPI_TABLES, SZ_64K, 12); if (!ptr) - return -ENOMEM; + return -ENOBUFS; addr = map_to_sysmem(ptr); /* Generate ACPI tables */ diff --git a/drivers/misc/qfw_smbios.c b/drivers/misc/qfw_smbios.c index c3e8c310d00..93c4a80286b 100644 --- a/drivers/misc/qfw_smbios.c +++ b/drivers/misc/qfw_smbios.c @@ -5,6 +5,7 @@ #define LOG_CATEGORY UCLASS_QFW +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -105,11 +107,10 @@ out: /** * qfw_write_smbios_tables() - copy SMBIOS tables from QEMU * - * @addr: target buffer - * @size: size of target buffer + * @addr: address of target buffer * Return: 0 for success, -ve on error */ -static int qfw_write_smbios_tables(u8 *addr, uint32_t size) +ulong write_smbios_table(ulong addr) { int ret; struct udevice *dev; @@ -143,16 +144,13 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size) table = qfw_load_smbios_table(dev, &table_size, "etc/smbios/smbios-tables"); - if (table_size + sizeof(struct smbios3_entry) > size) { - free(table); - return -ENOMEM; - } - memcpy(addr, table, table_size); + memcpy((void *)addr, table, table_size); free(table); - return 0; + return addr + table_size; } +#ifndef CONFIG_X86 /** * qfw_evt_write_smbios_tables() - event handler for copying QEMU SMBIOS tables * @@ -160,9 +158,9 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size) */ static int qfw_evt_write_smbios_tables(void) { - phys_addr_t addr; + ulong addr, end; void *ptr; - int ret; + /* * TODO: * This size is currently hard coded in lib/efi_loader/efi_smbios.c. @@ -170,22 +168,21 @@ static int qfw_evt_write_smbios_tables(void) */ uint32_t size = SZ_4K; - /* Reserve 64K for SMBIOS tables, aligned to a 4K boundary */ - ptr = memalign(SZ_4K, size); - if (!ptr) { - log_err("Out of memory\n"); - return -ENOMEM; - } + log_debug("qfw_evt_write_smbios_tables bloblist\n"); + /* Reserve 4K for SMBIOS tables, aligned to a 4K boundary */ + ptr = bloblist_add(BLOBLISTT_SMBIOS_TABLES, size, 12); + if (!ptr) + return log_msg_ret("bloblist", -ENOBUFS); + addr = map_to_sysmem(ptr); /* Generate SMBIOS tables */ - ret = qfw_write_smbios_tables(ptr, size); - if (ret) { - if (CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)) { - log_info("Falling back to U-Boot generated SMBIOS tables\n"); - write_smbios_table(addr); - } + end = write_smbios_table(addr); + if (IS_ERR_VALUE(end)) { + log_warning("SMBIOS: Failed to write (err=%dE)\n", (int)end); } else { + if (end - addr > size) + return -ENOMEM; log_debug("SMBIOS tables copied from QEMU\n"); } @@ -193,5 +190,5 @@ static int qfw_evt_write_smbios_tables(void) return 0; } - EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables); +#endif /* !X86 */ diff --git a/lib/Kconfig b/lib/Kconfig index 8f1a96d98c4..5217edea62c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1067,6 +1067,7 @@ menu "System tables" config BLOBLIST_TABLES bool "Put tables in a bloblist" depends on BLOBLIST + default y if X86 default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE) default n help diff --git a/lib/Makefile b/lib/Makefile index 5cb3278d2ef..228c9cf4b1c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -41,7 +41,12 @@ obj-$(CONFIG_ERRNO_STR) += errno_str.o obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o + +# With QEMU the SMBIOS tables come from there, not from U-Boot +ifndef CONFIG_QFW_SMBIOS obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o +endif + obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o From d56c761ca29e420fde7ad464fcf515564932a952 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:18 -0700 Subject: [PATCH 19/30] x86: Create more space for SPL with qemu-x86_64 The space here is quite tight and there is plenty of room in the ROM. Move SPL earlier to allow for expansion. Signed-off-by: Simon Glass --- configs/qemu-x86_64_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 3c0fc7a34fe..39375c76227 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -7,7 +7,7 @@ CONFIG_MAX_CPUS=2 CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx" CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 -CONFIG_SPL_TEXT_BASE=0xfffd4000 +CONFIG_SPL_TEXT_BASE=0xfffd0000 CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200 CONFIG_X86_RUN_64BIT=y From 97425461e7be88c047f7acb3d701c74cf2acac39 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:19 -0700 Subject: [PATCH 20/30] pci: video: Set up the pixel-format field Add this information to the handoff structure so that it is available to U-Boot proper. Update bochs and the video handoff. Signed-off-by: Simon Glass --- drivers/pci/pci_rom.c | 3 +++ drivers/video/bochs.c | 1 + drivers/video/video-uclass.c | 1 + include/video.h | 2 ++ 4 files changed, 7 insertions(+) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 2753df275ca..3697ad00be2 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -347,6 +347,7 @@ int vesa_setup_video_priv(struct vesa_mode_info *vesa, u64 fb, case 32: case 24: uc_priv->bpix = VIDEO_BPP32; + uc_priv->format = VIDEO_X8B8G8R8; break; case 16: uc_priv->bpix = VIDEO_BPP16; @@ -392,6 +393,7 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) uc_priv->ysize = ho->ysize; uc_priv->line_length = ho->line_length; uc_priv->bpix = ho->bpix; + uc_priv->format = ho->format; } else { bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); ret = dm_pci_run_vga_bios(dev, int15_handler, @@ -438,6 +440,7 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) ho->ysize = uc_priv->ysize; ho->line_length = uc_priv->line_length; ho->bpix = uc_priv->bpix; + ho->format = uc_priv->format; } return 0; diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c index 00e673a4db0..c34bc23f274 100644 --- a/drivers/video/bochs.c +++ b/drivers/video/bochs.c @@ -64,6 +64,7 @@ static int bochs_init_fb(struct udevice *dev) uc_priv->xsize = xsize; uc_priv->ysize = ysize; uc_priv->bpix = VIDEO_BPP32; + uc_priv->format = VIDEO_X8B8G8R8; /* setup video mode */ bochs_write(mmio, INDEX_ENABLE, 0); diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index a5b3e898066..ff4f2199585 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -589,6 +589,7 @@ static int video_post_probe(struct udevice *dev) ho->ysize = priv->ysize; ho->line_length = priv->line_length; ho->bpix = priv->bpix; + ho->format = priv->format; } if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base) diff --git a/include/video.h b/include/video.h index 4ec71ab16da..a1f7fd7e839 100644 --- a/include/video.h +++ b/include/video.h @@ -150,6 +150,7 @@ struct video_ops { * set by the driver, but if not, the uclass will set it after * probing * @bpix: Encoded bits per pixel (enum video_log2_bpp) + * @format: Video format (enum video_format) */ struct video_handoff { u64 fb; @@ -158,6 +159,7 @@ struct video_handoff { u16 ysize; u32 line_length; u8 bpix; + u8 format; }; /** enum colour_idx - the 16 colors supported by consoles */ From 44e39ff6acf080379c279de402ec58731d0fe66a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:20 -0700 Subject: [PATCH 21/30] x86: Show an error if video fails If video is enabled we expect it to work. Avoid silent failure by adding a panic if things go wrong. Expand the SPL malloc-area for qemu-x86_64 to avoid a panic. Signed-off-by: Simon Glass --- arch/x86/lib/spl.c | 9 +++++++-- configs/qemu-x86_64_defconfig | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index f761fbc8bc3..aad748532d0 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -300,9 +300,14 @@ void spl_board_init(void) if (CONFIG_IS_ENABLED(VIDEO)) { struct udevice *dev; + int ret; /* Set up PCI video in SPL if required */ - uclass_first_device_err(UCLASS_PCI, &dev); - uclass_first_device_err(UCLASS_VIDEO, &dev); + ret = uclass_first_device_err(UCLASS_PCI, &dev); + if (ret) + panic("Failed to set up PCI"); + ret = uclass_first_device_err(UCLASS_VIDEO, &dev); + if (ret) + panic("Failed to set up video"); } } diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 39375c76227..2771a4b9e19 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -6,7 +6,7 @@ CONFIG_ENV_SIZE=0x40000 CONFIG_MAX_CPUS=2 CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx" -CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x3000 CONFIG_SPL_TEXT_BASE=0xfffd0000 CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200 From 9d5072bb1d965b0077ff0a1f73adcc5b5e033099 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:21 -0700 Subject: [PATCH 22/30] x86: Support jumping to a UPL image Add a function to allow x86 boards to jump to a UPL images. Currently only 32-bit entry is supported. Signed-off-by: Simon Glass --- arch/x86/lib/bootm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index b37f42f5db6..0827a884b1d 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -259,3 +259,14 @@ int do_bootm_linux(int flag, struct bootm_info *bmi) return boot_jump_linux(images); } + +int arch_upl_jump(ulong entry, const struct abuf *buf) +{ + typedef EFIAPI void (*h_func)(void *hoff); + h_func func; + + func = (h_func)(ulong)entry; + func(buf->data); + + return -EFAULT; +} From 4339a82a4908b5905f70ea8f8d5cde7455fefb92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:22 -0700 Subject: [PATCH 23/30] x86: Enable UPL handoff for SPL Add the GD_FLG_UPL so that a UPL-handoff is created. Signed-off-by: Simon Glass --- arch/x86/lib/spl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index aad748532d0..7a033505101 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -298,6 +298,9 @@ void spl_board_init(void) if (IS_ENABLED(CONFIG_QEMU)) qemu_chipset_init(); + if (CONFIG_IS_ENABLED(UPL_OUT)) + gd->flags |= GD_FLG_UPL; + if (CONFIG_IS_ENABLED(VIDEO)) { struct udevice *dev; int ret; From d013e80be7d2efa5f5afa27a50501faa5f89ee27 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:23 -0700 Subject: [PATCH 24/30] x86: Move tables to use SZ macros Update the tables to use linux/sizes rather than open-coped values. Signed-off-by: Simon Glass Suggested-by: Heinrich Schuchardt --- arch/x86/lib/tables.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 5fc7dc75377..9e4f21ae5ad 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -16,6 +16,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -59,10 +60,10 @@ static struct table_info table_list[] = { * that the calculation of gd->table_end works properly */ #ifdef CONFIG_GENERATE_ACPI_TABLE - { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, + { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, SZ_64K, SZ_4K}, #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE - { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, 0x1000, 0x100}, + { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, SZ_4K, SZ_256}, #endif }; From 5a7e8839e4191299cd78755e0ff06e11ae15b2be Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:24 -0700 Subject: [PATCH 25/30] x86: Align the SMBIOS table to a 4K boundary This isn't strictly needed, but with UPL we use the reserved-memory nodes to indicate where the SMBIOS table is. Tianocore requires 4KB alignment on these regions, so it is easier to adjust the alignment to match. Signed-off-by: Simon Glass --- arch/x86/lib/tables.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 9e4f21ae5ad..44fe80c5224 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -63,7 +63,11 @@ static struct table_info table_list[] = { { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, SZ_64K, SZ_4K}, #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE - { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, SZ_4K, SZ_256}, + /* + * align this to a 4K boundary, since UPL adds a reserved-memory node + * for it + */ + { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, SZ_4K, SZ_4K}, #endif }; From cfb4aa2a754ed1849425418ecbb0d80dbfe72579 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:25 -0700 Subject: [PATCH 26/30] efi_loader: Avoid mapping the ACPI tables twice The add_u_boot_and_runtime() function paints with a broad brush, considering all of the memory from the top of U-Boot stack to gd->ram_top as EFI_RUNTIME_SERVICES_CODE This is fine, but we need to make sure we don't add a separate entry for any ACPI tables in this region (which happens when bloblist is used for tables). Otherwise the memory map looks strange and we get a test failure on qemu-x86 (only) for the 'virtual address map' test. Good map: Type Start End Attributes ================ ================ ================ ========== CONVENTIONAL 0000000000000000-00000000000a0000 WB RESERVED 00000000000a0000-00000000000f0000 WB RUNTIME DATA 00000000000f0000-00000000000f2000 WB|RT RESERVED 00000000000f2000-0000000000100000 WB CONVENTIONAL 0000000000100000-0000000005cc7000 WB BOOT DATA 0000000005cc7000-0000000005ccc000 WB RUNTIME DATA 0000000005ccc000-0000000005ccd000 WB|RT BOOT DATA 0000000005ccd000-0000000005cce000 WB RUNTIME DATA 0000000005cce000-0000000005cf0000 WB|RT BOOT DATA 0000000005cf0000-0000000006cf5000 WB RESERVED 0000000006cf5000-0000000006cfa000 WB ACPI RECLAIM MEM 0000000006cfa000-0000000006d1c000 WB RESERVED 0000000006d1c000-0000000006f35000 WB RUNTIME CODE 0000000006f35000-0000000006f37000 WB|RT RESERVED 0000000006f37000-0000000008000000 WB RESERVED 00000000e0000000-00000000f0000000 WB Bad map: (with BLOBLIST_TABLES but without this patch): Type Start End Attributes ================ ================ ================ ========== CONVENTIONAL 0000000000000000-00000000000a0000 WB RESERVED 00000000000a0000-00000000000f0000 WB ACPI RECLAIM MEM 00000000000f0000-00000000000f1000 WB RESERVED 00000000000f1000-0000000000100000 WB CONVENTIONAL 0000000000100000-0000000005ca5000 WB BOOT DATA 0000000005ca5000-0000000005caa000 WB RUNTIME DATA 0000000005caa000-0000000005cab000 WB|RT BOOT DATA 0000000005cab000-0000000005cac000 WB RUNTIME DATA 0000000005cac000-0000000005cce000 WB|RT BOOT DATA 0000000005cce000-0000000006cd3000 WB RUNTIME DATA 0000000006cd3000-0000000006cd5000 WB|RT BOOT DATA 0000000006cd5000-0000000006cf4000 WB RESERVED 0000000006cf4000-0000000006cf9000 WB ACPI RECLAIM MEM 0000000006cf9000-0000000006ce6000 WB Signed-off-by: Simon Glass --- lib/efi_loader/efi_acpi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index 67bd7f8ca24..ff305a6b13e 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -25,6 +25,16 @@ efi_status_t efi_acpi_register(void) ulong addr, start, end; efi_status_t ret; + /* + * The bloblist is already marked reserved. For now, we don't bother + * marking it with EFI_ACPI_RECLAIM_MEMORY since we would need to cut a + * hole in the EFI_BOOT_SERVICES_CODE region added by + * add_u_boot_and_runtime(). At some point that function could create a + * more detailed map. + */ + if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) + return EFI_SUCCESS; + /* Mark space used for tables */ start = ALIGN_DOWN(gd->arch.table_start, EFI_PAGE_MASK); end = ALIGN(gd->arch.table_end, EFI_PAGE_MASK); From d5bc5c6cb0291203fe848a8532a7ecbcd44cfe9e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:26 -0700 Subject: [PATCH 27/30] x86: emulation: Enable bloblist Add bloblist support so that tables can be generated and placed in a bloblist, then passed to a payload using UPL Signed-off-by: Simon Glass --- configs/qemu-x86_64_defconfig | 2 ++ configs/qemu-x86_defconfig | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 2771a4b9e19..792ba06c2b8 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -1,6 +1,7 @@ CONFIG_X86=y CONFIG_TEXT_BASE=0x1110000 CONFIG_SYS_MALLOC_F_LEN=0x1000 +CONFIG_BLOBLIST_SIZE_RELOC=0x20000 CONFIG_NR_DRAM_BANKS=8 CONFIG_ENV_SIZE=0x40000 CONFIG_MAX_CPUS=2 @@ -33,6 +34,7 @@ CONFIG_LOGF_FUNC=y CONFIG_SPL_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_PCI_INIT_R=y +CONFIG_BLOBLIST=y CONFIG_BLOBLIST_FIXED=y CONFIG_BLOBLIST_ADDR=0x10000 CONFIG_SPL_NO_BSS_LIMIT=y diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 947d15cd727..0b0e10c795f 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -1,6 +1,7 @@ CONFIG_X86=y CONFIG_TEXT_BASE=0xFFF00000 CONFIG_SYS_MALLOC_F_LEN=0x1000 +CONFIG_BLOBLIST_SIZE_RELOC=0x20000 CONFIG_NR_DRAM_BANKS=8 CONFIG_ENV_SIZE=0x40000 CONFIG_MAX_CPUS=2 @@ -23,6 +24,9 @@ CONFIG_LOG=y CONFIG_LOGF_FUNC=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_PCI_INIT_R=y +CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_FIXED=y +CONFIG_BLOBLIST_ADDR=0x10000 CONFIG_CMD_CPU=y CONFIG_CMD_BOOTEFI_SELFTEST=y CONFIG_CMD_NVEDIT_EFI=y From ff698f2ddbcce5601a19fd61bef45aedd3d59cc6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:27 -0700 Subject: [PATCH 28/30] dm: core: Clarify behaviour of ofnode_name_eq() This function is somewhat ambiguous, so expand the comments and add a test for the undefined behaviour. Signed-off-by: Simon Glass --- include/dm/ofnode.h | 7 +++---- test/dm/core.c | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index c5f0a6d6788..2f3da384eba 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -386,11 +386,10 @@ static inline oftree oftree_from_np(struct device_node *root) void oftree_dispose(oftree tree); /** - * ofnode_name_eq() - Check if the node name is equivalent to a given name - * ignoring the unit address + * ofnode_name_eq() - Check a node name ignoring its unit address * - * @node: valid node reference that has to be compared - * @name: name that has to be compared with the node name + * @node: valid node to compared, which may have a unit address + * @name: name (without unit address) to compare with the node name * Return: true if matches, false if it doesn't match */ bool ofnode_name_eq(ofnode node, const char *name); diff --git a/test/dm/core.c b/test/dm/core.c index c59ffc6f611..d40916ef588 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -186,6 +186,8 @@ static int dm_test_compare_node_name(struct unit_test_state *uts) ut_assert(ofnode_valid(node)); ut_assert(ofnode_name_eq(node, "mmio-bus")); + ut_assert(!ofnode_name_eq(node, "mmio-bus@0")); + return 0; } DM_TEST(dm_test_compare_node_name, UTF_SCAN_PDATA); From aacc05b07d28e01bbbaf9037b3e8e1275e48701f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:28 -0700 Subject: [PATCH 29/30] dm: core: Provide ofnode_name_eq_unit() to accept a unit address When a unit-address is provided, use it to match against the node name. Since this increases code size, put it into a separate function. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 23 +++++++++++++++++++++++ include/dm/ofnode.h | 14 ++++++++++++++ test/dm/core.c | 18 ++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 83c60069cb3..373c7840eef 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -309,6 +309,29 @@ bool ofnode_name_eq(ofnode node, const char *name) return (strlen(name) == len) && !strncmp(node_name, name, len); } +bool ofnode_name_eq_unit(ofnode node, const char *name) +{ + const char *node_name, *p; + int len; + + assert(ofnode_valid(node)); + + node_name = ofnode_get_name(node); + + /* check the whole name */ + if (!strcmp(node_name, name)) + return true; + + /* if @name has no unit address, try the node name without it */ + len = strlen(name); + p = strchr(node_name, '@'); + if (p && !strchr(name, '@') && len == p - node_name && + !strncmp(node_name, name, len)) + return true; + + return false; +} + int ofnode_read_u8(ofnode node, const char *propname, u8 *outp) { const u8 *cell; diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 2f3da384eba..8e4c3574df8 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -394,6 +394,20 @@ void oftree_dispose(oftree tree); */ bool ofnode_name_eq(ofnode node, const char *name); +/** + * ofnode_name_eq_unit() - Check a node name ignoring its unit address + * + * This is separate from ofnode_name_eq() to avoid code-size increase for + * boards which don't need this function + * + * @node: valid node to compared, which may have a unit address + * @name: name to compare with the node name. If this contains a unit + * address, it is matched, otherwise the unit address is ignored + * when searching for matches + * Return: true if matches, false if it doesn't match + */ +bool ofnode_name_eq_unit(ofnode node, const char *name); + /** * ofnode_read_u8() - Read a 8-bit integer from a property * diff --git a/test/dm/core.c b/test/dm/core.c index d40916ef588..959b834576f 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -192,6 +192,24 @@ static int dm_test_compare_node_name(struct unit_test_state *uts) } DM_TEST(dm_test_compare_node_name, UTF_SCAN_PDATA); +/* compare node names ignoring the unit address */ +static int dm_test_compare_node_name_unit(struct unit_test_state *uts) +{ + ofnode node; + + node = ofnode_path("/mmio-bus@0"); + ut_assert(ofnode_valid(node)); + ut_assert(ofnode_name_eq_unit(node, "mmio-bus")); + + ut_assert(ofnode_name_eq_unit(node, "mmio-bus@0")); + ut_assert(!ofnode_name_eq_unit(node, "mmio-bus@1")); + ut_assert(!ofnode_name_eq_unit(node, "mmio-bu")); + ut_assert(!ofnode_name_eq_unit(node, "mmio-buss@0")); + + return 0; +} +DM_TEST(dm_test_compare_node_name_unit, UTF_SCAN_PDATA); + /* Test that binding with uclass plat setting occurs correctly */ static int dm_test_autobind_uclass_pdata_valid(struct unit_test_state *uts) { From 8985ff56b16dc6c04da2c96d48e7f6f54d04e3ff Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 10 Jan 2025 17:00:29 -0700 Subject: [PATCH 30/30] dm: core: Provide ofnode_find_subnode_unit() The ofnode_find_subnode() function currently processes things two different ways, so the treatment of unit addresses differs depending on whether OF_LIVE is enabled or not. Add a new version which uses the ofnode API and add a test to check that unit addresses can be matched correctly. Leave the old function in place for the !OF_LIVE case, to avoid a code-size increase, e.g. on firefly-rk3288 Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 29 ++++++++++++++++++++++------- include/dm/ofnode.h | 12 ++++++++++++ test/dm/ofnode.c | 19 +++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 373c7840eef..26e014d5c53 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -599,14 +599,9 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) log_debug("%s: %s: ", __func__, subnode_name); if (ofnode_is_np(node)) { - struct device_node *np = ofnode_to_np(node); - - for (np = np->child; np; np = np->sibling) { - if (!strcmp(subnode_name, np->name)) - break; - } - subnode = np_to_ofnode(np); + subnode = ofnode_find_subnode_unit(node, subnode_name); } else { + /* special case to avoid code-size increase */ int ooffset = fdt_subnode_offset(ofnode_to_fdt(node), ofnode_to_offset(node), subnode_name); subnode = noffset_to_ofnode(node, ooffset); @@ -617,6 +612,26 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) return subnode; } +ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name) +{ + ofnode subnode, found = ofnode_null(); + + assert(ofnode_valid(node)); + log_debug("%s: ", subnode_name); + + ofnode_for_each_subnode(subnode, node) { + if (ofnode_name_eq_unit(subnode, subnode_name)) { + found = subnode; + break; + } + } + + log_debug("%s\n", ofnode_valid(found) ? + ofnode_get_name(found) : ""); + + return found; +} + int ofnode_read_u32_array(ofnode node, const char *propname, u32 *out_values, size_t sz) { diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 8e4c3574df8..120393426db 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -607,6 +607,18 @@ bool ofnode_read_bool(ofnode node, const char *propname); */ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name); +/** + * ofnode_find_subnode_unit() - find a named subnode of a parent node + * + * @node: valid reference to parent node + * @subnode_name: name of subnode to find, including any unit address. If the + * unit address is omitted, any subnode which matches the name (excluding + * any unit address) is returned + * Return: reference to subnode (which can be invalid if there is no such + * subnode) + */ +ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name); + #if CONFIG_IS_ENABLED(DM_INLINE_OFNODE) #include diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index f16b643fa3f..4a23a3ca38c 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1303,6 +1303,25 @@ static int dm_test_ofnode_find_subnode(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_find_subnode, UTF_SCAN_FDT); +/* check ofnode_find_subnode() with unit addresses */ +static int dm_test_ofnode_find_subnode_unit(struct unit_test_state *uts) +{ + ofnode node, subnode; + + node = ofnode_path("/some-bus"); + ut_assert(ofnode_valid(node)); + subnode = ofnode_find_subnode_unit(node, "c-test@5"); + ut_assert(ofnode_valid(subnode)); + ut_asserteq_str("c-test@5", ofnode_get_name(subnode)); + + subnode = ofnode_find_subnode_unit(node, "c-test"); + ut_assert(ofnode_valid(subnode)); + ut_asserteq_str("c-test@5", ofnode_get_name(subnode)); + + return 0; +} +DM_TEST(dm_test_ofnode_find_subnode_unit, UTF_SCAN_FDT); + /* test ofnode_find_subnode() on the 'other' tree */ static int dm_test_ofnode_find_subnode_ot(struct unit_test_state *uts) {