diff options
-rw-r--r-- | cmd/bootefi.c | 75 | ||||
-rw-r--r-- | cmd/efidebug.c | 4 | ||||
-rw-r--r-- | include/efi_loader.h | 5 | ||||
-rw-r--r-- | lib/crypto/public_key.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 70 | ||||
-rw-r--r-- | lib/efi_loader/efi_var_common.c | 1 |
6 files changed, 97 insertions, 62 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 8154efde52..fbfed54e85 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -31,55 +31,37 @@ static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; /** - * Set the load options of an image from an environment variable. + * efi_env_set_load_options() - set load options from environment variable * * @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, - u16 **load_options) +static efi_status_t efi_env_set_load_options(efi_handle_t handle, + const char *env_var, + u16 **load_options) { - struct efi_loaded_image *loaded_image_info; - size_t size; const char *env = env_get(env_var); + size_t size; u16 *pos; efi_status_t ret; *load_options = NULL; - ret = EFI_CALL(systab.boottime->open_protocol( - handle, - &efi_guid_loaded_image, - (void **)&loaded_image_info, - efi_root, NULL, - EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)); - if (ret != EFI_SUCCESS) - return EFI_INVALID_PARAMETER; - - loaded_image_info->load_options = NULL; - loaded_image_info->load_options_size = 0; if (!env) - goto out; - - size = utf8_utf16_strlen(env) + 1; - loaded_image_info->load_options = calloc(size, sizeof(u16)); - if (!loaded_image_info->load_options) { - log_err("ERROR: Out of memory\n"); - EFI_CALL(systab.boottime->close_protocol(handle, - &efi_guid_loaded_image, - efi_root, NULL)); + return EFI_SUCCESS; + size = sizeof(u16) * (utf8_utf16_strlen(env) + 1); + pos = calloc(size, 1); + if (!pos) 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; - -out: - return EFI_CALL(systab.boottime->close_protocol(handle, - &efi_guid_loaded_image, - efi_root, NULL)); + ret = efi_set_load_options(handle, size, *load_options); + if (ret != EFI_SUCCESS) { + free(*load_options); + *load_options = NULL; + } + return ret; } #if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) @@ -328,17 +310,11 @@ efi_status_t efi_install_fdt(void *fdt) * Load the EFI binary into a newly assigned memory unwinding the relocation * information, install the loaded image protocol, and call the binary. */ -static efi_status_t do_bootefi_exec(efi_handle_t handle) +static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options) { 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", &load_options); - if (ret != EFI_SUCCESS) - return ret; /* Call our payload! */ ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data)); @@ -367,14 +343,15 @@ static int do_efibootmgr(void) { efi_handle_t handle; efi_status_t ret; + void *load_options; - ret = efi_bootmgr_load(&handle); + ret = efi_bootmgr_load(&handle, &load_options); if (ret != EFI_SUCCESS) { log_notice("EFI boot manager: Cannot load any image\n"); return CMD_RET_FAILURE; } - ret = do_bootefi_exec(handle); + ret = do_bootefi_exec(handle, load_options); if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; @@ -485,7 +462,14 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) if (ret != EFI_SUCCESS) goto out; - ret = do_bootefi_exec(handle); + u16 *load_options; + + /* Transfer environment variable as load options */ + ret = efi_env_set_load_options(handle, "bootargs", &load_options); + if (ret != EFI_SUCCESS) + goto out; + + ret = do_bootefi_exec(handle, load_options); out: efi_delete_handle(mem_handle); @@ -509,8 +493,9 @@ 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, - &load_options); + return efi_env_set_load_options((efi_handle_t)*image_objp, + load_options_path, + &load_options); } /** diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 58018f700c..d00d4247dc 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1126,8 +1126,9 @@ static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, efi_uintn_t exit_data_size = 0; u16 *exit_data = NULL; efi_status_t ret; + void *load_options; - ret = efi_bootmgr_load(&image); + ret = efi_bootmgr_load(&image, &load_options); printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK); /* We call efi_start_image() even if error for test purpose. */ @@ -1138,6 +1139,7 @@ static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, efi_restore_gd(); + free(load_options); return CMD_RET_SUCCESS; } diff --git a/include/efi_loader.h b/include/efi_loader.h index 98944640be..7f0ab1be56 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -717,7 +717,10 @@ struct efi_load_option { efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, efi_uintn_t *size); unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data); -efi_status_t efi_bootmgr_load(efi_handle_t *handle); +efi_status_t efi_set_load_options(efi_handle_t handle, + efi_uintn_t load_options_size, + void *load_options); +efi_status_t efi_bootmgr_load(efi_handle_t *handle, void **load_options); /** * efi_image_regions - A list of memory regions diff --git a/lib/crypto/public_key.c b/lib/crypto/public_key.c index a8f7fbed45..df6033cdb4 100644 --- a/lib/crypto/public_key.c +++ b/lib/crypto/public_key.c @@ -97,7 +97,6 @@ int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { struct image_sign_info info; - struct image_region region; int ret; pr_devel("==>%s()\n", __func__); @@ -137,9 +136,6 @@ int public_key_verify_signature(const struct public_key *pkey, info.key = pkey->key; info.keylen = pkey->keylen; - region.data = sig->digest; - region.size = sig->digest_size; - if (rsa_verify_with_pkey(&info, sig->digest, sig->s, sig->s_size)) ret = -EKEYREJECTED; else diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index e03198b57a..1e06e60963 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -30,6 +30,38 @@ static const struct efi_runtime_services *rs; * should do normal or recovery boot. */ +/** + * efi_set_load_options() - set the load options of a loaded image + * + * @handle: the image handle + * @load_options_size: size of load options + * @load_options: pointer to load options + * Return: status code + */ +efi_status_t efi_set_load_options(efi_handle_t handle, + efi_uintn_t load_options_size, + void *load_options) +{ + struct efi_loaded_image *loaded_image_info; + efi_status_t ret; + + ret = EFI_CALL(systab.boottime->open_protocol( + handle, + &efi_guid_loaded_image, + (void **)&loaded_image_info, + efi_root, NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)); + if (ret != EFI_SUCCESS) + return EFI_INVALID_PARAMETER; + + loaded_image_info->load_options = load_options; + loaded_image_info->load_options_size = load_options_size; + + return EFI_CALL(systab.boottime->close_protocol(handle, + &efi_guid_loaded_image, + efi_root, NULL)); +} + /** * efi_deserialize_load_option() - parse serialized data @@ -174,11 +206,13 @@ static void *get_var(u16 *name, const efi_guid_t *vendor, * if successful. This checks that the EFI_LOAD_OPTION is active (enabled) * and that the specified file to boot exists. * - * @n: number of the boot option, e.g. 0x0a13 for Boot0A13 - * @handle: on return handle for the newly installed image - * Return: status code + * @n: number of the boot option, e.g. 0x0a13 for Boot0A13 + * @handle: on return handle for the newly installed image + * @load_options: load options set on the loaded image protocol + * Return: status code */ -static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) +static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, + void **load_options) { struct efi_load_option lo; u16 varname[] = L"Boot0000"; @@ -218,10 +252,9 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; - size = sizeof(n); ret = efi_set_variable_int(L"BootCurrent", &efi_global_variable_guid, - attributes, size, &n, false); + attributes, sizeof(n), &n, false); if (ret != EFI_SUCCESS) { if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS) @@ -234,6 +267,19 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) ret = EFI_LOAD_ERROR; } + /* Set load options */ + if (size) { + *load_options = malloc(size); + if (!*load_options) { + ret = EFI_OUT_OF_RESOURCES; + goto error; + } + memcpy(*load_options, lo.optional_data, size); + ret = efi_set_load_options(*handle, size, *load_options); + } else { + load_options = NULL; + } + error: free(load_option); @@ -247,10 +293,11 @@ error: * EFI variable, the available load-options, finding and returning * the first one that can be loaded successfully. * - * @handle: on return handle for the newly installed image - * Return: status code + * @handle: on return handle for the newly installed image + * @load_options: load options set on the loaded image protocol + * Return: status code */ -efi_status_t efi_bootmgr_load(efi_handle_t *handle) +efi_status_t efi_bootmgr_load(efi_handle_t *handle, void **load_options) { u16 bootnext, *bootorder; efi_uintn_t size; @@ -278,7 +325,8 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) /* load BootNext */ if (ret == EFI_SUCCESS) { if (size == sizeof(u16)) { - ret = try_load_entry(bootnext, handle); + ret = try_load_entry(bootnext, handle, + load_options); if (ret == EFI_SUCCESS) return ret; log_warning( @@ -301,7 +349,7 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) for (i = 0; i < num; i++) { log_debug("%s trying to load Boot%04X\n", __func__, bootorder[i]); - ret = try_load_entry(bootorder[i], handle); + ret = try_load_entry(bootorder[i], handle, load_options); if (ret == EFI_SUCCESS) break; } diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index 453cbce5c8..1c7459266a 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -3,6 +3,7 @@ * UEFI runtime variable services * * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> + * Copyright (c) 2020 Linaro Limited, Author: AKASHI Takahiro */ #include <common.h> |