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 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') 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: */ -- cgit v1.3.1 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(-) (limited to 'include') 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.3.1 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(-) (limited to 'include') 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.3.1 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(-) (limited to 'include') 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.3.1