diff options
-rw-r--r-- | cmd/bootefi.c | 32 | ||||
-rw-r--r-- | configs/colibri_vf_defconfig | 2 | ||||
-rw-r--r-- | include/efi_loader.h | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 6 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 52 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 24 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path_to_text.c | 45 | ||||
-rw-r--r-- | lib/efi_loader/efi_firmware.c | 4 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_fdt.c | 72 | ||||
-rw-r--r-- | lib/vsprintf.c | 14 | ||||
-rw-r--r-- | test/unicode_ut.c | 31 | ||||
-rw-r--r-- | tools/mkeficapsule.c | 1 |
12 files changed, 192 insertions, 92 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3a8b2b6061..94d18ca73f 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); diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig index 3d15f22b17..8cf8a31beb 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 diff --git a/include/efi_loader.h b/include/efi_loader.h index f4ae84dc89..e390d323a9 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_boottime.c b/lib/efi_loader/efi_boottime.c index 1ea04de906..82128ac1d5 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) || diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 3b012e1a66..ba68a15017 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; - - 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; - - r = efi_create_handle(&console_input_handle); - if (r != EFI_SUCCESS) - goto out_of_memory; - - 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 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)); + + /* 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; + + /* Hook UART up to the device list */ + efi_add_handle(&uart_obj); + + /* 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, diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index c61f485933..dc787b4d3d 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); } } @@ -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; - - ret = blk_find_device(desc->if_type, desc->devnum, &dev); + struct udevice *dev = desc->bdev; - if (ret) - dev = desc->bdev->parent; buf = dp_fill(buf, dev); if (part == 0) /* the actual disk, not a partition */ diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index d8a83c8849..4d73954ef8 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 <common.h> #include <blk.h> #include <efi_loader.h> +#include <malloc.h> #define MAC_OUTPUT_LEN 22 #define UNKNOWN_OUTPUT_LEN 23 @@ -121,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: { @@ -292,10 +303,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: diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 519a47267c..a5ff32f121 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) diff --git a/lib/efi_selftest/efi_selftest_fdt.c b/lib/efi_selftest/efi_selftest_fdt.c index f4a7fcb426..114ac58bf5 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 <xypron.glpk@gmx.de> + * 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 <efi_riscv.h> #include <efi_selftest.h> #include <linux/libfdt.h> @@ -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/vsprintf.c b/lib/vsprintf.c index 69b2f6a1ad..fe06aa2d71 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; } diff --git a/test/unicode_ut.c b/test/unicode_ut.c index f821e5a6be..f2f63d5367 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); diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 243fd6e483..d6e3725e5f 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -5,7 +5,6 @@ */ #include <getopt.h> -#include <malloc.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> |