From de44d80e99156a14ac20ee2df83ad3decf250ac1 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 14 Jan 2022 23:29:09 +0100 Subject: [PATCH 01/14] configs: disable UEFI for Colibri VF610 The size of the board file is limited to 520192 bytes. This conflicts with the size requirement for the UEFI code. Signed-off-by: Heinrich Schuchardt Acked-by: Marcel Ziswiler --- configs/colibri_vf_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig index 3d15f22b17a..8cf8a31beb0 100644 --- a/configs/colibri_vf_defconfig +++ b/configs/colibri_vf_defconfig @@ -105,4 +105,4 @@ CONFIG_VIDEO_FSL_DCU_FB=y CONFIG_SPLASH_SCREEN_ALIGN=y CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_FDT_FIXUP_PARTITIONS=y -# CONFIG_EFI_UNICODE_CAPITALIZATION is not set +# CONFIG_EFI_LOADER is not set From 8efefcec00240c982ff4f4c7437f0f89829a5ab6 Mon Sep 17 00:00:00 2001 From: Sunil V L Date: Fri, 28 Jan 2022 20:48:45 +0530 Subject: [PATCH 02/14] efi_selftest: unit test for RISCV_EFI_BOOT_PROTOCOL Add a test for the RISCV_EFI_BOOT_PROTOCOL. Signed-off-by: Sunil V L --- lib/efi_selftest/Makefile | 1 + lib/efi_selftest/efi_selftest_riscv.c | 119 ++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_riscv.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 9ff6e1760c6..0b05f8a5911 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_selftest_rng.o obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_selftest_tcg2.o +obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_selftest_riscv.o ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) obj-y += efi_selftest_fdt.o diff --git a/lib/efi_selftest/efi_selftest_riscv.c b/lib/efi_selftest/efi_selftest_riscv.c new file mode 100644 index 00000000000..9d2182e61f7 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_riscv.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_riscv + * + * Copyright (c) 2022 Ventana Micro Systems Inc + * + * Test the RISCV_EFI_BOOT_PROTOCOL. + * + * The following services are tested: + * get_boot_hartid + */ + +#include +#include +#include + +static const struct efi_system_table *systemtab; +static const struct efi_boot_services *boottime; +static const char *fdt; +static const efi_guid_t riscv_efi_boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID; +static const efi_guid_t fdt_guid = EFI_FDT_GUID; + +/** + * efi_st_get_config_table() - get configuration table + * + * @guid: GUID of the configuration table + * Return: pointer to configuration table or NULL + */ +static void *efi_st_get_config_table(const efi_guid_t *guid) +{ + size_t i; + + for (i = 0; i < systab.nr_tables; i++) { + if (!guidcmp(guid, &systemtab->tables[i].guid)) + return systemtab->tables[i].table; + } + return NULL; +} + +/* + * Setup unit test. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + systemtab = systable; + boottime = systable->boottime; + + fdt = efi_st_get_config_table(&fdt_guid); + + if (!fdt) { + efi_st_error("Missing device tree\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + efi_status_t ret; + struct riscv_efi_boot_protocol *prot; + efi_uintn_t efi_hartid, fdt_hartid; + int chosen_node, len; + const fdt32_t *prop; + + /* Get riscv boot protocol */ + ret = boottime->locate_protocol(&riscv_efi_boot_protocol_guid, NULL, + (void **)&prot); + if (ret != EFI_SUCCESS) { + efi_st_error("RISC-V Boot Protocol not available\n"); + return EFI_ST_FAILURE; + } + + /* Get Boot Hart ID from EFI protocol */ + ret = prot->get_boot_hartid(prot, &efi_hartid); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not retrieve boot hart ID\n"); + return EFI_ST_FAILURE; + } + + /* Get Boot Hart ID from FDT */ + chosen_node = fdt_path_offset(fdt, "/chosen"); + if (chosen_node < 0) { + efi_st_error("/chosen node not found\n"); + return EFI_ST_FAILURE; + } + + prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len); + if (!prop || len != sizeof(u32)) { + efi_st_error("boot-hartid not found\n"); + return EFI_ST_FAILURE; + } + + fdt_hartid = fdt32_to_cpu(*prop); + + /* Boot Hart ID should be same */ + if (efi_hartid != fdt_hartid) { + efi_st_error("boot-hartid is not same in EFI and FDT\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(riscv) = { + .name = "riscv", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, +}; From b9b4cecf9bd5208269bd706965be8ceb215cdcaf Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 5 Feb 2022 08:45:55 +0100 Subject: [PATCH 03/14] efi_selftest: merge FDT and RISC-V tests The test for the RISCV_EFI_BOOT_PROTOCOL retrieves the boot hart id via the protocol and compares it to the value of the boot hart id in the device tree. The boot hart id is already retrieved from the device tree in the FDT test. Merge the two tests to avoid code duplication. Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/Makefile | 1 - lib/efi_selftest/efi_selftest_fdt.c | 72 ++++++++++++---- lib/efi_selftest/efi_selftest_riscv.c | 119 -------------------------- 3 files changed, 57 insertions(+), 135 deletions(-) delete mode 100644 lib/efi_selftest/efi_selftest_riscv.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 0b05f8a5911..9ff6e1760c6 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_selftest_rng.o obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_selftest_tcg2.o -obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_selftest_riscv.o ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) obj-y += efi_selftest_fdt.o diff --git a/lib/efi_selftest/efi_selftest_fdt.c b/lib/efi_selftest/efi_selftest_fdt.c index f4a7fcb426e..114ac58bf5c 100644 --- a/lib/efi_selftest/efi_selftest_fdt.c +++ b/lib/efi_selftest/efi_selftest_fdt.c @@ -1,15 +1,14 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * efi_selftest_pos + * efi_selftest_fdt * * Copyright (c) 2018 Heinrich Schuchardt + * Copyright (c) 2022 Ventana Micro Systems Inc * - * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. - * - * The following services are tested: - * OutputString, TestString, SetAttribute. + * Check the device tree, test the RISCV_EFI_BOOT_PROTOCOL. */ +#include #include #include @@ -22,6 +21,8 @@ static const char *fdt; static const efi_guid_t fdt_guid = EFI_FDT_GUID; static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; +static const efi_guid_t riscv_efi_boot_protocol_guid = + RISCV_EFI_BOOT_PROTOCOL_GUID; /** * f2h() - convert FDT value to host endianness. @@ -189,6 +190,29 @@ static int setup(const efi_handle_t img_handle, return EFI_ST_SUCCESS; } +__maybe_unused static efi_status_t get_boot_hartid(efi_uintn_t *efi_hartid) +{ + efi_status_t ret; + struct riscv_efi_boot_protocol *prot; + + /* Get RISC-V boot protocol */ + ret = boottime->locate_protocol(&riscv_efi_boot_protocol_guid, NULL, + (void **)&prot); + if (ret != EFI_SUCCESS) { + efi_st_error("RISC-V Boot Protocol not available\n"); + return EFI_ST_FAILURE; + } + + /* Get boot hart ID from EFI protocol */ + ret = prot->get_boot_hartid(prot, efi_hartid); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not retrieve boot hart ID\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + /* * Execute unit test. * @@ -220,19 +244,37 @@ static int execute(void) return EFI_ST_FAILURE; } } - str = get_property(u"boot-hartid", u"chosen"); if (IS_ENABLED(CONFIG_RISCV)) { - if (str) { - efi_st_printf("boot-hartid: %u\n", - f2h(*(fdt32_t *)str)); - ret = boottime->free_pool(str); - if (ret != EFI_SUCCESS) { - efi_st_error("FreePool failed\n"); + u32 fdt_hartid; + + str = get_property(u"boot-hartid", u"chosen"); + if (!str) { + efi_st_error("boot-hartid missing in devicetree\n"); + return EFI_ST_FAILURE; + } + fdt_hartid = f2h(*(fdt32_t *)str); + efi_st_printf("boot-hartid: %u\n", fdt_hartid); + + ret = boottime->free_pool(str); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + + if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) { + efi_uintn_t efi_hartid; + int r; + + r = get_boot_hartid(&efi_hartid); + if (r != EFI_ST_SUCCESS) + return r; + /* Boot hart ID should be same */ + if (efi_hartid != fdt_hartid) { + efi_st_error("boot-hartid differs: prot 0x%p, DT 0x%.8x\n", + (void *)(uintptr_t)efi_hartid, + fdt_hartid); return EFI_ST_FAILURE; } - } else { - efi_st_error("boot-hartid not found\n"); - return EFI_ST_FAILURE; } } diff --git a/lib/efi_selftest/efi_selftest_riscv.c b/lib/efi_selftest/efi_selftest_riscv.c deleted file mode 100644 index 9d2182e61f7..00000000000 --- a/lib/efi_selftest/efi_selftest_riscv.c +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * efi_selftest_riscv - * - * Copyright (c) 2022 Ventana Micro Systems Inc - * - * Test the RISCV_EFI_BOOT_PROTOCOL. - * - * The following services are tested: - * get_boot_hartid - */ - -#include -#include -#include - -static const struct efi_system_table *systemtab; -static const struct efi_boot_services *boottime; -static const char *fdt; -static const efi_guid_t riscv_efi_boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID; -static const efi_guid_t fdt_guid = EFI_FDT_GUID; - -/** - * efi_st_get_config_table() - get configuration table - * - * @guid: GUID of the configuration table - * Return: pointer to configuration table or NULL - */ -static void *efi_st_get_config_table(const efi_guid_t *guid) -{ - size_t i; - - for (i = 0; i < systab.nr_tables; i++) { - if (!guidcmp(guid, &systemtab->tables[i].guid)) - return systemtab->tables[i].table; - } - return NULL; -} - -/* - * Setup unit test. - * - * @handle: handle of the loaded image - * @systable: system table - * @return: EFI_ST_SUCCESS for success - */ -static int setup(const efi_handle_t img_handle, - const struct efi_system_table *systable) -{ - systemtab = systable; - boottime = systable->boottime; - - fdt = efi_st_get_config_table(&fdt_guid); - - if (!fdt) { - efi_st_error("Missing device tree\n"); - return EFI_ST_FAILURE; - } - return EFI_ST_SUCCESS; -} - -/* - * Execute unit test. - * - * @return: EFI_ST_SUCCESS for success - */ -static int execute(void) -{ - efi_status_t ret; - struct riscv_efi_boot_protocol *prot; - efi_uintn_t efi_hartid, fdt_hartid; - int chosen_node, len; - const fdt32_t *prop; - - /* Get riscv boot protocol */ - ret = boottime->locate_protocol(&riscv_efi_boot_protocol_guid, NULL, - (void **)&prot); - if (ret != EFI_SUCCESS) { - efi_st_error("RISC-V Boot Protocol not available\n"); - return EFI_ST_FAILURE; - } - - /* Get Boot Hart ID from EFI protocol */ - ret = prot->get_boot_hartid(prot, &efi_hartid); - if (ret != EFI_SUCCESS) { - efi_st_error("Could not retrieve boot hart ID\n"); - return EFI_ST_FAILURE; - } - - /* Get Boot Hart ID from FDT */ - chosen_node = fdt_path_offset(fdt, "/chosen"); - if (chosen_node < 0) { - efi_st_error("/chosen node not found\n"); - return EFI_ST_FAILURE; - } - - prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len); - if (!prop || len != sizeof(u32)) { - efi_st_error("boot-hartid not found\n"); - return EFI_ST_FAILURE; - } - - fdt_hartid = fdt32_to_cpu(*prop); - - /* Boot Hart ID should be same */ - if (efi_hartid != fdt_hartid) { - efi_st_error("boot-hartid is not same in EFI and FDT\n"); - return EFI_ST_FAILURE; - } - - return EFI_ST_SUCCESS; -} - -EFI_UNIT_TEST(riscv) = { - .name = "riscv", - .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, - .setup = setup, - .execute = execute, -}; From fe14f880500cd842eadd581b7261538bb9646b7f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 29 Jan 2022 16:43:20 +0100 Subject: [PATCH 04/14] lib: fix snprintf() for UTF-16 strings snprintf() must return the required buffer length. Signed-off-by: Heinrich Schuchardt --- lib/vsprintf.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 69b2f6a1adc..fe06aa2d711 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -285,15 +285,25 @@ static __maybe_unused char *string16(char *buf, char *end, u16 *s, if (!(flags & LEFT)) for (; len < field_width; --field_width) ADDCH(buf, ' '); - for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) { + if (buf < end) + *buf = 0; + for (i = 0; i < len; ++i) { + int slen = utf16_utf8_strnlen(str, 1); s32 s = utf16_get(&str); if (s < 0) s = '?'; - utf8_put(s, &buf); + if (buf + slen < end) { + utf8_put(s, &buf); + if (buf < end) + *buf = 0; + } else { + buf += slen; + } } for (; len < field_width; --field_width) ADDCH(buf, ' '); + return buf; } From c672dd770ee0d9874086543c20a9088124514051 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 29 Jan 2022 18:28:08 +0100 Subject: [PATCH 05/14] test: test UTF-16 truncation in snprintf() Check that snprintf() returns the correct required buffer length and prints the correct string for UTF-16 strings. Signed-off-by: Heinrich Schuchardt --- test/unicode_ut.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/unicode_ut.c b/test/unicode_ut.c index f821e5a6be8..f2f63d5367b 100644 --- a/test/unicode_ut.c +++ b/test/unicode_ut.c @@ -97,6 +97,7 @@ UNICODE_TEST(unicode_test_u16_strcpy); static int unicode_test_string16(struct unit_test_state *uts) { char buf[20]; + int ret; /* Test length and precision */ memset(buf, 0xff, sizeof(buf)); @@ -130,6 +131,36 @@ static int unicode_test_string16(struct unit_test_state *uts) sprintf(buf, "%ls", i3); ut_asserteq_str("i3?", buf); + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 4, "%ls", c1); + ut_asserteq(6, ret); + ut_asserteq_str("U-B", buf); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 6, "%ls", c2); + ut_asserteq_str("kafb", buf); + ut_asserteq(9, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 7, "%ls", c2); + ut_asserteq_str("kafb\xC3\xA1", buf); + ut_asserteq(9, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 8, "%ls", c3); + ut_asserteq_str("\xE6\xBD\x9C\xE6\xB0\xB4", buf); + ut_asserteq(9, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 11, "%ls", c4); + ut_asserteq_str("\xF0\x90\x92\x8D\xF0\x90\x92\x96", buf); + ut_asserteq(12, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 4, "%ls", c4); + ut_asserteq_str("", buf); + ut_asserteq(12, ret); + return 0; } UNICODE_TEST(unicode_test_string16); From 344f26a7664f0a3f1a4b302e08a408171bdc3ece Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 29 Jan 2022 19:01:07 +0100 Subject: [PATCH 06/14] efi_loader: fix device path to text protocol The printing of a file path node must properly handle: * odd length of the device path node * UTF-16 character only partially contained in device path node * buffer overflow due to very long file path Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_device_path_to_text.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index d8a83c88493..97b3d3e815e 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -8,6 +8,7 @@ #include #include #include +#include #define MAC_OUTPUT_LEN 22 #define UNKNOWN_OUTPUT_LEN 23 @@ -292,10 +293,18 @@ static char *dp_media(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_FILE_PATH: { struct efi_device_path_file_path *fp = (struct efi_device_path_file_path *)dp; - int slen = (dp->length - sizeof(*dp)) / 2; - if (slen > MAX_NODE_LEN - 2) - slen = MAX_NODE_LEN - 2; - s += sprintf(s, "%-.*ls", slen, fp->str); + u16 *buffer; + int slen = dp->length - sizeof(*dp); + + /* two bytes for \0, extra byte if dp->length is odd */ + buffer = calloc(1, slen + 3); + if (!buffer) { + log_err("Out of memory\n"); + return s; + } + memcpy(buffer, fp->str, dp->length - sizeof(*dp)); + s += snprintf(s, MAX_NODE_LEN - 1, "%ls", buffer); + free(buffer); break; } default: From e9df54968f53600a709575f001474695c312141a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 3 Feb 2022 22:21:51 +0100 Subject: [PATCH 07/14] efi_loader: use %zu not %zd to print efi_uintn_t efi_uintnt_t is an unsigned type. We should avoid showing negative numbers. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1ea04de9065..82128ac1d5c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -467,7 +467,7 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type, { efi_status_t r; - EFI_ENTRY("%d, %zd, %p", pool_type, size, buffer); + EFI_ENTRY("%d, %zu, %p", pool_type, size, buffer); r = efi_allocate_pool(pool_type, size, buffer); return EFI_EXIT(r); } @@ -914,7 +914,7 @@ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events, { int i; - EFI_ENTRY("%zd, %p, %p", num_events, event, index); + EFI_ENTRY("%zu, %p, %p", num_events, event, index); /* Check parameters */ if (!num_events || !event) @@ -2028,7 +2028,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_status_t ret; void *dest_buffer; - EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image, + EFI_ENTRY("%d, %p, %pD, %p, %zu, %p", boot_policy, parent_image, file_path, source_buffer, source_size, image_handle); if (!image_handle || (!source_buffer && !file_path) || From b1193fa9576c988ebbe04334f10bf38279cc72ec Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 3 Feb 2022 20:13:17 +0100 Subject: [PATCH 08/14] efi_loader: use %zu to print efi_uintn_t in FMP driver For printing an unsigned value we should use %u and not %d. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_firmware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 519a47267ca..a5ff32f121f 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -302,7 +302,7 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( efi_status_t (*progress)(efi_uintn_t completion), u16 **abort_reason) { - EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image, + EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image, image_size, vendor_code, progress, abort_reason); if (!image || image_index != 1) @@ -417,7 +417,7 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( efi_status_t status; efi_uintn_t capsule_payload_size; - EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image, + EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image, image_size, vendor_code, progress, abort_reason); if (!image) From 915623c0d3f504dce8a2310c1ddf5dcc638e5d93 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 4 Feb 2022 16:36:49 +0100 Subject: [PATCH 09/14] efi_loader: fix text output for Uart() DP nodes The UEFI specification concerning Uart() device path nodes has been clarified: Parity and stop bits can either both use keywords or both use numbers but numbers and keywords should not be mixed. Let's go for keywords as this is what EDK II does. For illegal values fall back to numbers. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_device_path_to_text.c | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 97b3d3e815e..4d73954ef89 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -122,16 +122,26 @@ static char *dp_msging(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_MSG_UART: { struct efi_device_path_uart *uart = (struct efi_device_path_uart *)dp; - s += sprintf(s, "Uart(%lld,%d,%d,", uart->baud_rate, - uart->data_bits, uart->parity); - switch (uart->stop_bits) { - case 2: - s += sprintf(s, "1.5)"); - break; - default: + const char parity_str[6] = {'D', 'N', 'E', 'O', 'M', 'S'}; + const char *stop_bits_str[4] = { "D", "1", "1.5", "2" }; + + s += sprintf(s, "Uart(%lld,%d,", uart->baud_rate, + uart->data_bits); + + /* + * Parity and stop bits can either both use keywords or both use + * numbers but numbers and keywords should not be mixed. Let's + * go for keywords as this is what EDK II does. For illegal + * values fall back to numbers. + */ + if (uart->parity < 6) + s += sprintf(s, "%c,", parity_str[uart->parity]); + else + s += sprintf(s, "%d,", uart->parity); + if (uart->stop_bits < 4) + s += sprintf(s, "%s)", stop_bits_str[uart->stop_bits]); + else s += sprintf(s, "%d)", uart->stop_bits); - break; - } break; } case DEVICE_PATH_SUB_TYPE_MSG_USB: { From 3c95b323c7527dd2b312b061a82a4b65bb3feff2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 4 Feb 2022 20:47:09 +0100 Subject: [PATCH 10/14] efi_loader: add handle for UART When loading an EFI binary via the UART we assign a UART device path to it. But we lack a handle with that device path. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 1 + lib/efi_loader/efi_console.c | 46 +++++++++++++++++------------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index f4ae84dc89b..e390d323a98 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -769,6 +769,7 @@ const struct efi_device_path *efi_dp_last_node( efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, struct efi_device_path **device_path, struct efi_device_path **file_path); +struct efi_device_path *efi_dp_from_uart(void); efi_status_t efi_dp_from_name(const char *dev, const char *devnr, const char *path, struct efi_device_path **device, diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 3b012e1a669..ba68a150172 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -25,6 +25,8 @@ struct cout_mode { int present; }; +__maybe_unused static struct efi_object uart_obj; + static struct cout_mode efi_cout_modes[] = { /* EFI Mode 0 is 80x25 and always present */ { @@ -1258,37 +1260,33 @@ static void EFIAPI efi_key_notify(struct efi_event *event, void *context) efi_status_t efi_console_register(void) { efi_status_t r; - efi_handle_t console_output_handle; - efi_handle_t console_input_handle; + struct efi_device_path *dp; /* Set up mode information */ query_console_size(); - /* Create handles */ - r = efi_create_handle(&console_output_handle); - if (r != EFI_SUCCESS) - goto out_of_memory; + /* Install protocols on root node */ + r = EFI_CALL(efi_install_multiple_protocol_interfaces + (&efi_root, + &efi_guid_text_output_protocol, &efi_con_out, + &efi_guid_text_input_protocol, &efi_con_in, + &efi_guid_text_input_ex_protocol, &efi_con_in_ex, + NULL)); - r = efi_add_protocol(console_output_handle, - &efi_guid_text_output_protocol, &efi_con_out); - if (r != EFI_SUCCESS) - goto out_of_memory; - systab.con_out_handle = console_output_handle; - systab.stderr_handle = console_output_handle; + /* Create console node and install device path protocols */ + if (CONFIG_IS_ENABLED(DM_SERIAL)) { + dp = efi_dp_from_uart(); + if (!dp) + goto out_of_memory; - r = efi_create_handle(&console_input_handle); - if (r != EFI_SUCCESS) - goto out_of_memory; + /* Hook UART up to the device list */ + efi_add_handle(&uart_obj); - r = efi_add_protocol(console_input_handle, - &efi_guid_text_input_protocol, &efi_con_in); - if (r != EFI_SUCCESS) - goto out_of_memory; - systab.con_in_handle = console_input_handle; - r = efi_add_protocol(console_input_handle, - &efi_guid_text_input_ex_protocol, &efi_con_in_ex); - if (r != EFI_SUCCESS) - goto out_of_memory; + /* Install device path */ + r = efi_add_protocol(&uart_obj, &efi_guid_device_path, dp); + if (r != EFI_SUCCESS) + goto out_of_memory; + } /* Create console events */ r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify, From d837cb1e3b6bf6a3d77f058b90ea937935fc2c8f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 29 Jan 2022 14:58:37 -0700 Subject: [PATCH 11/14] efi: Add debugging to efi_set_bootdev() The operation of this function can be confusing. Add some debugging so we can see what it is doing and when it is called. Also drop the preprocessor usage. Signed-off-by: Simon Glass Reviewed-by: heinrich Schuchardt --- cmd/bootefi.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3a8b2b60618..94d18ca73fa 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -65,6 +65,9 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, struct efi_device_path *device, *image; efi_status_t ret; + log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev, + devnr, path, buffer, buffer_size); + /* Forget overwritten image */ if (buffer + buffer_size >= image_addr && image_addr + image_size >= buffer) @@ -72,18 +75,19 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, /* Remember only PE-COFF and FIT images */ if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) { -#ifdef CONFIG_FIT - if (fit_check_format(buffer, IMAGE_SIZE_INVAL)) + if (IS_ENABLED(CONFIG_FIT) && + !fit_check_format(buffer, IMAGE_SIZE_INVAL)) { + /* + * FIT images of type EFI_OS are started via command + * bootm. We should not use their boot device with the + * bootefi command. + */ + buffer = 0; + buffer_size = 0; + } else { + log_debug("- not remembering image\n"); return; - /* - * FIT images of type EFI_OS are started via command bootm. - * We should not use their boot device with the bootefi command. - */ - buffer = 0; - buffer_size = 0; -#else - return; -#endif + } } /* efi_set_bootdev() is typically called repeatedly, recover memory */ @@ -103,7 +107,11 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, efi_free_pool(image_tmp); } bootefi_image_path = image; + log_debug("- recorded device %ls\n", efi_dp_str(device)); + if (image) + log_debug("- and image %ls\n", efi_dp_str(image)); } else { + log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); efi_clear_bootdev(); } } @@ -451,6 +459,7 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) u16 *load_options; if (!bootefi_device_path || !bootefi_image_path) { + log_debug("Not loaded from disk\n"); /* * Special case for efi payload not loaded from disk, * such as 'bootefi hello' or for example payload @@ -476,6 +485,7 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) file_path = efi_dp_append(bootefi_device_path, bootefi_image_path); msg_path = bootefi_image_path; + log_debug("Loaded from disk\n"); } log_info("Booting %pD\n", msg_path); From 377d39d178570a3510a34aac61f008b43cca783f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 29 Jan 2022 14:58:38 -0700 Subject: [PATCH 12/14] efi: Use device_get_uclass_id() where appropriate Use this function rather than following the pointers, since it is there for this purpose. Add the uclass name to the debug call at the end of dp_fill() since it is quite useful. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_device_path.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index c61f4859330..75ab4de7070 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -494,7 +494,7 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) if (!dev || !dev->driver) return sizeof(ROOT); - switch (dev->driver->id) { + switch (device_get_uclass_id(dev)) { case UCLASS_ROOT: case UCLASS_SIMPLE_BUS: /* stop traversing parents at this point: */ @@ -579,7 +579,7 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) if (!dev || !dev->driver) return buf; - switch (dev->driver->id) { + switch (device_get_uclass_id(dev)) { case UCLASS_ROOT: case UCLASS_SIMPLE_BUS: { /* stop traversing parents at this point: */ @@ -759,9 +759,9 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &udp[1]; } default: - debug("%s(%u) %s: unhandled device class: %s (%u)\n", - __FILE__, __LINE__, __func__, - dev->name, dev->driver->id); + /* If the uclass driver is missing, this will show NULL */ + log_debug("unhandled device class: %s (%s)\n", dev->name, + dev_get_uclass_name(dev)); return dp_fill(buf, dev->parent); } } From e2bceb03312a8abfb4f423ac349ab5861feb3548 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 29 Jan 2022 14:58:39 -0700 Subject: [PATCH 13/14] efi: Drop unnecessary calls to blk_find_device() When we have the block descriptor we can simply access the device. Drop the unnecessary function call. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_device_path.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 75ab4de7070..dc787b4d3dd 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -769,13 +769,8 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) static unsigned dp_part_size(struct blk_desc *desc, int part) { unsigned dpsize; - struct udevice *dev; - int ret; + struct udevice *dev = desc->bdev; - ret = blk_find_device(desc->if_type, desc->devnum, &dev); - - if (ret) - dev = desc->bdev->parent; dpsize = dp_size(dev); if (part == 0) /* the actual disk, not a partition */ @@ -866,13 +861,8 @@ static void *dp_part_node(void *buf, struct blk_desc *desc, int part) */ static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) { - struct udevice *dev; - int ret; + struct udevice *dev = desc->bdev; - ret = blk_find_device(desc->if_type, desc->devnum, &dev); - - if (ret) - dev = desc->bdev->parent; buf = dp_fill(buf, dev); if (part == 0) /* the actual disk, not a partition */ From 6bbe12f61c4f7208b428cc038170dc286c872a91 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 5 Feb 2022 20:10:03 +0100 Subject: [PATCH 14/14] tools: mkeficapsule: dont use malloc.h malloc() functions are declared via stdlib.h. Including malloc.h can lead to build errors e.g. on OS-X. Signed-off-by: Heinrich Schuchardt --- tools/mkeficapsule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 243fd6e4837..d6e3725e5f6 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -5,7 +5,6 @@ */ #include -#include #include #include #include