From c9463859500c0db85a3e5a0a8e347fcb35e54aae Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 26 Apr 2024 16:13:18 +0200 Subject: efi_loader: move distro_efi_get_fdt_name() Move distro_efi_get_fdt_name() to a separate C module and rename it to efi_get_distro_fdt_name(). Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_fdt.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 lib/efi_loader/efi_fdt.c (limited to 'lib/efi_loader/efi_fdt.c') diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c new file mode 100644 index 00000000000..0edf0c1e2fc --- /dev/null +++ b/lib/efi_loader/efi_fdt.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for distro boot via EFI + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include + +/** + * distro_efi_get_fdt_name() - get the filename for reading the .dtb file + * + * @fname: buffer for filename + * @size: buffer size + * @seq: sequence number, to cycle through options (0=first) + * + * Returns: + * 0 on success, + * -ENOENT if the "fdtfile" env var does not exist, + * -EINVAL if there are no more options, + * -EALREADY if the control FDT should be used + */ +int efi_get_distro_fdt_name(char *fname, int size, int seq) +{ + const char *fdt_fname; + const char *prefix; + + /* select the prefix */ + switch (seq) { + case 0: + /* this is the default */ + prefix = "/dtb"; + break; + case 1: + prefix = ""; + break; + case 2: + prefix = "/dtb/current"; + break; + default: + return log_msg_ret("pref", -EINVAL); + } + + fdt_fname = env_get("fdtfile"); + if (fdt_fname) { + snprintf(fname, size, "%s/%s", prefix, fdt_fname); + log_debug("Using device tree: %s\n", fname); + } else if (IS_ENABLED(CONFIG_OF_HAS_PRIOR_STAGE)) { + strcpy(fname, ""); + return log_msg_ret("pref", -EALREADY); + /* Use this fallback only for 32-bit ARM */ + } else if (IS_ENABLED(CONFIG_ARM) && !IS_ENABLED(CONFIG_ARM64)) { + const char *soc = env_get("soc"); + const char *board = env_get("board"); + const char *boardver = env_get("boardver"); + + /* cf the code in label_boot() which seems very complex */ + snprintf(fname, size, "%s/%s%s%s%s.dtb", prefix, + soc ? soc : "", soc ? "-" : "", board ? board : "", + boardver ? boardver : ""); + log_debug("Using default device tree: %s\n", fname); + } else { + return log_msg_ret("env", -ENOENT); + } + + return 0; +} -- cgit v1.2.3 From e91b68fd6b83d6e4c862000630d240b339cc5a7b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 26 Apr 2024 16:13:21 +0200 Subject: efi_loader: load distro dtb in bootmgr If no device-tree is specified, try to load a device-tree from the boot device use the $fdtfile concatenated to either of the paths '/dtb/', '/', '/dtb/current/'. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_fdt.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'lib/efi_loader/efi_fdt.c') diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c index 0edf0c1e2fc..86ba00c2bdd 100644 --- a/lib/efi_loader/efi_fdt.c +++ b/lib/efi_loader/efi_fdt.c @@ -71,3 +71,47 @@ int efi_get_distro_fdt_name(char *fname, int size, int seq) return 0; } + +/** + * efi_load_distro_fdt() - load distro device-tree + * + * @fdt: on return device-tree, must be freed via efi_free_pages() + * @fdt_size: buffer size + */ +void efi_load_distro_fdt(void **fdt, efi_uintn_t *fdt_size) +{ + struct efi_device_path *rem, *dp; + efi_status_t ret; + efi_handle_t device; + + *fdt = NULL; + + dp = efi_get_dp_from_boot(NULL); + if (!dp) + return; + device = efi_dp_find_obj(dp, NULL, &rem); + ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid, + NULL); + if (ret != EFI_SUCCESS) + goto err; + memcpy(rem, &END, sizeof(END)); + + /* try the various available names */ + for (int seq = 0; ; ++seq) { + struct efi_device_path *file; + char buf[255]; + + if (efi_get_distro_fdt_name(buf, sizeof(buf), seq)) + break; + file = efi_dp_from_file(dp, buf); + if (!file) + break; + ret = efi_load_image_from_path(true, file, fdt, fdt_size); + efi_free_pool(file); + if (ret == EFI_SUCCESS) + break; + } + +err: + efi_free_pool(dp); +} -- cgit v1.2.3