From 9f00d38ce7600a162e37156ee6d5a050857a3a9f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 17 Jan 2025 01:09:51 +0100 Subject: efi_loader: correct logging StartImage() When logging running an image, e.g. `bootefi hello` the indent is not correctly reset. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 12 ++++++++++++ lib/efi_loader/efi_boottime.c | 7 +++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 0d858c1e12e..5bf271afaad 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -245,6 +245,18 @@ const char *__efi_nesting_dec(void); _r; \ }) +/** + * define EFI_RETURN() - return from EFI_CALL in efi_start_image() + * + * @ret: status code + */ +#define EFI_RETURN(ret) ({ \ + typeof(ret) _r = ret; \ + assert(__efi_entry_check()); \ + debug("%sEFI: %lu returned by started image", __efi_nesting_dec(), \ + (unsigned long)((uintptr_t)_r & ~EFI_ERROR_MASK)); \ +}) + /* * Call void UEFI function from u-boot: */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 723a9b58691..db544382137 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -3256,11 +3256,10 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, * To get ready to call EFI_EXIT below we have to execute the * missed out steps of EFI_CALL. */ - assert(__efi_entry_check()); - EFI_PRINT("%lu returned by started image\n", - (unsigned long)((uintptr_t)exit_status & - ~EFI_ERROR_MASK)); + EFI_RETURN(exit_status); + current_image = parent_image; + return EFI_EXIT(exit_status); } -- cgit v1.2.3 From 1daacb92757e0c2e7b5155613ad9b1334545eb86 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 17 Jan 2025 01:09:52 +0100 Subject: log: make log_has_file() static Function log_has_file() is not used externally. Make it static. Rename the function to log_has_member() as we can reuse for filtering other strings. Signed-off-by: Heinrich Schuchardt --- common/log.c | 20 ++++++++++++++------ include/log.h | 12 ------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/common/log.c b/common/log.c index c9fe35230d6..b2b5f3c81ba 100644 --- a/common/log.c +++ b/common/log.c @@ -130,17 +130,25 @@ bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat) return false; } -bool log_has_file(const char *file_list, const char *file) +/** + * log_has_member() - check if a string is in a comma separated list + * + * @list: Comma separated list of strings + * @member: String to find + * + * Return: ``true`` if @member is in @list, else ``false`` + */ +static bool log_has_member(const char *list, const char *member) { - int file_len = strlen(file); + int member_len = strlen(member); const char *s, *p; int substr_len; - for (s = file_list; *s; s = p + (*p != '\0')) { + for (s = list; *s; s = p + (*p != '\0')) { p = strchrnul(s, ','); substr_len = p - s; - if (file_len >= substr_len && - !strncmp(file + file_len - substr_len, s, substr_len)) + if (member_len >= substr_len && + !strncmp(member + member_len - substr_len, s, substr_len)) return true; } @@ -181,7 +189,7 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec) continue; if (filt->file_list && - !log_has_file(filt->file_list, rec->file)) + !log_has_member(filt->file_list, rec->file)) continue; if (filt->flags & LOGFF_DENY) diff --git a/include/log.h b/include/log.h index 4f6d6a2c2cf..3f9023ae0d2 100644 --- a/include/log.h +++ b/include/log.h @@ -571,18 +571,6 @@ struct log_device *log_device_find_by_name(const char *drv_name); */ bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat); -/** - * log_has_file() - check if a file is with a list - * - * @file_list: List of files to check, separated by comma - * @file: File to check for. This string is matched against the end of each - * file in the list, i.e. ignoring any preceding path. The list is - * intended to consist of relative pathnames, e.g. common/main.c,cmd/log.c - * - * Return: ``true`` if @file is in @file_list, else ``false`` - */ -bool log_has_file(const char *file_list, const char *file); - /* Log format flags (bit numbers) for gd->log_fmt. See log_fmt_chars */ enum log_fmt { LOGF_CAT = 0, -- cgit v1.2.3 From cb43e3e427769f5dcbb1ffda155198f38fb7375c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 17 Jan 2025 01:09:53 +0100 Subject: log: enable filtering on functions Up to now we could only use log level, category, and file for filtering. Allow filtering on a list of functions. Signed-off-by: Heinrich Schuchardt --- cmd/log.c | 42 ++++++++++++++++++++++-------------------- common/log.c | 13 ++++++++++++- include/log.h | 7 +++++-- test/log/log_filter.c | 1 - test/log/log_test.c | 10 +++++----- 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/cmd/log.c b/cmd/log.c index 519ec76f3b5..64add6d8b5a 100644 --- a/cmd/log.c +++ b/cmd/log.c @@ -115,30 +115,27 @@ static int do_log_filter_list(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_FAILURE; } - /* <3> < 6 > <2+1 + 7 > < 16 > < unbounded... */ - printf("num policy level categories files\n"); list_for_each_entry(filt, &ldev->filter_head, sibling_node) { - printf("%3d %6.6s %s %-7.7s ", filt->filter_num, - filt->flags & LOGFF_DENY ? "deny" : "allow", + printf("%-3d: %s %s %s\n", filt->filter_num, + filt->flags & LOGFF_DENY ? "DENY" : "ALLOW", filt->flags & LOGFF_LEVEL_MIN ? ">=" : "<=", log_get_level_name(filt->level)); if (filt->flags & LOGFF_HAS_CAT) { - int i; - - if (filt->cat_list[0] != LOGC_END) - printf("%16.16s %s\n", - log_get_cat_name(filt->cat_list[0]), - filt->file_list ? filt->file_list : ""); - - for (i = 1; i < LOGF_MAX_CATEGORIES && - filt->cat_list[i] != LOGC_END; i++) - printf("%21c %16.16s\n", ' ', + printf(" Categories:"); + for (int i = 0; + i < LOGF_MAX_CATEGORIES && + filt->cat_list[i] != LOGC_END; + ++i) { + printf(" %s", log_get_cat_name(filt->cat_list[i])); - } else { - printf("%16c %s\n", ' ', - filt->file_list ? filt->file_list : ""); + } + printf("\n"); } + if (filt->file_list) + printf(" Files: %s\n", filt->file_list); + if (filt->func_list) + printf(" Functions: %s\n", filt->func_list); } return CMD_RET_SUCCESS; @@ -151,6 +148,7 @@ static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc, bool print_num = false; bool type_set = false; char *file_list = NULL; + char *func_list = NULL; const char *drv_name = "console"; int opt, err; int cat_count = 0; @@ -160,7 +158,7 @@ static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc, struct getopt_state gs; getopt_init_state(&gs); - while ((opt = getopt(&gs, argc, argv, "Ac:d:Df:l:L:p")) > 0) { + while ((opt = getopt(&gs, argc, argv, "Ac:d:Df:F:l:L:p")) > 0) { switch (opt) { case 'A': #define do_type() do { \ @@ -199,6 +197,9 @@ static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc, case 'f': file_list = gs.arg; break; + case 'F': + func_list = gs.arg; + break; case 'l': #define do_level() do { \ if (level_set) { \ @@ -229,7 +230,7 @@ static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc, cat_list[cat_count] = LOGC_END; err = log_add_filter_flags(drv_name, cat_count ? cat_list : NULL, level, - file_list, flags); + file_list, func_list, flags); if (err < 0) { printf("Could not add filter (err = %d)\n", err); return CMD_RET_FAILURE; @@ -388,7 +389,8 @@ U_BOOT_LONGHELP(log, "\t-d - Specify the log driver to add the filter to; defaults\n" "\t to console\n" "\t-D - Deny messages matching this filter; mutually exclusive with -A\n" - "\t-f - A comma-separated list of files to match\n" + "\t-f - A comma-separated list of files to match\n" + "\t-F - A comma-separated list of functions to match\n" "\t-l - Match log levels less than or equal to ;\n" "\t mutually-exclusive with -L\n" "\t-L - Match log levels greather than or equal to ;\n" diff --git a/common/log.c b/common/log.c index b2b5f3c81ba..b75e404420b 100644 --- a/common/log.c +++ b/common/log.c @@ -192,6 +192,10 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec) !log_has_member(filt->file_list, rec->file)) continue; + if (filt->func_list && + !log_has_member(filt->func_list, rec->func)) + continue; + if (filt->flags & LOGFF_DENY) return false; else @@ -329,7 +333,7 @@ int _log_buffer(enum log_category_t cat, enum log_level_t level, int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], enum log_level_t level, const char *file_list, - int flags) + const char *func_list, int flags) { struct log_filter *filt; struct log_device *ldev; @@ -364,6 +368,13 @@ int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], goto err; } } + if (func_list) { + filt->func_list = strdup(func_list); + if (!filt->func_list) { + ret = -ENOMEM; + goto err; + } + } filt->filter_num = ldev->next_filter_num++; /* Add deny filters to the beginning of the list */ if (flags & LOGFF_DENY) diff --git a/include/log.h b/include/log.h index 3f9023ae0d2..dd44badc361 100644 --- a/include/log.h +++ b/include/log.h @@ -500,6 +500,7 @@ enum log_filter_flags { * @level: Maximum (or minimum, if %LOGFF_MIN_LEVEL) log level to allow * @file_list: List of files to allow, separated by comma. If NULL then all * files are permitted + * @func_list: Comma separated list of functions or NULL. * @sibling_node: Next filter in the list of filters for this log device */ struct log_filter { @@ -508,6 +509,7 @@ struct log_filter { enum log_category_t cat_list[LOGF_MAX_CATEGORIES]; enum log_level_t level; const char *file_list; + const char *func_list; struct list_head sibling_node; }; @@ -599,13 +601,14 @@ int do_log_test(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); * @level: Maximum (or minimum, if %LOGFF_LEVEL_MIN) log level to allow * @file_list: List of files to allow, separated by comma. If NULL then all * files are permitted + * @func_list: Comma separated list of functions or NULL. * Return: * the sequence number of the new filter (>=0) if the filter was added, or a * -ve value on error */ int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[], enum log_level_t level, const char *file_list, - int flags); + const char *func_list, int flags); /** * log_add_filter() - Add a new filter to a log device @@ -628,7 +631,7 @@ static inline int log_add_filter(const char *drv_name, const char *file_list) { return log_add_filter_flags(drv_name, cat_list, max_level, file_list, - 0); + NULL, 0); } /** diff --git a/test/log/log_filter.c b/test/log/log_filter.c index d36e9d9714e..8622dcf2913 100644 --- a/test/log/log_filter.c +++ b/test/log/log_filter.c @@ -39,7 +39,6 @@ static int log_test_filter(struct unit_test_state *uts) #define create_filter(args, filter_num) do {\ ut_assertok(run_command("log filter-add -p " args, 0)); \ - ut_assert_skipline(); \ ut_assertok(strict_strtoul(uts->actual_str, 10, &(filter_num))); \ ut_assert_console_end(); \ } while (0) diff --git a/test/log/log_test.c b/test/log/log_test.c index 1c89df4ef18..8686b1cbef3 100644 --- a/test/log/log_test.c +++ b/test/log/log_test.c @@ -320,7 +320,7 @@ int log_test_cat_deny(struct unit_test_state *uts) filt1 = log_add_filter("console", cat_list, LOGL_MAX, NULL); ut_assert(filt1 >= 0); filt2 = log_add_filter_flags("console", cat_list, LOGL_MAX, NULL, - LOGFF_DENY); + NULL, LOGFF_DENY); ut_assert(filt2 >= 0); log_run_cat(UCLASS_SPI); @@ -340,7 +340,7 @@ int log_test_file_deny(struct unit_test_state *uts) filt1 = log_add_filter("console", NULL, LOGL_MAX, "file"); ut_assert(filt1 >= 0); filt2 = log_add_filter_flags("console", NULL, LOGL_MAX, "file", - LOGFF_DENY); + NULL, LOGFF_DENY); ut_assert(filt2 >= 0); log_run_file("file"); @@ -360,7 +360,7 @@ int log_test_level_deny(struct unit_test_state *uts) filt1 = log_add_filter("console", NULL, LOGL_INFO, NULL); ut_assert(filt1 >= 0); filt2 = log_add_filter_flags("console", NULL, LOGL_WARNING, NULL, - LOGFF_DENY); + NULL, LOGFF_DENY); ut_assert(filt2 >= 0); log_run(); @@ -380,10 +380,10 @@ int log_test_min(struct unit_test_state *uts) int filt1, filt2; filt1 = log_add_filter_flags("console", NULL, LOGL_WARNING, NULL, - LOGFF_LEVEL_MIN); + NULL, LOGFF_LEVEL_MIN); ut_assert(filt1 >= 0); filt2 = log_add_filter_flags("console", NULL, LOGL_INFO, NULL, - LOGFF_DENY | LOGFF_LEVEL_MIN); + NULL, LOGFF_DENY | LOGFF_LEVEL_MIN); ut_assert(filt2 >= 0); log_run(); -- cgit v1.2.3 From 01b35b3e38bb5baa476a33e75b88346e820e4ba2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 17 Jan 2025 01:09:54 +0100 Subject: test/log: test function filters Add unit tests for function filters. Signed-off-by: Heinrich Schuchardt --- test/log/log_test.c | 68 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/test/log/log_test.c b/test/log/log_test.c index 8686b1cbef3..00b442252f0 100644 --- a/test/log/log_test.c +++ b/test/log/log_test.c @@ -15,7 +15,8 @@ DECLARE_GLOBAL_DATA_PTR; /* emit some sample log records in different ways, for testing */ -static int do_log_run(struct unit_test_state *uts, int cat, const char *file) +static int do_log_run(struct unit_test_state *uts, int cat, const char *file, + const char *func) { int i; int ret, expected_ret; @@ -30,13 +31,13 @@ static int do_log_run(struct unit_test_state *uts, int cat, const char *file) for (i = LOGL_FIRST; i < LOGL_COUNT; i++) { log(cat, i, "log %d\n", i); ret = _log(log_uc_cat(cat), i, file, 100 + i, - "func", "_log %d\n", i); + func, "_log %d\n", i); ut_asserteq(ret, expected_ret); } /* test with LOGL_COUNT flag */ for (i = LOGL_FIRST; i < LOGL_COUNT; i++) { ret = _log(log_uc_cat(cat), i | LOGL_FORCE_DEBUG, file, 100 + i, - "func", "_log force %d\n", i); + func, "_log force %d\n", i); ut_asserteq(ret, expected_ret); } @@ -44,9 +45,10 @@ static int do_log_run(struct unit_test_state *uts, int cat, const char *file) return 0; } -#define log_run_cat(cat) do_log_run(uts, cat, "file") -#define log_run_file(file) do_log_run(uts, UCLASS_SPI, file) -#define log_run() do_log_run(uts, UCLASS_SPI, "file") +#define log_run_cat(cat) do_log_run(uts, cat, "file", "func") +#define log_run_file(file) do_log_run(uts, UCLASS_SPI, file, "func") +#define log_run_func(func) do_log_run(uts, UCLASS_SPI, "file", func) +#define log_run() do_log_run(uts, UCLASS_SPI, "file", "func") #define EXPECT_LOG BIT(0) #define EXPECT_DIRECT BIT(1) @@ -55,7 +57,7 @@ static int do_log_run(struct unit_test_state *uts, int cat, const char *file) #define EXPECT_DEBUG BIT(4) static int do_check_log_entries(struct unit_test_state *uts, int flags, int min, - int max) + int max, const char *func) { int i; @@ -63,7 +65,8 @@ static int do_check_log_entries(struct unit_test_state *uts, int flags, int min, if (flags & EXPECT_LOG) ut_assert_nextline(" do_log_run() log %d", i); if (flags & EXPECT_DIRECT) - ut_assert_nextline(" func() _log %d", i); + ut_assert_nextline(" %s() _log %d", func, + i); if (flags & EXPECT_DEBUG) { ut_assert_nextline("log %d", i); ut_assert_nextline("_log %d", i); @@ -71,12 +74,13 @@ static int do_check_log_entries(struct unit_test_state *uts, int flags, int min, } if (flags & EXPECT_EXTRA) for (; i <= LOGL_MAX ; i++) - ut_assert_nextline(" func() _log %d", i); + ut_assert_nextline(" %s() _log %d", func, + i); for (i = LOGL_FIRST; i < LOGL_COUNT; i++) { if (flags & EXPECT_FORCE) - ut_assert_nextline(" func() _log force %d", - i); + ut_assert_nextline(" %s() _log force %d", + func, i); if (flags & EXPECT_DEBUG) ut_assert_nextline("_log force %d", i); } @@ -86,7 +90,7 @@ static int do_check_log_entries(struct unit_test_state *uts, int flags, int min, } #define check_log_entries_flags_levels(flags, min, max) do {\ - int ret = do_check_log_entries(uts, flags, min, max); \ + int ret = do_check_log_entries(uts, flags, min, max, "func"); \ if (ret) \ return ret; \ } while (0) @@ -192,6 +196,46 @@ int log_test_file_mid(struct unit_test_state *uts) } LOG_TEST_FLAGS(log_test_file_mid, UTF_CONSOLE); +/* Check passing and failing function filters */ +int log_test_func(struct unit_test_state *uts) +{ + int filt; + + filt = log_add_filter_flags("console", NULL, LOGL_MAX, "file", "func", + 0); + ut_assert(filt >= 0); + + log_run_func("func"); + check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE); + + log_run_func("fnc2"); + do_check_log_entries(uts, EXPECT_FORCE, LOGL_FIRST, _LOG_MAX_LEVEL, + "fnc2"); + + ut_assertok(log_remove_filter("console", filt)); + + return 0; +} +LOG_TEST_FLAGS(log_test_func, UTF_CONSOLE); + +/* Check a passing function filter (middle of list) */ +int log_test_func_mid(struct unit_test_state *uts) +{ + int filt; + + filt = log_add_filter_flags("console", NULL, LOGL_MAX, "file", + "bad1,func,bad2", 0); + ut_assert(filt >= 0); + + log_run_func("func"); + check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE); + + ut_assertok(log_remove_filter("console", filt)); + + return 0; +} +LOG_TEST_FLAGS(log_test_func_mid, UTF_CONSOLE); + /* Check a log level filter */ int log_test_level(struct unit_test_state *uts) { -- cgit v1.2.3 From e9c34fab18a9a0022b36729afd8e262e062764e2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 16 Jan 2025 20:26:59 +0100 Subject: efi_loader: use LOGC_EFI consistently The log category should be LOGC_EFI all over the EFI sub-system. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_driver/efi_block_device.c | 2 ++ lib/efi_driver/efi_uclass.c | 2 ++ lib/efi_loader/efi_acpi.c | 2 ++ lib/efi_loader/efi_boottime.c | 2 ++ lib/efi_loader/efi_conformance.c | 2 ++ lib/efi_loader/efi_device_path_to_text.c | 2 ++ lib/efi_loader/efi_device_path_utilities.c | 2 ++ lib/efi_loader/efi_dt_fixup.c | 2 ++ lib/efi_loader/efi_esrt.c | 2 ++ lib/efi_loader/efi_fdt.c | 2 ++ lib/efi_loader/efi_file.c | 2 ++ lib/efi_loader/efi_firmware.c | 2 ++ lib/efi_loader/efi_gop.c | 2 ++ lib/efi_loader/efi_helper.c | 1 + lib/efi_loader/efi_hii.c | 2 ++ lib/efi_loader/efi_hii_config.c | 2 ++ lib/efi_loader/efi_http.c | 2 ++ lib/efi_loader/efi_ipconfig.c | 2 ++ lib/efi_loader/efi_load_initrd.c | 1 + lib/efi_loader/efi_net.c | 2 ++ lib/efi_loader/efi_riscv.c | 1 + lib/efi_loader/efi_root_node.c | 2 ++ lib/efi_loader/efi_runtime.c | 2 ++ lib/efi_loader/efi_signature.c | 2 ++ lib/efi_loader/efi_string.c | 2 ++ lib/efi_loader/efi_tcg2.c | 1 + lib/efi_loader/efi_unicode_collation.c | 2 ++ lib/efi_loader/efi_var_common.c | 2 ++ lib/efi_loader/efi_var_mem.c | 2 ++ lib/efi_loader/efi_variable_tee.c | 2 ++ lib/efi_loader/efi_watchdog.c | 2 ++ 31 files changed, 58 insertions(+) diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 19a5ee24794..d3c668dc183 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -28,6 +28,8 @@ * iPXE uses the simple file protocol to load Grub or the Linux Kernel. */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index e1e28df20b2..495be53cb77 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -17,6 +17,8 @@ * controllers. */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index ff305a6b13e..4422b31ac6a 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -5,6 +5,8 @@ * Copyright (C) 2018, Bin Meng */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index db544382137..5164cb15986 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c index 167067e26cd..2bae93a94bd 100644 --- a/lib/efi_loader/efi_conformance.c +++ b/lib/efi_loader/efi_conformance.c @@ -5,6 +5,8 @@ * Copyright (C) 2022 Arm Ltd. */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 481a9712d9d..f6889cb7399 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index ac250bbfcc9..552c5bb1f05 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Leif Lindholm */ +#define LOG_CATEGORY LOGC_EFI + #include const efi_guid_t efi_guid_device_path_utilities_protocol = diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c index 0dac94b0c6c..26928cfc454 100644 --- a/lib/efi_loader/efi_dt_fixup.c +++ b/lib/efi_loader/efi_dt_fixup.c @@ -5,6 +5,8 @@ * Copyright (c) 2020 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c index 443bd999ce1..e235c8fe91c 100644 --- a/lib/efi_loader/efi_esrt.c +++ b/lib/efi_loader/efi_esrt.c @@ -5,6 +5,8 @@ * Copyright (C) 2021 Arm Ltd. */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c index f882622fdad..1ba6641d821 100644 --- a/lib/efi_loader/efi_fdt.c +++ b/lib/efi_loader/efi_fdt.c @@ -6,6 +6,8 @@ * Written by Simon Glass */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 95b3c890ee9..201fa5f8f3c 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Rob Clark */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 112775daf4c..5a754c9cd03 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -6,6 +6,8 @@ * Author: AKASHI Takahiro */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 41e12fa7246..4593975be5a 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index bf96f61d3d0..04b2efc4a3b 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -4,6 +4,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c index 74e402df1b8..44235970a7c 100644 --- a/lib/efi_loader/efi_hii.c +++ b/lib/efi_loader/efi_hii.c @@ -6,6 +6,8 @@ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c index ae0f3ecd3b1..37d8c6629e2 100644 --- a/lib/efi_loader/efi_hii_config.c +++ b/lib/efi_loader/efi_hii_config.c @@ -10,6 +10,8 @@ * the Makefile. */ +#define LOG_CATEGORY LOGC_EFI + #include const efi_guid_t efi_guid_hii_config_routing_protocol diff --git a/lib/efi_loader/efi_http.c b/lib/efi_loader/efi_http.c index 694e1993418..88816256b03 100644 --- a/lib/efi_loader/efi_http.c +++ b/lib/efi_loader/efi_http.c @@ -7,6 +7,8 @@ * IP4_CONFIG2_PROTOCOL */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_ipconfig.c b/lib/efi_loader/efi_ipconfig.c index 0b247a4c028..f1c092daafd 100644 --- a/lib/efi_loader/efi_ipconfig.c +++ b/lib/efi_loader/efi_ipconfig.c @@ -4,6 +4,8 @@ * */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index 23508431c83..fb8cc7bcbe3 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -4,6 +4,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 67593ef50c0..ce9272fa240 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -15,6 +15,8 @@ * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_riscv.c b/lib/efi_loader/efi_riscv.c index 4d398c5be34..6f2ccf4f7e6 100644 --- a/lib/efi_loader/efi_riscv.c +++ b/lib/efi_loader/efi_riscv.c @@ -7,6 +7,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index 4d7fb74b5d6..74225edad29 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -5,6 +5,8 @@ * Copyright (c) 2018 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 05369c47b01..35eb6a77766 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 184eac8cddb..93a4f257016 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -4,6 +4,8 @@ * Copyright (c) 2019 Linaro Limited, Author: AKASHI Takahiro */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_string.c b/lib/efi_loader/efi_string.c index 413e329b600..50d1daf33a9 100644 --- a/lib/efi_loader/efi_string.c +++ b/lib/efi_loader/efi_string.c @@ -5,6 +5,8 @@ * Copyright (c) 2020 AKASHI Takahiro, Linaro Limited */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index a15c73162ee..c697b53441a 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -8,6 +8,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index d48700a352b..df2a988ee39 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -5,6 +5,8 @@ * Copyright (c) 2018 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index ea8d2a4cf98..4b34a58b4cf 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -5,6 +5,8 @@ * Copyright (c) 2020 Linaro Limited, Author: AKASHI Takahiro */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index 139e16aad7c..b265d95dd6b 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -5,6 +5,8 @@ * Copyright (c) 2020, Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index 8b6b0a39086..0d090d051dd 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -10,6 +10,8 @@ * Abdellatif El Khlifi */ +#define LOG_CATEGORY LOGC_EFI + #if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) #include #endif diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c index f5fb9117717..c21d8086074 100644 --- a/lib/efi_loader/efi_watchdog.c +++ b/lib/efi_loader/efi_watchdog.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include /* Conversion factor from seconds to multiples of 100ns */ -- cgit v1.2.3 From e20349a38caf429f3109a6a02529573472f521ae Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 17 Jan 2025 21:34:01 +0100 Subject: efi_loader: reduce UEFI size if HAS_BOARD_SIZE_LIMIT=y If a board has a strict size limit, disable * Unicode capitalization and * HII protocols by default to reduce the image size. Reviewed-by: Ilias Apalodimas Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 798dced475e..ad0bbdd8a77 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -387,7 +387,7 @@ config EFI_DT_FIXUP config EFI_LOADER_HII bool "HII protocols" - default y + default y if !HAS_BOARD_SIZE_LIMIT help The Human Interface Infrastructure is a complicated framework that allows UEFI applications to draw fancy menus and hook strings using @@ -407,7 +407,7 @@ if EFI_UNICODE_COLLATION_PROTOCOL2 config EFI_UNICODE_CAPITALIZATION bool "Support Unicode capitalization" - default y + default y if !HAS_BOARD_SIZE_LIMIT help Select this option to enable correct handling of the capitalization of Unicode codepoints in the range 0x0000-0xffff. If this option is not -- cgit v1.2.3 From 7a713ab1c63fd5efb1f71caf6678166f9a7447be Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 23 Jan 2025 03:46:51 +0100 Subject: doc: describe creating a pflash file for qemu-system-riscv64 U-Boot can be executed in place from a flash device. Describe how this can be emulated on RISC-V QEMU. Signed-off-by: Heinrich Schuchardt --- doc/board/emulation/qemu-riscv.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/board/emulation/qemu-riscv.rst b/doc/board/emulation/qemu-riscv.rst index 8388e13d96d..cf2f893b723 100644 --- a/doc/board/emulation/qemu-riscv.rst +++ b/doc/board/emulation/qemu-riscv.rst @@ -42,6 +42,23 @@ use the configurations qemu-riscv32_smode_defconfig and qemu-riscv64_smode_defconfig instead. Note that U-Boot running in supervisor mode requires a supervisor binary interface (SBI), such as RISC-V OpenSBI. +To create a U-Boot binary that can be utilized with a pflash device in QEMU +apply these addtional settings to qemu-riscv64_smode_defconfig: + +:: + + CONFIG_TEXT_BASE=0x20000000 + CONFIG_XIP=y + # CONFIG_AVAILABLE_HARTS is not set + CONFIG_SYS_MONITOR_BASE=0x80200000 + +Truncate the resulting u-boot.bin to 32 MiB. Add the following to your +qemu-system-riscv64 command: + +.. code-block:: bash + + -drive if=pflash,format=raw,unit=0,file=u-boot.bin + Running U-Boot -------------- The minimal QEMU command line to get U-Boot up and running is: -- cgit v1.2.3 From a70759898a0ee9750d418da78ff0ebcd432e9bb5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 23 Jan 2025 15:07:20 -0700 Subject: efi_loader: Update efi_run_image() to accept image and device path Provide these globals as parameters to this function, on the way to making it possible to start an image without relying on the globals. Signed-off-by: Simon Glass Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_bootbin.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index 428991df88f..71591dd54b9 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -157,9 +157,13 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, * * @source_buffer: memory address of the UEFI image * @source_size: size of the UEFI image + * @dp_dev: EFI device-path + * @dp_img: EFI image-path * Return: status code */ -static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) +static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size, + struct efi_device_path *dp_dev, + struct efi_device_path *dp_img) { efi_handle_t mem_handle = NULL, handle; struct efi_device_path *file_path = NULL; @@ -167,7 +171,7 @@ static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) efi_status_t ret; u16 *load_options; - if (!bootefi_device_path || !bootefi_image_path) { + if (!dp_img || !dp_img) { log_debug("Not loaded from disk\n"); /* * Special case for efi payload not loaded from disk, @@ -188,9 +192,8 @@ static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) goto out; msg_path = file_path; } else { - file_path = efi_dp_concat(bootefi_device_path, - bootefi_image_path, 0); - msg_path = bootefi_image_path; + file_path = efi_dp_concat(dp_img, dp_img, 0); + msg_path = dp_img; log_debug("Loaded from disk\n"); } @@ -252,5 +255,6 @@ efi_status_t efi_binary_run(void *image, size_t size, void *fdt) if (ret != EFI_SUCCESS) return ret; - return efi_run_image(image, size); + return efi_run_image(image, size, bootefi_device_path, + bootefi_image_path); } -- cgit v1.2.3 From b9f42821af4dfc0988c39cb4d0ae28118da2c312 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 23 Jan 2025 15:07:21 -0700 Subject: efi_loader: Add a version of efi_binary_run() with more parameters This uses a few global variables at present. With the bootflow we have the required parameters, so add a function which accepts these. Update the existing function to call the new one with the globals. Signed-off-by: Simon Glass Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_bootbin.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index 71591dd54b9..789da8bcda0 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -228,18 +228,22 @@ out: } /** - * efi_binary_run() - run loaded UEFI image + * efi_binary_run_dp() - run loaded UEFI image * * @image: memory address of the UEFI image * @size: size of the UEFI image * @fdt: device-tree + * @dp_dev: EFI device-path + * @dp_img: EFI image-path * * Execute an EFI binary image loaded at @image. * @size may be zero if the binary is loaded with U-Boot load command. * * Return: status code */ -efi_status_t efi_binary_run(void *image, size_t size, void *fdt) +efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt, + struct efi_device_path *dp_dev, + struct efi_device_path *dp_img) { efi_status_t ret; @@ -255,6 +259,23 @@ efi_status_t efi_binary_run(void *image, size_t size, void *fdt) if (ret != EFI_SUCCESS) return ret; - return efi_run_image(image, size, bootefi_device_path, - bootefi_image_path); + return efi_run_image(image, size, dp_dev, dp_img); +} + +/** + * efi_binary_run() - run loaded UEFI image + * + * @image: memory address of the UEFI image + * @size: size of the UEFI image + * @fdt: device-tree + * + * Execute an EFI binary image loaded at @image. + * @size may be zero if the binary is loaded with U-Boot load command. + * + * Return: status code + */ +efi_status_t efi_binary_run(void *image, size_t size, void *fdt) +{ + return efi_binary_run_dp(image, size, fdt, bootefi_device_path, + bootefi_image_path); } -- cgit v1.2.3 From 5f67c8800e8ea56ab161a7b643f54190556e70bc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 23 Jan 2025 15:07:22 -0700 Subject: efi_loader: Move the fallback code from efi_run_image() This code is only needed if an invalid image/device path is passed in. Move the code out to a caller where this can be dealt with. The normal flow will provide these parameters. Signed-off-by: Simon Glass --- lib/efi_loader/efi_bootbin.c | 89 +++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index 789da8bcda0..dce154e728a 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -165,37 +165,13 @@ static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size, struct efi_device_path *dp_dev, struct efi_device_path *dp_img) { - efi_handle_t mem_handle = NULL, handle; - struct efi_device_path *file_path = NULL; - struct efi_device_path *msg_path; + efi_handle_t handle; + struct efi_device_path *msg_path, *file_path; efi_status_t ret; u16 *load_options; - if (!dp_img || !dp_img) { - log_debug("Not loaded from disk\n"); - /* - * Special case for efi payload not loaded from disk, - * such as 'bootefi hello' or for example payload - * loaded directly into memory via JTAG, etc: - */ - file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, - (uintptr_t)source_buffer, - source_size); - /* - * Make sure that device for device_path exist - * in load_image(). Otherwise, shell and grub will fail. - */ - ret = efi_install_multiple_protocol_interfaces(&mem_handle, - &efi_guid_device_path, - file_path, NULL); - if (ret != EFI_SUCCESS) - goto out; - msg_path = file_path; - } else { - file_path = efi_dp_concat(dp_img, dp_img, 0); - msg_path = dp_img; - log_debug("Loaded from disk\n"); - } + file_path = efi_dp_concat(dp_dev, dp_img, 0); + msg_path = dp_img; log_info("Booting %pD\n", msg_path); @@ -214,15 +190,6 @@ static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size, ret = do_bootefi_exec(handle, load_options); out: - if (mem_handle) { - efi_status_t r; - - r = efi_uninstall_multiple_protocol_interfaces( - mem_handle, &efi_guid_device_path, file_path, NULL); - if (r != EFI_SUCCESS) - log_err("Uninstalling protocol interfaces failed\n"); - } - efi_free_pool(file_path); return ret; } @@ -241,9 +208,9 @@ out: * * Return: status code */ -efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt, - struct efi_device_path *dp_dev, - struct efi_device_path *dp_img) +static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt, + struct efi_device_path *dp_dev, + struct efi_device_path *dp_img) { efi_status_t ret; @@ -276,6 +243,44 @@ efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt, */ efi_status_t efi_binary_run(void *image, size_t size, void *fdt) { - return efi_binary_run_dp(image, size, fdt, bootefi_device_path, - bootefi_image_path); + efi_handle_t mem_handle = NULL; + struct efi_device_path *file_path = NULL; + efi_status_t ret; + + 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 + * loaded directly into memory via JTAG, etc: + */ + file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)image, size); + /* + * Make sure that device for device_path exist + * in load_image(). Otherwise, shell and grub will fail. + */ + ret = efi_install_multiple_protocol_interfaces(&mem_handle, + &efi_guid_device_path, + file_path, NULL); + if (ret != EFI_SUCCESS) + goto out; + } else { + log_debug("Loaded from disk\n"); + } + + ret = efi_binary_run_dp(image, size, fdt, bootefi_device_path, + bootefi_image_path); +out: + if (mem_handle) { + efi_status_t r; + + r = efi_uninstall_multiple_protocol_interfaces(mem_handle, + &efi_guid_device_path, file_path, NULL); + if (r != EFI_SUCCESS) + log_err("Uninstalling protocol interfaces failed\n"); + } + efi_free_pool(file_path); + + return ret; } -- cgit v1.2.3 From a2338955fc1d3bb6de86ab4fb6e7c55ff189f4f0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 23 Jan 2025 15:07:23 -0700 Subject: efi_loader: Pass in the required parameters from EFI bootmeth Rather than setting up the global variables and then making the call, pass them into function directly. This cleans up the code and makes it all a bit easier to understand. Signed-off-by: Simon Glass --- boot/bootmeth_efi.c | 49 ++---------------------------- include/efi_loader.h | 10 +++++++ lib/efi_loader/efi_bootbin.c | 71 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 47 deletions(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index a2998452666..b745ba8bd4b 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -52,40 +52,6 @@ static bool bootmeth_uses_network(struct bootflow *bflow) device_get_uclass_id(media) == UCLASS_ETH; } -static void set_efi_bootdev(struct blk_desc *desc, struct bootflow *bflow) -{ - const struct udevice *media_dev; - int size = bflow->size; - const char *dev_name; - char devnum_str[9]; - char dirname[200]; - char *last_slash; - - /* - * This is a horrible hack to tell EFI about this boot device. Once we - * unify EFI with the rest of U-Boot we can clean this up. The same hack - * exists in multiple places, e.g. in the fs, tftp and load commands. - * - * Once we can clean up the EFI code to make proper use of driver model, - * this can go away. - */ - media_dev = dev_get_parent(bflow->dev); - snprintf(devnum_str, sizeof(devnum_str), "%x:%x", - desc ? desc->devnum : dev_seq(media_dev), - bflow->part); - - strlcpy(dirname, bflow->fname, sizeof(dirname)); - last_slash = strrchr(dirname, '/'); - if (last_slash) - *last_slash = '\0'; - - dev_name = device_get_uclass_id(media_dev) == UCLASS_MASS_STORAGE ? - "usb" : blk_get_uclass_name(device_get_uclass_id(media_dev)); - log_debug("setting bootdev %s, %s, %s, %p, %x\n", - dev_name, devnum_str, bflow->fname, bflow->buf, size); - efi_set_bootdev(dev_name, devnum_str, bflow->fname, bflow->buf, size); -} - static int efiload_read_file(struct bootflow *bflow, ulong addr) { struct blk_desc *desc = NULL; @@ -102,8 +68,6 @@ static int efiload_read_file(struct bootflow *bflow, ulong addr) return log_msg_ret("rdf", ret); bflow->buf = map_sysmem(addr, bflow->size); - set_efi_bootdev(desc, bflow); - return 0; } @@ -344,17 +308,8 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) fdt = env_get_hex("fdt_addr_r", 0); } - if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) { - log_debug("Booting with built-in fdt\n"); - if (efi_binary_run(map_sysmem(kernel, 0), bflow->size, - EFI_FDT_USE_INTERNAL)) - return log_msg_ret("run", -EINVAL); - } else { - log_debug("Booting with external fdt\n"); - if (efi_binary_run(map_sysmem(kernel, 0), bflow->size, - map_sysmem(fdt, 0))) - return log_msg_ret("run", -EINVAL); - } + if (efi_bootflow_run(bflow)) + return log_msg_ret("run", -EINVAL); return 0; } diff --git a/include/efi_loader.h b/include/efi_loader.h index 5bf271afaad..dcae6a731a0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -20,6 +20,7 @@ #include struct blk_desc; +struct bootflow; struct jmp_buf_data; #if CONFIG_IS_ENABLED(EFI_LOADER) @@ -590,6 +591,15 @@ efi_status_t efi_install_fdt(void *fdt); efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options); /* Run loaded UEFI image with given fdt */ efi_status_t efi_binary_run(void *image, size_t size, void *fdt); + +/** + * efi_bootflow_run() - Run a bootflow containing an EFI application + * + * @bootflow: Bootflow to run + * Return: Status code, something went wrong + */ +efi_status_t efi_bootflow_run(struct bootflow *bootflow); + /* Initialize variable services */ efi_status_t efi_init_variables(void); /* Notify ExitBootServices() is called */ diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index dce154e728a..fdde536af7a 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -6,13 +6,16 @@ #define LOG_CATEGORY LOGC_EFI +#include #include +#include #include #include #include #include #include #include +#include static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; @@ -284,3 +287,71 @@ out: return ret; } + +/** + * calc_dev_name() - Calculate the device name to give to EFI + * + * If not supported, this shows an error. + * + * Return name, or NULL if not supported + */ +static const char *calc_dev_name(struct bootflow *bflow) +{ + const struct udevice *media_dev; + + media_dev = dev_get_parent(bflow->dev); + + if (!bflow->blk) { + log_err("Cannot boot EFI app on media '%s'\n", + dev_get_uclass_name(media_dev)); + + return NULL; + } + + if (device_get_uclass_id(media_dev) == UCLASS_MASS_STORAGE) + return "usb"; + + return blk_get_uclass_name(device_get_uclass_id(media_dev)); +} + +efi_status_t efi_bootflow_run(struct bootflow *bflow) +{ + struct efi_device_path *device, *image; + const struct udevice *media_dev; + struct blk_desc *desc = NULL; + const char *dev_name; + char devnum_str[9]; + efi_status_t ret; + void *fdt; + + media_dev = dev_get_parent(bflow->dev); + if (bflow->blk) { + desc = dev_get_uclass_plat(bflow->blk); + + snprintf(devnum_str, sizeof(devnum_str), "%x:%x", + desc ? desc->devnum : dev_seq(media_dev), bflow->part); + } else { + *devnum_str = '\0'; + } + + dev_name = calc_dev_name(bflow); + log_debug("dev_name '%s' devnum_str '%s' fname '%s' media_dev '%s'\n", + dev_name, devnum_str, bflow->fname, media_dev->name); + if (!dev_name) + return EFI_UNSUPPORTED; + ret = calculate_paths(dev_name, devnum_str, bflow->fname, &device, + &image); + if (ret) + return ret; + + if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) { + log_debug("Booting with built-in fdt\n"); + fdt = EFI_FDT_USE_INTERNAL; + } else { + log_debug("Booting with external fdt\n"); + fdt = map_sysmem(bflow->fdt_addr, 0); + } + ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, device, image); + + return ret; +} -- cgit v1.2.3 From 21de624eb89c647a21b06a5b0f5b186838be1d17 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 23 Jan 2025 15:07:24 -0700 Subject: bootmeth_efi: Support PXE booting Finish off the implementation so it is possible to boot an EFI app over a network. Signed-off-by: Simon Glass --- boot/bootmeth_efi.c | 15 +-------------- lib/efi_loader/efi_bootbin.c | 5 ++++- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index b745ba8bd4b..0c9b4c3d59d 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -210,6 +210,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (size <= 0) return log_msg_ret("sz", -EINVAL); bflow->size = size; + bflow->buf = map_sysmem(addr, size); /* bootfile should be setup by dhcp */ bootfile_name = env_get("bootfile"); @@ -219,10 +220,6 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (!bflow->fname) return log_msg_ret("fi0", -ENOMEM); - /* do the hideous EFI hack */ - efi_set_bootdev("Net", "", bflow->fname, map_sysmem(addr, 0), - bflow->size); - /* read the DT file also */ fdt_addr_str = env_get("fdt_addr_r"); if (!fdt_addr_str) @@ -296,16 +293,6 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) if (bflow->flags & ~BOOTFLOWF_USE_BUILTIN_FDT) fdt = bflow->fdt_addr; - } else { - /* - * This doesn't actually work for network devices: - * - * do_bootefi_image() No UEFI binary known at 0x02080000 - * - * But this is the same behaviour for distro boot, so it can be - * fixed here. - */ - fdt = env_get_hex("fdt_addr_r", 0); } if (efi_bootflow_run(bflow)) diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index fdde536af7a..10ec5e9ada3 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -302,6 +302,9 @@ static const char *calc_dev_name(struct bootflow *bflow) media_dev = dev_get_parent(bflow->dev); if (!bflow->blk) { + if (device_get_uclass_id(media_dev) == UCLASS_ETH) + return "Net"; + log_err("Cannot boot EFI app on media '%s'\n", dev_get_uclass_name(media_dev)); @@ -342,7 +345,7 @@ efi_status_t efi_bootflow_run(struct bootflow *bflow) ret = calculate_paths(dev_name, devnum_str, bflow->fname, &device, &image); if (ret) - return ret; + return EFI_UNSUPPORTED; if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) { log_debug("Booting with built-in fdt\n"); -- cgit v1.2.3