diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 64de5c08b7b..f592fec07f6 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -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; @@ -157,16 +161,58 @@ static int distro_efi_try_bootflow_files(struct udevice *dev, 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 - */ + 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; }