X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=cmd%2Fbootefi.c;h=f55a40dc84cd05dc2f3cbb39583f9c70f7e5a68c;hb=a1b73c18724eb8cb75f7a60d851578d933c78095;hp=d20775eccd99c709aab87c20c21afad6f91bcf22;hpb=2218b32d88f9b4b4484cea9a8b034ddab0be298b;p=u-boot diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d20775eccd..f55a40dc84 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -1,141 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * EFI application loader * * Copyright (c) 2016 Alexander Graf - * - * SPDX-License-Identifier: GPL-2.0+ */ +#include #include #include #include #include +#include #include -#include -#include +#include +#include #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; -static uint8_t efi_obj_list_initalized; +#define OBJ_LIST_NOT_INITIALIZED 1 -/* - * When booting using the "bootefi" command, we don't know which - * physical device the file came from. So we create a pseudo-device - * called "bootefi" with the device path /bootefi. - * - * In addition to the originating device we also declare the file path - * of "bootefi" based loads to be /bootefi. - */ -static struct efi_device_path_file_path bootefi_image_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -static struct efi_device_path_file_path bootefi_device_path[] = { - { - .dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH, - .dp.length = sizeof(bootefi_image_path[0]), - .str = { 'b','o','o','t','e','f','i' }, - }, { - .dp.type = DEVICE_PATH_TYPE_END, - .dp.sub_type = DEVICE_PATH_SUB_TYPE_END, - .dp.length = sizeof(bootefi_image_path[0]), - } -}; - -/* The EFI loaded_image interface for the image executed via "bootefi" */ -static struct efi_loaded_image loaded_image_info = { - .device_handle = bootefi_device_path, - .file_path = bootefi_image_path, -}; - -/* The EFI object struct for the image executed via "bootefi" */ -static struct efi_object loaded_image_info_obj = { - .handle = &loaded_image_info, - .protocols = { - { - /* - * When asking for the loaded_image interface, just - * return handle which points to loaded_image_info - */ - .guid = &efi_guid_loaded_image, - .protocol_interface = &loaded_image_info, - }, - { - /* - * When asking for the device path interface, return - * bootefi_device_path - */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path, - }, - { - .guid = &efi_guid_console_control, - .protocol_interface = (void *) &efi_console_control - }, - { - .guid = &efi_guid_device_path_to_text_protocol, - .protocol_interface = (void *) &efi_device_path_to_text - }, - }, -}; - -/* The EFI object struct for the device the "bootefi" image was loaded from */ -static struct efi_object bootefi_device_obj = { - .handle = bootefi_device_path, - .protocols = { - { - /* When asking for the device path interface, return - * bootefi_device_path */ - .guid = &efi_guid_device_path, - .protocol_interface = bootefi_device_path - } - }, -}; +static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; + +static struct efi_device_path *bootefi_image_path; +static struct efi_device_path *bootefi_device_path; /* Initialize and populate EFI object list */ -static void efi_init_obj_list(void) +efi_status_t efi_init_obj_list(void) { - efi_obj_list_initalized = 1; + efi_status_t ret = EFI_SUCCESS; - list_add_tail(&loaded_image_info_obj.link, &efi_obj_list); - list_add_tail(&bootefi_device_obj.link, &efi_obj_list); - efi_console_register(); + /* Initialize once only */ + if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) + return efi_obj_list_initialized; + + /* Initialize EFI driver uclass */ + ret = efi_driver_init(); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_console_register(); + if (ret != EFI_SUCCESS) + goto out; #ifdef CONFIG_PARTITIONS - efi_disk_register(); + ret = efi_disk_register(); + if (ret != EFI_SUCCESS) + goto out; #endif #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) - efi_gop_register(); + ret = efi_gop_register(); + if (ret != EFI_SUCCESS) + goto out; #endif #ifdef CONFIG_NET - void *nethandle = loaded_image_info.device_handle; - efi_net_register(&nethandle); - - if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) - loaded_image_info.device_handle = nethandle; - else - loaded_image_info.device_handle = bootefi_device_path; + ret = efi_net_register(); + if (ret != EFI_SUCCESS) + goto out; #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE - efi_smbios_register(); + ret = efi_smbios_register(); + if (ret != EFI_SUCCESS) + goto out; #endif + ret = efi_watchdog_register(); + if (ret != EFI_SUCCESS) + goto out; /* Initialize EFI runtime services */ - efi_reset_system_init(); - efi_get_time_init(); + ret = efi_reset_system_init(); + if (ret != EFI_SUCCESS) + goto out; + ret = efi_get_time_init(); + if (ret != EFI_SUCCESS) + goto out; + +out: + efi_obj_list_initialized = ret; + return ret; +} + +/* + * Allow unaligned memory access. + * + * This routine is overridden by architectures providing this feature. + */ +void __weak allow_unaligned(void) +{ +} + +/* + * Set the load options of an image from an environment variable. + * + * @loaded_image_info: the image + * @env_var: name of the environment variable + */ +static void set_load_options(struct efi_loaded_image *loaded_image_info, + const char *env_var) +{ + size_t size; + const char *env = env_get(env_var); + + loaded_image_info->load_options = NULL; + loaded_image_info->load_options_size = 0; + if (!env) + return; + size = strlen(env) + 1; + loaded_image_info->load_options = calloc(size, sizeof(u16)); + if (!loaded_image_info->load_options) { + printf("ERROR: Out of memory\n"); + return; + } + utf8_to_utf16(loaded_image_info->load_options, (u8 *)env, size); + loaded_image_info->load_options_size = size * 2; } static void *copy_fdt(void *fdt) @@ -158,16 +138,18 @@ static void *copy_fdt(void *fdt) } /* Give us at least 4kb breathing room */ - fdt_size = ALIGN(fdt_size + 4096, 4096); + fdt_size = ALIGN(fdt_size + 4096, EFI_PAGE_SIZE); fdt_pages = fdt_size >> EFI_PAGE_SHIFT; /* Safe fdt location is at 128MB */ new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size; - if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages, + if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, + EFI_RUNTIME_SERVICES_DATA, fdt_pages, &new_fdt_addr) != EFI_SUCCESS) { /* If we can't put it there, put it somewhere */ - new_fdt_addr = (ulong)memalign(4096, fdt_size); - if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages, + new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); + if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, + EFI_RUNTIME_SERVICES_DATA, fdt_pages, &new_fdt_addr) != EFI_SUCCESS) { printf("ERROR: Failed to reserve space for FDT\n"); return NULL; @@ -181,9 +163,10 @@ static void *copy_fdt(void *fdt) return new_fdt; } -static ulong efi_do_enter(void *image_handle, - struct efi_system_table *st, - asmlinkage ulong (*entry)(void *image_handle, +static efi_status_t efi_do_enter( + efi_handle_t image_handle, struct efi_system_table *st, + EFIAPI efi_status_t (*entry)( + efi_handle_t image_handle, struct efi_system_table *st)) { efi_status_t ret = EFI_LOAD_ERROR; @@ -195,9 +178,9 @@ static ulong efi_do_enter(void *image_handle, } #ifdef CONFIG_ARM64 -static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( - void *image_handle, struct efi_system_table *st), - void *image_handle, struct efi_system_table *st) +static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)( + efi_handle_t image_handle, struct efi_system_table *st), + efi_handle_t image_handle, struct efi_system_table *st) { /* Enable caches again */ dcache_enable(); @@ -206,17 +189,109 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( } #endif +/* Carve out DT reserved memory ranges */ +static efi_status_t efi_carve_out_dt_rsv(void *fdt) +{ + int nr_rsv, i; + uint64_t addr, size, pages; + + nr_rsv = fdt_num_mem_rsv(fdt); + + /* Look for an existing entry and add it to the efi mem map. */ + for (i = 0; i < nr_rsv; i++) { + if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) + continue; + + pages = ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT; + efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, + false); + } + + return EFI_SUCCESS; +} + +static efi_status_t efi_install_fdt(void *fdt) +{ + bootm_headers_t img = { 0 }; + ulong fdt_pages, fdt_size, fdt_start, fdt_end; + efi_status_t ret; + + if (fdt_check_header(fdt)) { + printf("ERROR: invalid device tree\n"); + return EFI_INVALID_PARAMETER; + } + + /* Prepare fdt for payload */ + fdt = copy_fdt(fdt); + if (!fdt) + return EFI_OUT_OF_RESOURCES; + + if (image_setup_libfdt(&img, fdt, 0, NULL)) { + printf("ERROR: failed to process device tree\n"); + return EFI_LOAD_ERROR; + } + + if (efi_carve_out_dt_rsv(fdt) != EFI_SUCCESS) { + printf("ERROR: failed to carve out memory\n"); + return EFI_LOAD_ERROR; + } + + /* Link to it in the efi tables */ + ret = efi_install_configuration_table(&efi_guid_fdt, fdt); + if (ret != EFI_SUCCESS) + return EFI_OUT_OF_RESOURCES; + + /* And reserve the space in the memory map */ + 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; + ret = efi_add_memory_map(fdt_start, fdt_pages, + EFI_BOOT_SERVICES_DATA, true); + return ret; +} + /* * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. */ -static unsigned long do_bootefi_exec(void *efi, void *fdt) +static efi_status_t do_bootefi_exec(void *efi, + struct efi_device_path *device_path, + struct efi_device_path *image_path) { - ulong (*entry)(void *image_handle, struct efi_system_table *st) - asmlinkage; - ulong fdt_pages, fdt_size, fdt_start, fdt_end; - const efi_guid_t fdt_guid = EFI_FDT_GUID; - bootm_headers_t img = { 0 }; + struct efi_loaded_image loaded_image_info = {}; + struct efi_object loaded_image_info_obj = {}; + struct efi_object mem_obj = {}; + struct efi_device_path *memdp = NULL; + efi_status_t ret; + + EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, + struct efi_system_table *st); + + /* + * Special case for efi payload not loaded from disk, such as + * 'bootefi hello' or for example payload loaded directly into + * memory via jtag/etc: + */ + if (!device_path && !image_path) { + printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); + /* actual addresses filled in after efi_load_pe() */ + memdp = efi_dp_from_mem(0, 0, 0); + device_path = image_path = memdp; + efi_add_handle(&mem_obj); + + ret = efi_add_protocol(mem_obj.handle, &efi_guid_device_path, + device_path); + if (ret != EFI_SUCCESS) + goto exit; + } else { + assert(device_path && image_path); + } + + efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, + device_path, image_path); /* * gd lives in a fixed register which may get clobbered while we execute @@ -224,46 +299,33 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) */ efi_save_gd(); - if (fdt && !fdt_check_header(fdt)) { - /* Prepare fdt for payload */ - 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 */ - efi_install_configuration_table(&fdt_guid, fdt); - - /* And reserve the space in the memory map */ - 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: Invalid device tree, expect boot to fail\n"); - efi_install_configuration_table(&fdt_guid, NULL); - } - + /* Transfer environment variable bootargs as load options */ + set_load_options(&loaded_image_info, "bootargs"); /* Load the EFI payload */ entry = efi_load_pe(efi, &loaded_image_info); - if (!entry) - return -ENOENT; + if (!entry) { + ret = EFI_LOAD_ERROR; + goto exit; + } + + if (memdp) { + struct efi_device_path_memory *mdp = (void *)memdp; + mdp->memory_type = loaded_image_info.image_code_type; + mdp->start_address = (uintptr_t)loaded_image_info.image_base; + mdp->end_address = mdp->start_address + + loaded_image_info.image_size; + } - /* Initialize and populate EFI object list */ - if (!efi_obj_list_initalized) - efi_init_obj_list(); + /* we don't support much: */ + env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported", + "{ro,boot}(blob)0000000000000000"); /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); if (setjmp(&loaded_image_info.exit_jmp)) { - return loaded_image_info.exit_status; + ret = loaded_image_info.exit_status; + goto exit; } #ifdef CONFIG_ARM64 @@ -273,7 +335,8 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) dcache_disable(); /* flush cache before switch to EL2 */ /* Move into EL2 and keep running there */ - armv8_switch_to_el2((ulong)entry, (ulong)&loaded_image_info, + armv8_switch_to_el2((ulong)entry, + (ulong)&loaded_image_info_obj.handle, (ulong)&systab, 0, (ulong)efi_run_in_el2, ES_TO_AARCH64); @@ -282,40 +345,138 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) } #endif - return efi_do_enter(&loaded_image_info, &systab, entry); + ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry); + +exit: + /* image has returned, loaded-image obj goes *poof*: */ + list_del(&loaded_image_info_obj.link); + if (mem_obj.handle) + list_del(&mem_obj.link); + + return ret; } +static int do_bootefi_bootmgr_exec(void) +{ + struct efi_device_path *device_path, *file_path; + void *addr; + efi_status_t r; + + /* + * gd lives in a fixed register which may get clobbered while we execute + * the payload. So save it here and restore it on every callback entry + */ + efi_save_gd(); + + addr = efi_bootmgr_load(&device_path, &file_path); + if (!addr) + return 1; + + printf("## Starting EFI application at %p ...\n", addr); + r = do_bootefi_exec(addr, device_path, file_path); + printf("## Application terminated, r = %lu\n", + r & ~EFI_ERROR_MASK); + + if (r != EFI_SUCCESS) + return 1; + + return 0; +} /* Interpreter command to boot an arbitrary EFI image from memory */ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *saddr, *sfdt; - unsigned long addr, fdt_addr = 0; - unsigned long r; + unsigned long addr; + char *saddr; + efi_status_t r; + void *fdt_addr; + + /* Allow unaligned memory access */ + allow_unaligned(); + + /* Initialize EFI drivers */ + r = efi_init_obj_list(); + if (r != EFI_SUCCESS) { + printf("Error: Cannot set up EFI drivers, r = %lu\n", + r & ~EFI_ERROR_MASK); + return CMD_RET_FAILURE; + } if (argc < 2) return CMD_RET_USAGE; + + if (argc > 2) { + fdt_addr = (void *)simple_strtoul(argv[2], NULL, 16); + if (!fdt_addr && *argv[2] != '0') + return CMD_RET_USAGE; + /* Install device tree */ + r = efi_install_fdt(fdt_addr); + if (r != EFI_SUCCESS) { + printf("ERROR: failed to install device tree\n"); + return CMD_RET_FAILURE; + } + } else { + /* Remove device tree. EFI_NOT_FOUND can be ignored here */ + efi_install_configuration_table(&efi_guid_fdt, NULL); + printf("WARNING: booting without device tree\n"); + } #ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp(argv[1], "hello")) { - ulong size = __efi_hello_world_end - __efi_hello_world_begin; - - addr = CONFIG_SYS_LOAD_ADDR; - memcpy((char *)addr, __efi_hello_world_begin, size); + ulong size = __efi_helloworld_end - __efi_helloworld_begin; + + saddr = env_get("loadaddr"); + if (saddr) + addr = simple_strtoul(saddr, NULL, 16); + else + addr = CONFIG_SYS_LOAD_ADDR; + memcpy((char *)addr, __efi_helloworld_begin, size); + } else +#endif +#ifdef CONFIG_CMD_BOOTEFI_SELFTEST + if (!strcmp(argv[1], "selftest")) { + struct efi_loaded_image loaded_image_info = {}; + struct efi_object loaded_image_info_obj = {}; + + /* Construct a dummy device path. */ + bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)&efi_selftest, + (uintptr_t)&efi_selftest); + bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); + + efi_setup_loaded_image(&loaded_image_info, + &loaded_image_info_obj, + bootefi_device_path, bootefi_image_path); + /* + * gd lives in a fixed register which may get clobbered while we + * execute the payload. So save it here and restore it on every + * callback entry + */ + efi_save_gd(); + /* Transfer environment variable efi_selftest as load options */ + set_load_options(&loaded_image_info, "efi_selftest"); + /* Execute the test */ + r = efi_selftest(loaded_image_info_obj.handle, &systab); + efi_restore_gd(); + free(loaded_image_info.load_options); + list_del(&loaded_image_info_obj.link); + return r != EFI_SUCCESS; } else #endif - { + if (!strcmp(argv[1], "bootmgr")) { + return do_bootefi_bootmgr_exec(); + } else { saddr = argv[1]; addr = simple_strtoul(saddr, NULL, 16); + /* Check that a numeric value was passed */ + if (!addr && *saddr != '0') + return CMD_RET_USAGE; - if (argc > 2) { - sfdt = argv[2]; - fdt_addr = simple_strtoul(sfdt, NULL, 16); - } } printf("## Starting EFI application at %08lx ...\n", addr); - r = do_bootefi_exec((void *)addr, (void*)fdt_addr); + r = do_bootefi_exec((void *)addr, bootefi_device_path, + bootefi_image_path); printf("## Application terminated, r = %lu\n", r & ~EFI_ERROR_MASK); @@ -332,10 +493,20 @@ static char bootefi_help_text[] = " If specified, the device tree located at gets\n" " exposed as EFI configuration table.\n" #ifdef CONFIG_CMD_BOOTEFI_HELLO - "hello\n" - " - boot a sample Hello World application stored within U-Boot" + "bootefi hello\n" + " - boot a sample Hello World application stored within U-Boot\n" +#endif +#ifdef CONFIG_CMD_BOOTEFI_SELFTEST + "bootefi selftest [fdt address]\n" + " - boot an EFI selftest application stored within U-Boot\n" + " Use environment variable efi_selftest to select a single test.\n" + " Use 'setenv efi_selftest list' to enumerate all tests.\n" #endif - ; + "bootefi bootmgr [fdt addr]\n" + " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" + "\n" + " If specified, the device tree located at gets\n" + " exposed as EFI configuration table.\n"; #endif U_BOOT_CMD( @@ -346,56 +517,38 @@ U_BOOT_CMD( void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { - __maybe_unused struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - char *colon, *s; - -#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION) - desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); -#endif - -#ifdef CONFIG_BLK - if (desc) { - snprintf(devname, sizeof(devname), "%s", desc->bdev->name); - } else -#endif - - { - /* Assemble the condensed device name we use in efi_disk.c */ - snprintf(devname, sizeof(devname), "%s%s", dev, devnr); - } + char filename[32] = { 0 }; /* dp->str is u16[32] long */ + char *s; - colon = strchr(devname, ':'); + if (strcmp(dev, "Net")) { + struct blk_desc *desc; + disk_partition_t fs_partition; + int part; -#if CONFIG_IS_ENABLED(ISO_PARTITION) - /* For ISOs we create partition block devices */ - if (desc && (desc->type != DEV_TYPE_UNKNOWN) && - (desc->part_type == PART_TYPE_ISO)) { - if (!colon) - snprintf(devname, sizeof(devname), "%s:1", devname); + part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition, + 1); + if (part < 0) + return; - colon = NULL; - } + bootefi_device_path = efi_dp_from_part(desc, part); + } else { +#ifdef CONFIG_NET + bootefi_device_path = efi_dp_from_eth(); #endif + } - if (colon) - *colon = '\0'; - - /* Patch bootefi_device_path to the target device */ - memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str)); - ascii2unicode(bootefi_device_path[0].str, devname); + if (!path) + return; - /* Patch bootefi_image_path to the target file path */ - memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str)); if (strcmp(dev, "Net")) { /* Add leading / to fs paths, because they're absolute */ - snprintf(devname, sizeof(devname), "/%s", path); + snprintf(filename, sizeof(filename), "/%s", path); } else { - snprintf(devname, sizeof(devname), "%s", path); + snprintf(filename, sizeof(filename), "%s", path); } /* DOS style file path: */ - s = devname; + s = filename; while ((s = strchr(s, '/'))) *s++ = '\\'; - ascii2unicode(bootefi_image_path[0].str, devname); + bootefi_image_path = efi_dp_from_file(NULL, 0, filename); }