summaryrefslogtreecommitdiff
path: root/boot/bootmeth_efi.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/bootmeth_efi.c')
-rw-r--r--boot/bootmeth_efi.c79
1 files changed, 63 insertions, 16 deletions
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 0af23df3a4a..f592fec07f6 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -16,6 +16,7 @@
#include <efi.h>
#include <efi_loader.h>
#include <env.h>
+#include <extension_board.h>
#include <fs.h>
#include <malloc.h>
#include <mapmem.h>
@@ -99,8 +100,11 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
static int distro_efi_try_bootflow_files(struct udevice *dev,
struct bootflow *bflow)
{
+ ulong fdt_addr, size, overlay_addr;
+ const struct extension *extension;
+ struct fdt_header *working_fdt;
struct blk_desc *desc = NULL;
- ulong fdt_addr, size;
+ struct alist *extension_list;
char fname[256];
int ret, seq;
@@ -148,23 +152,66 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
return log_msg_ret("fil", -ENOMEM);
}
- if (!ret) {
- bflow->fdt_size = size;
- bflow->fdt_addr = fdt_addr;
-
- /*
- * TODO: Apply extension overlay
- *
- * Here we need to load and apply the extension overlay. This is
- * not implemented. See do_extension_apply(). The extension
- * stuff needs an implementation in boot/extension.c so it is
- * separate from the command code. Really the extension stuff
- * should use the device tree and a uclass / driver interface
- * rather than implementing its own list
- */
- } else {
+ if (ret) {
log_debug("No device tree available\n");
bflow->flags |= BOOTFLOWF_USE_BUILTIN_FDT;
+ return 0;
+ }
+
+ bflow->fdt_size = size;
+ bflow->fdt_addr = fdt_addr;
+
+ if (!CONFIG_IS_ENABLED(SUPPORT_EXTENSION_SCAN))
+ return 0;
+
+ ret = extension_scan();
+ if (ret < 0)
+ return 0;
+
+ extension_list = extension_get_list();
+ if (!extension_list)
+ return 0;
+
+ working_fdt = map_sysmem(fdt_addr, 0);
+ if (fdt_check_header(working_fdt))
+ return 0;
+
+ overlay_addr = env_get_hex("extension_overlay_addr", 0);
+ if (!overlay_addr) {
+ log_debug("Environment extension_overlay_addr is missing\n");
+ return 0;
+ }
+
+ alist_for_each(extension, extension_list) {
+ char *overlay_file;
+ int len;
+
+ len = sizeof(EFI_DIRNAME) + strlen(extension->overlay);
+ overlay_file = calloc(1, len);
+ if (!overlay_file)
+ return -ENOMEM;
+
+ snprintf(overlay_file, len, "%s%s", EFI_DIRNAME,
+ extension->overlay);
+
+ ret = bootmeth_common_read_file(dev, bflow, overlay_file,
+ overlay_addr,
+ (enum bootflow_img_t)IH_TYPE_FLATDT,
+ &size);
+ if (ret) {
+ log_debug("Failed loading overlay %s\n", overlay_file);
+ free(overlay_file);
+ continue;
+ }
+
+ ret = extension_apply(working_fdt, size);
+ if (ret) {
+ log_debug("Failed applying overlay %s\n", overlay_file);
+ free(overlay_file);
+ continue;
+ }
+ bflow->fdt_size += size;
+ free(overlay_file);
}
return 0;