X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cmd%2Fbootefi.c;h=0f6d0f77507ca2b0e577814a830dc4a5b813bce0;hb=09140113108541b95d340f3c7b6ee597d31ccc73;hp=78c8b8dbd166ce3bac91910d0efe797257679ef2;hpb=f64f223256f32e86d97ec32eea7dc36d5e9c5fd9;p=oweals%2Fu-boot.git diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 78c8b8dbd1..0f6d0f7750 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,11 +30,13 @@ static struct efi_device_path *bootefi_device_path; /** * Set the load options of an image from an environment variable. * - * @handle: the image handle - * @env_var: name of the environment variable - * Return: status code + * @handle: the image handle + * @env_var: name of the environment variable + * @load_options: pointer to load options (output) + * Return: status code */ -static efi_status_t set_load_options(efi_handle_t handle, const char *env_var) +static efi_status_t set_load_options(efi_handle_t handle, const char *env_var, + u16 **load_options) { struct efi_loaded_image *loaded_image_info; size_t size; @@ -40,6 +44,7 @@ static efi_status_t set_load_options(efi_handle_t handle, const char *env_var) u16 *pos; efi_status_t ret; + *load_options = NULL; ret = EFI_CALL(systab.boottime->open_protocol( handle, &efi_guid_loaded_image, @@ -64,6 +69,7 @@ static efi_status_t set_load_options(efi_handle_t handle, const char *env_var) return EFI_OUT_OF_RESOURCES; } pos = loaded_image_info->load_options; + *load_options = pos; utf8_utf16_strcpy(&pos, env); loaded_image_info->load_options_size = size * 2; @@ -122,13 +128,13 @@ static efi_status_t copy_fdt(void **fdtp) new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 + fdt_size, 0); ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, - EFI_BOOT_SERVICES_DATA, fdt_pages, + EFI_ACPI_RECLAIM_MEMORY, fdt_pages, &new_fdt_addr); if (ret != EFI_SUCCESS) { /* If we can't put it there, put it somewhere */ new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, - EFI_BOOT_SERVICES_DATA, fdt_pages, + EFI_ACPI_RECLAIM_MEMORY, fdt_pages, &new_fdt_addr); if (ret != EFI_SUCCESS) { printf("ERROR: Failed to reserve space for FDT\n"); @@ -144,6 +150,16 @@ done: return ret; } +static void efi_reserve_memory(u64 addr, u64 size) +{ + /* Convert from sandbox address space. */ + addr = (uintptr_t)map_sysmem(addr, 0); + if (efi_add_memory_map(addr, size, + EFI_RESERVED_MEMORY_TYPE) != EFI_SUCCESS) + printf("Reserved memory mapping failed addr %llx size %llx\n", + addr, size); +} + /** * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges * @@ -156,7 +172,8 @@ done: static void efi_carve_out_dt_rsv(void *fdt) { int nr_rsv, i; - uint64_t addr, size, pages; + u64 addr, size; + int nodeoffset, subnode; nr_rsv = fdt_num_mem_rsv(fdt); @@ -164,15 +181,26 @@ static void efi_carve_out_dt_rsv(void *fdt) for (i = 0; i < nr_rsv; i++) { if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) continue; + efi_reserve_memory(addr, size); + } - /* Convert from sandbox address space. */ - addr = (uintptr_t)map_sysmem(addr, 0); - - pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); - addr &= ~EFI_PAGE_MASK; - if (efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, - false) != EFI_SUCCESS) - printf("FDT memrsv map %d: Failed to add to map\n", i); + /* process reserved-memory */ + nodeoffset = fdt_subnode_offset(fdt, 0, "reserved-memory"); + if (nodeoffset >= 0) { + subnode = fdt_first_subnode(fdt, nodeoffset); + while (subnode >= 0) { + /* check if this subnode has a reg property */ + addr = fdtdec_get_addr_size(fdt, subnode, "reg", + (fdt_size_t *)&size); + /* + * The /reserved-memory node may have children with + * a size instead of a reg property. + */ + if (addr != FDT_ADDR_T_NONE && + fdtdec_get_is_enabled(fdt, subnode)) + efi_reserve_memory(addr, size); + subnode = fdt_next_subnode(fdt, subnode); + } } } @@ -198,15 +226,15 @@ static void *get_config_table(const efi_guid_t *guid) /** * efi_install_fdt() - install device tree * - * If fdt_addr is available, the device tree located at that memory address will - * will be installed as configuration table, otherwise the device tree located - * at the address indicated by environment variable fdt_addr or as fallback - * fdtcontroladdr will be used. + * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory + * address will will be installed as configuration table, otherwise the device + * tree located at the address indicated by environment variable fdt_addr or as + * fallback fdtcontroladdr will be used. * * On architectures using ACPI tables device trees shall not be installed as * configuration table. * - * @fdt_addr: address of device tree or EFI_FDT_USE_INTERNAL to use the + * @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use the * the hardware device tree as indicated by environment variable * fdt_addr or as fallback the internal device tree as indicated by * the environment variable fdtcontroladdr @@ -258,9 +286,6 @@ efi_status_t efi_install_fdt(void *fdt) return EFI_LOAD_ERROR; } - /* Create memory reservations as indicated by the device tree */ - efi_carve_out_dt_rsv(fdt); - /* Prepare device tree for payload */ ret = copy_fdt(&fdt); if (ret) { @@ -273,6 +298,9 @@ efi_status_t efi_install_fdt(void *fdt) return EFI_LOAD_ERROR; } + /* Create memory reservations as indicated by the device tree */ + efi_carve_out_dt_rsv(fdt); + /* Install device tree as UEFI table */ ret = efi_install_configuration_table(&efi_guid_fdt, fdt); if (ret != EFI_SUCCESS) { @@ -298,9 +326,10 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle) efi_status_t ret; efi_uintn_t exit_data_size = 0; u16 *exit_data = NULL; + u16 *load_options; /* Transfer environment variable as load options */ - ret = set_load_options(handle, "bootargs"); + ret = set_load_options(handle, "bootargs", &load_options); if (ret != EFI_SUCCESS) return ret; @@ -314,12 +343,7 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle) efi_restore_gd(); - /* - * FIXME: Who is responsible for - * free(loaded_image_info->load_options); - * Once efi_exit() is implemented correctly, - * handle itself doesn't exist here. - */ + free(load_options); return ret; } @@ -454,10 +478,8 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) ret = do_bootefi_exec(handle); out: - if (mem_handle) - efi_delete_handle(mem_handle); - if (file_path) - efi_free_pool(file_path); + efi_delete_handle(mem_handle); + efi_free_pool(file_path); return ret; } @@ -469,6 +491,7 @@ static efi_status_t bootefi_run_prepare(const char *load_options_path, struct efi_loaded_image **loaded_image_infop) { efi_status_t ret; + u16 *load_options; ret = efi_setup_loaded_image(device_path, image_path, image_objp, loaded_image_infop); @@ -476,7 +499,8 @@ static efi_status_t bootefi_run_prepare(const char *load_options_path, return ret; /* Transfer environment variable as load options */ - return set_load_options((efi_handle_t)*image_objp, load_options_path); + return set_load_options((efi_handle_t)*image_objp, load_options_path, + &load_options); } /** @@ -571,7 +595,8 @@ static int do_efi_selftest(void) * @argv: command line arguments * Return: status code */ -static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) { efi_status_t ret; void *fdt;