diff options
-rw-r--r-- | cmd/bootefi.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index f502996..9b8af65 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -12,6 +12,10 @@ #include <errno.h> #include <libfdt.h> #include <libfdt_env.h> +#include <malloc.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; /* * When booting using the "bootefi" command, we don't know which @@ -97,6 +101,21 @@ static struct efi_object bootefi_device_obj = { }, }; +static void *copy_fdt(void *fdt) +{ + u64 fdt_size = fdt_totalsize(fdt); + void *new_fdt; + + /* Give us 64kb breathing room */ + fdt_size += 64 * 1024; + + new_fdt = malloc(fdt_size); + memcpy(new_fdt, fdt, fdt_totalsize(fdt)); + fdt_set_totalsize(new_fdt, fdt_size); + + return new_fdt; +} + /* * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. @@ -106,6 +125,7 @@ static unsigned long do_bootefi_exec(void *efi) ulong (*entry)(void *image_handle, struct efi_system_table *st); ulong fdt_pages, fdt_size, fdt_start, fdt_end; bootm_headers_t img = { 0 }; + void *fdt = working_fdt; /* * gd lives in a fixed register which may get clobbered while we execute @@ -115,28 +135,33 @@ static unsigned long do_bootefi_exec(void *efi) /* Update system table to point to our currently loaded FDT */ - if (working_fdt) { + /* Fall back to included fdt if none was manually loaded */ + if (!fdt && gd->fdt_blob) + fdt = (void *)gd->fdt_blob; + + if (fdt) { /* Prepare fdt for payload */ - if (image_setup_libfdt(&img, working_fdt, 0, NULL)) { + fdt = copy_fdt(fdt); + + if (image_setup_libfdt(&img, fdt, 0, NULL)) { printf("ERROR: Failed to process device tree\n"); return -EINVAL; } /* Link to it in the efi tables */ systab.tables[0].guid = EFI_FDT_GUID; - systab.tables[0].table = working_fdt; + systab.tables[0].table = fdt; systab.nr_tables = 1; /* And reserve the space in the memory map */ - fdt_start = ((ulong)working_fdt) & ~EFI_PAGE_MASK; - fdt_end = ((ulong)working_fdt) + fdt_totalsize(working_fdt); + fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK; + fdt_end = ((ulong)fdt) + fdt_totalsize(fdt); fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK; fdt_pages = fdt_size >> EFI_PAGE_SHIFT; /* Give a bootloader the chance to modify the device tree */ fdt_pages += 2; efi_add_memory_map(fdt_start, fdt_pages, EFI_BOOT_SERVICES_DATA, true); - } else { printf("WARNING: No device tree loaded, expect boot to fail\n"); systab.nr_tables = 0; |