diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 111 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 6 | ||||
-rw-r--r-- | lib/efi_loader/efi_load_initrd.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_var_common.c | 6 | ||||
-rw-r--r-- | lib/efi_loader/efi_var_mem.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 25 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable_tee.c | 5 | ||||
-rw-r--r-- | lib/efi_selftest/Makefile | 1 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_variables.c | 13 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_variables_common.c | 102 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_variables_runtime.c | 19 |
13 files changed, 213 insertions, 85 deletions
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 4ac519228a6..7da3139f917 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -613,9 +613,12 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, void *load_option; efi_uintn_t size; efi_status_t ret; + u32 attributes; - efi_create_indexed_name(varname, sizeof(varname), "Boot", n); + *handle = NULL; + *load_options = NULL; + efi_create_indexed_name(varname, sizeof(varname), "Boot", n); load_option = efi_get_var(varname, &efi_global_variable_guid, &size); if (!load_option) return EFI_LOAD_ERROR; @@ -626,55 +629,54 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, goto error; } - if (lo.attributes & LOAD_OPTION_ACTIVE) { - u32 attributes; - - log_debug("trying to load \"%ls\" from %pD\n", lo.label, - lo.file_path); - - if (EFI_DP_TYPE(lo.file_path, MEDIA_DEVICE, FILE_PATH)) { - /* file_path doesn't contain a device path */ - ret = try_load_from_short_path(lo.file_path, handle); - } else if (EFI_DP_TYPE(lo.file_path, MESSAGING_DEVICE, MSG_URI)) { - if (IS_ENABLED(CONFIG_EFI_HTTP_BOOT)) - ret = try_load_from_uri_path( - (struct efi_device_path_uri *)lo.file_path, - lo.label, handle); - else - ret = EFI_LOAD_ERROR; - } else { - ret = try_load_from_media(lo.file_path, handle); - } - if (ret != EFI_SUCCESS) { - log_warning("Loading %ls '%ls' failed\n", - varname, lo.label); - goto error; - } + if (!(lo.attributes & LOAD_OPTION_ACTIVE)) { + ret = EFI_LOAD_ERROR; + goto error; + } - attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS; - ret = efi_set_variable_int(u"BootCurrent", - &efi_global_variable_guid, - attributes, sizeof(n), &n, false); - if (ret != EFI_SUCCESS) - goto unload; - /* try to register load file2 for initrd's */ - if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) { - ret = efi_initrd_register(); - if (ret != EFI_SUCCESS) - goto unload; - } + log_debug("trying to load \"%ls\" from %pD\n", lo.label, lo.file_path); - log_info("Booting: %ls\n", lo.label); + if (EFI_DP_TYPE(lo.file_path, MEDIA_DEVICE, FILE_PATH)) { + /* file_path doesn't contain a device path */ + ret = try_load_from_short_path(lo.file_path, handle); + } else if (EFI_DP_TYPE(lo.file_path, MESSAGING_DEVICE, MSG_URI)) { + if (IS_ENABLED(CONFIG_EFI_HTTP_BOOT)) + ret = try_load_from_uri_path( + (struct efi_device_path_uri *)lo.file_path, + lo.label, handle); + else + ret = EFI_LOAD_ERROR; } else { - ret = EFI_LOAD_ERROR; + ret = try_load_from_media(lo.file_path, handle); + } + if (ret != EFI_SUCCESS) { + log_warning("Loading %ls '%ls' failed\n", + varname, lo.label); + goto error; + } + + attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS; + ret = efi_set_variable_int(u"BootCurrent", &efi_global_variable_guid, + attributes, sizeof(n), &n, false); + if (ret != EFI_SUCCESS) + goto error; + + /* try to register load file2 for initrd's */ + if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) { + ret = efi_initrd_register(); + if (ret != EFI_SUCCESS) + goto error; } - /* Set load options */ + log_info("Booting: %ls\n", lo.label); + + /* Ignore the optional data in auto-generated boot options */ if (size >= sizeof(efi_guid_t) && !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) size = 0; + /* Set optional data in loaded file protocol */ if (size) { *load_options = malloc(size); if (!*load_options) { @@ -683,18 +685,15 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, } memcpy(*load_options, lo.optional_data, size); ret = efi_set_load_options(*handle, size, *load_options); - } else { - *load_options = NULL; + if (ret != EFI_SUCCESS) + free(load_options); } error: - free(load_option); - - return ret; - -unload: - if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS) + if (ret != EFI_SUCCESS && *handle && + EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS) log_err("Unloading image failed\n"); + free(load_option); return ret; @@ -1210,15 +1209,21 @@ efi_status_t efi_bootmgr_run(void *fdt) return CMD_RET_FAILURE; } - ret = efi_install_fdt(fdt); - if (ret != EFI_SUCCESS) - return ret; - ret = efi_bootmgr_load(&handle, &load_options); if (ret != EFI_SUCCESS) { log_notice("EFI boot manager: Cannot load any image\n"); return ret; } + ret = efi_install_fdt(fdt); + if (ret != EFI_SUCCESS) { + if (EFI_CALL(efi_unload_image(handle)) == EFI_SUCCESS) + free(load_options); + else + log_err("Unloading image failed\n"); + + return ret; + } + return do_bootefi_exec(handle, load_options); } diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 46aa59b9e40..aec224d8466 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -102,7 +102,7 @@ int efi_dp_match(const struct efi_device_path *a, * See UEFI spec, section 3.1.2 for "short-form device path". * * @dp: original device-path - * @Return: shortened device-path or NULL + * Return: shortened device-path or NULL */ struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp) { diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 6918fd5e48a..73d0279e843 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -72,7 +72,7 @@ out: * * Return: device path or NULL. Caller must free the returned value */ -struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) +struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t *guid) { struct efi_load_option lo; void *var_value; @@ -92,7 +92,7 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) if (ret != EFI_SUCCESS) goto err; - return efi_dp_from_lo(&lo, &guid); + return efi_dp_from_lo(&lo, guid); err: free(var_value); @@ -544,8 +544,6 @@ efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options) } } - efi_restore_gd(); - out: free(load_options); diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index 67d1f75d525..d91135436c4 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -63,7 +63,7 @@ static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp) * We can then use this specific return value and not install the * protocol, while allowing the boot to continue */ - dp = efi_get_dp_from_boot(efi_lf2_initrd_guid); + dp = efi_get_dp_from_boot(&efi_lf2_initrd_guid); if (!dp) return EFI_INVALID_PARAMETER; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 73831c527e0..011bcd04836 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -129,6 +129,10 @@ efi_status_t efi_init_runtime_supported(void) EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP | EFI_RT_SUPPORTED_CONVERT_POINTER; + if (IS_ENABLED(CONFIG_EFI_VARIABLE_FILE_STORE)) + rt_table->runtime_services_supported |= + EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO; + if (IS_ENABLED(CONFIG_EFI_RT_VOLATILE_STORE)) { u8 s = 0; diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index 961139f005a..ea8d2a4cf98 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: GPL-2.0+ /* * UEFI runtime variable services * @@ -163,11 +162,6 @@ efi_status_t EFIAPI efi_query_variable_info( EFI_ENTRY("%x %p %p %p", attributes, maximum_variable_storage_size, remaining_variable_storage_size, maximum_variable_size); - if (!maximum_variable_storage_size || - !remaining_variable_storage_size || - !maximum_variable_size) - return EFI_EXIT(EFI_INVALID_PARAMETER); - ret = efi_query_variable_info_int(attributes, maximum_variable_storage_size, remaining_variable_storage_size, diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index 940ab663882..139e16aad7c 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -232,8 +232,6 @@ efi_status_t efi_var_mem_init(void) efi_var_buf->length = (uintptr_t)efi_var_buf->var - (uintptr_t)efi_var_buf; - if (ret != EFI_SUCCESS) - return ret; ret = efi_create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, TPL_CALLBACK, efi_var_mem_notify_virtual_address_map, NULL, NULL, &event); diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 0cbed53d1db..1cc02acb3b2 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -406,12 +406,15 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, return EFI_SUCCESS; } -efi_status_t efi_query_variable_info_int(u32 attributes, - u64 *maximum_variable_storage_size, - u64 *remaining_variable_storage_size, - u64 *maximum_variable_size) +efi_status_t __efi_runtime +efi_query_variable_info_int(u32 attributes, + u64 *maximum_variable_storage_size, + u64 *remaining_variable_storage_size, + u64 *maximum_variable_size) { - if (attributes == 0) + if (!maximum_variable_storage_size || + !remaining_variable_storage_size || + !maximum_variable_size || !attributes) return EFI_INVALID_PARAMETER; /* EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is deprecated */ @@ -460,7 +463,17 @@ static efi_status_t __efi_runtime EFIAPI efi_query_variable_info_runtime( u64 *remaining_variable_storage_size, u64 *maximum_variable_size) { - return EFI_UNSUPPORTED; + if (!(attributes & EFI_VARIABLE_RUNTIME_ACCESS)) + return EFI_INVALID_PARAMETER; + if ((attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | + EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS))) + return EFI_UNSUPPORTED; + + return efi_query_variable_info_int(attributes, + maximum_variable_storage_size, + remaining_variable_storage_size, + maximum_variable_size); } /** diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index 4f1aa298da1..8b6b0a39086 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -873,6 +873,11 @@ efi_status_t efi_query_variable_info_int(u32 attributes, efi_status_t ret; u8 *comm_buf; + if (!max_variable_storage_size || + !remain_variable_storage_size || + !max_variable_size || !attributes) + return EFI_INVALID_PARAMETER; + payload_size = sizeof(*mm_query_info); comm_buf = setup_mm_hdr((void **)&mm_query_info, payload_size, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO, diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index e4d75420bff..414701893f6 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -45,6 +45,7 @@ efi_selftest_textinputex.o \ efi_selftest_textoutput.o \ efi_selftest_tpl.o \ efi_selftest_util.o \ +efi_selftest_variables_common.o \ efi_selftest_variables.o \ efi_selftest_variables_runtime.o \ efi_selftest_watchdog.o diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c index 39ad03a090d..3d5f38c6897 100644 --- a/lib/efi_selftest/efi_selftest_variables.c +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -51,15 +51,12 @@ static int execute(void) u16 varname[EFI_ST_MAX_VARNAME_SIZE]; int flag; efi_guid_t guid; - u64 max_storage, rem_storage, max_size; + int test_ret; - ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, - &max_storage, &rem_storage, - &max_size); - if (ret != EFI_SUCCESS) { - efi_st_todo("QueryVariableInfo failed\n"); - } else if (!max_storage || !rem_storage || !max_size) { - efi_st_error("QueryVariableInfo: wrong info\n"); + test_ret = efi_st_query_variable_common(runtime, + EFI_VARIABLE_BOOTSERVICE_ACCESS); + if (test_ret != EFI_ST_SUCCESS) { + efi_st_error("QueryVariableInfo failed\n"); return EFI_ST_FAILURE; } /* Set variable 0 */ diff --git a/lib/efi_selftest/efi_selftest_variables_common.c b/lib/efi_selftest/efi_selftest_variables_common.c new file mode 100644 index 00000000000..453bc8709a6 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_variables_common.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_variables_runtime + * + * Copyright (c) 2024 Ilias Apalodimas <ilias.apalodimas@linaro.org> + * + * This unit test checks common service across boottime/runtime + */ + +#include <efi_selftest.h> + +#define EFI_INVALID_ATTR BIT(30) + +int efi_st_query_variable_common(struct efi_runtime_services *runtime, + u32 attributes) +{ + efi_status_t ret; + u64 max_storage, rem_storage, max_size; + + ret = runtime->query_variable_info(attributes, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_SUCCESS) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } else if (!max_storage || !rem_storage || !max_size) { + efi_st_error("QueryVariableInfo: wrong info\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(EFI_VARIABLE_RUNTIME_ACCESS, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(attributes, + NULL, &rem_storage, + &max_size); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(attributes, + &max_storage, NULL, + &max_size); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(attributes, + &max_storage, &rem_storage, + NULL); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(0, &max_storage, &rem_storage, + &max_size); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(attributes | + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_UNSUPPORTED) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + ret = runtime->query_variable_info(EFI_VARIABLE_NON_VOLATILE, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + /* + * Use a mix existing/non-existing attribute bits from the + * UEFI spec + */ + ret = runtime->query_variable_info(attributes | EFI_INVALID_ATTR | + EFI_VARIABLE_NON_VOLATILE, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} diff --git a/lib/efi_selftest/efi_selftest_variables_runtime.c b/lib/efi_selftest/efi_selftest_variables_runtime.c index afa91be62c8..379c4f9c47b 100644 --- a/lib/efi_selftest/efi_selftest_variables_runtime.c +++ b/lib/efi_selftest/efi_selftest_variables_runtime.c @@ -55,14 +55,25 @@ static int execute(void) u16 varname[EFI_ST_MAX_VARNAME_SIZE]; efi_guid_t guid; u64 max_storage, rem_storage, max_size; + int test_ret; memset(v2, 0x1, sizeof(v2)); - ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, + + if (IS_ENABLED(CONFIG_EFI_VARIABLE_FILE_STORE)) { + test_ret = efi_st_query_variable_common(runtime, EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS); + if (test_ret != EFI_ST_SUCCESS) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } + } else { + ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, &max_storage, &rem_storage, &max_size); - if (ret != EFI_UNSUPPORTED) { - efi_st_error("QueryVariableInfo failed\n"); - return EFI_ST_FAILURE; + if (ret != EFI_UNSUPPORTED) { + efi_st_error("QueryVariableInfo failed\n"); + return EFI_ST_FAILURE; + } } ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0, |