summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/Kconfig6
-rw-r--r--lib/efi_loader/efi_boottime.c27
-rw-r--r--lib/efi_loader/efi_runtime.c244
-rw-r--r--lib/efi_loader/efi_setup.c5
-rw-r--r--lib/efi_loader/efi_variable.c81
-rw-r--r--lib/efi_selftest/Kconfig8
-rw-r--r--lib/efi_selftest/Makefile1
-rw-r--r--lib/efi_selftest/efi_selftest_variables_runtime.c94
8 files changed, 316 insertions, 150 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index cd5436c576..a7f2c68fa9 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -101,4 +101,10 @@ config EFI_PLATFORM_LANG_CODES
RFC 4646 format, e.g. "en-US;de-DE". The first language code is used
to initialize the PlatformLang variable.
+config EFI_HAVE_RUNTIME_RESET
+ # bool "Reset runtime service is available"
+ bool
+ default y
+ depends on ARCH_BCM283X || FSL_LAYERSCAPE || PSCI_RESET || SYSRESET_X86
+
endif
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index d104cc6b31..c2f89805c7 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * EFI application boot time services
+ * EFI application boot time services
*
- * Copyright (c) 2016 Alexander Graf
+ * Copyright (c) 2016 Alexander Graf
*/
#include <common.h>
@@ -1968,10 +1968,14 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
/* Make sure that notification functions are not called anymore */
efi_tpl = TPL_HIGH_LEVEL;
- /* TODO: Should persist EFI variables here */
+ /* Notify variable services */
+ efi_variables_boot_exit_notify();
board_quiesce_devices();
+ /* Patch out unsupported runtime function */
+ efi_runtime_detach();
+
/* Fix up caches for EFI payloads if necessary */
efi_exit_caches();
@@ -3234,7 +3238,7 @@ static efi_status_t efi_connect_single_controller(
if (r != EFI_SUCCESS)
return r;
- /* Context Override */
+ /* Context Override */
if (driver_image_handle) {
for (; *driver_image_handle; ++driver_image_handle) {
for (i = 0; i < count; ++i) {
@@ -3341,7 +3345,7 @@ static efi_status_t EFIAPI efi_connect_controller(
}
}
}
- /* Check for child controller specified by end node */
+ /* Check for child controller specified by end node */
if (ret != EFI_SUCCESS && remain_device_path &&
remain_device_path->type == DEVICE_PATH_TYPE_END)
ret = EFI_SUCCESS;
@@ -3620,11 +3624,7 @@ struct efi_system_table __efi_runtime_data systab = {
},
.fw_vendor = firmware_vendor,
.fw_revision = FW_VERSION << 16 | FW_PATCHLEVEL << 8,
- .con_in = &efi_con_in,
- .con_out = &efi_con_out,
- .std_err = &efi_con_out,
.runtime = &efi_runtime_services,
- .boottime = &efi_boot_services,
.nr_tables = 0,
.tables = NULL,
};
@@ -3644,6 +3644,15 @@ efi_status_t efi_initialize_system_table(void)
sizeof(struct efi_configuration_table),
(void **)&systab.tables);
+ /*
+ * These entries will be set to NULL in ExitBootServices(). To avoid
+ * relocation in SetVirtualAddressMap(), set them dynamically.
+ */
+ systab.con_in = &efi_con_in;
+ systab.con_out = &efi_con_out;
+ systab.std_err = &efi_con_out;
+ systab.boottime = &efi_boot_services;
+
/* Set CRC32 field in table headers */
efi_update_table_header_crc32(&systab.hdr);
efi_update_table_header_crc32(&efi_runtime_services.hdr);
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 40fdc0ea92..7a64dd42ca 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -26,8 +26,6 @@ struct efi_runtime_mmio_list {
LIST_HEAD(efi_runtime_mmio);
static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void);
-static efi_status_t __efi_runtime EFIAPI efi_device_error(void);
-static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void);
/*
* TODO(sjg@chromium.org): These defines and structures should come from the ELF
@@ -97,10 +95,7 @@ efi_status_t efi_init_runtime_supported(void)
* This value must be synced with efi_runtime_detach_list
* as well as efi_runtime_services.
*/
-#if CONFIG_IS_ENABLED(ARCH_BCM283X) || \
- CONFIG_IS_ENABLED(FSL_LAYERSCAPE) || \
- CONFIG_IS_ENABLED(SYSRESET_X86) || \
- CONFIG_IS_ENABLED(PSCI_RESET)
+#ifdef CONFIG_EFI_HAVE_RUNTIME_RESET
efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
#endif
efi_runtime_services_supported |=
@@ -387,80 +382,102 @@ efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time)
return EFI_UNSUPPORTED;
}
-struct efi_runtime_detach_list_struct {
- void *ptr;
- void *patchto;
-};
-
-static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
- {
- /* do_reset is gone */
- .ptr = &efi_runtime_services.reset_system,
- .patchto = efi_reset_system,
- }, {
- /* invalidate_*cache_all are gone */
- .ptr = &efi_runtime_services.set_virtual_address_map,
- .patchto = &efi_unimplemented,
- }, {
- /* RTC accessors are gone */
- .ptr = &efi_runtime_services.get_time,
- .patchto = &efi_get_time,
- }, {
- .ptr = &efi_runtime_services.set_time,
- .patchto = &efi_set_time,
- }, {
- /* Clean up system table */
- .ptr = &systab.con_in,
- .patchto = NULL,
- }, {
- /* Clean up system table */
- .ptr = &systab.con_out,
- .patchto = NULL,
- }, {
- /* Clean up system table */
- .ptr = &systab.std_err,
- .patchto = NULL,
- }, {
- /* Clean up system table */
- .ptr = &systab.boottime,
- .patchto = NULL,
- }, {
- .ptr = &efi_runtime_services.get_variable,
- .patchto = &efi_device_error,
- }, {
- .ptr = &efi_runtime_services.get_next_variable_name,
- .patchto = &efi_device_error,
- }, {
- .ptr = &efi_runtime_services.set_variable,
- .patchto = &efi_device_error,
- }
-};
-
-static bool efi_runtime_tobedetached(void *p)
+/**
+ * efi_is_runtime_service_pointer() - check if pointer points to runtime table
+ *
+ * @p: pointer to check
+ * Return: true if the pointer points to a service function pointer in the
+ * runtime table
+ */
+static bool efi_is_runtime_service_pointer(void *p)
{
- int i;
+ return p >= (void *)&efi_runtime_services.get_time &&
+ p <= (void *)&efi_runtime_services.query_variable_info;
+}
- for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++)
- if (efi_runtime_detach_list[i].ptr == p)
- return true;
+/**
+ * efi_runtime_detach() - detach unimplemented runtime functions
+ */
+void efi_runtime_detach(void)
+{
+ efi_runtime_services.reset_system = efi_reset_system;
+ efi_runtime_services.get_time = efi_get_time;
+ efi_runtime_services.set_time = efi_set_time;
- return false;
+ /* Update CRC32 */
+ efi_update_table_header_crc32(&efi_runtime_services.hdr);
}
-static void efi_runtime_detach(ulong offset)
+/**
+ * efi_set_virtual_address_map_runtime() - change from physical to virtual
+ * mapping
+ *
+ * This function implements the SetVirtualAddressMap() runtime service after
+ * it is first called.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @memory_map_size: size of the virtual map
+ * @descriptor_size: size of an entry in the map
+ * @descriptor_version: version of the map entries
+ * @virtmap: virtual address mapping information
+ * Return: status code EFI_UNSUPPORTED
+ */
+static efi_status_t EFIAPI efi_set_virtual_address_map_runtime(
+ unsigned long memory_map_size,
+ unsigned long descriptor_size,
+ uint32_t descriptor_version,
+ struct efi_mem_desc *virtmap)
{
- int i;
- ulong patchoff = offset - (ulong)gd->relocaddr;
+ return EFI_UNSUPPORTED;
+}
- for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) {
- ulong patchto = (ulong)efi_runtime_detach_list[i].patchto;
- ulong *p = efi_runtime_detach_list[i].ptr;
- ulong newaddr = patchto ? (patchto + patchoff) : 0;
+/**
+ * efi_convert_pointer_runtime() - convert from physical to virtual pointer
+ *
+ * This function implements the ConvertPointer() runtime service after
+ * the first call to SetVirtualAddressMap().
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @debug_disposition: indicates if pointer may be converted to NULL
+ * @address: pointer to be converted
+ * Return: status code EFI_UNSUPPORTED
+ */
+static __efi_runtime efi_status_t EFIAPI efi_convert_pointer_runtime(
+ efi_uintn_t debug_disposition, void **address)
+{
+ return EFI_UNSUPPORTED;
+}
- debug("%s: Setting %p to %lx\n", __func__, p, newaddr);
- *p = newaddr;
+static __efi_runtime void efi_relocate_runtime_table(ulong offset)
+{
+ ulong patchoff;
+ void **pos;
+
+ /* Relocate the runtime services pointers */
+ patchoff = offset - gd->relocaddr;
+ for (pos = (void **)&efi_runtime_services.get_time;
+ pos <= (void **)&efi_runtime_services.query_variable_info; ++pos) {
+ if (*pos)
+ *pos += patchoff;
}
+ /*
+ * The entry for SetVirtualAddress() must point to a physical address.
+ * After the first execution the service must return EFI_UNSUPPORTED.
+ */
+ efi_runtime_services.set_virtual_address_map =
+ &efi_set_virtual_address_map_runtime;
+
+ /*
+ * The entry for ConvertPointer() must point to a physical address.
+ * The service is not usable after SetVirtualAddress().
+ */
+ efi_runtime_services.convert_pointer = &efi_convert_pointer_runtime;
+
/* Update CRC32 */
efi_update_table_header_crc32(&efi_runtime_services.hdr);
}
@@ -483,6 +500,10 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
p = (void*)((ulong)rel->offset - base) + gd->relocaddr;
+ /* The runtime services are updated in efi_runtime_detach() */
+ if (map && efi_is_runtime_service_pointer(p))
+ continue;
+
debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__,
rel->info, *p, rel->offset);
@@ -506,9 +527,8 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
}
#endif
default:
- if (!efi_runtime_tobedetached(p))
- printf("%s: Unknown relocation type %llx\n",
- __func__, rel->info & R_MASK);
+ printf("%s: Unknown relocation type %llx\n",
+ __func__, rel->info & R_MASK);
continue;
}
@@ -516,9 +536,8 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
if (map && ((newaddr < map->virtual_start) ||
newaddr > (map->virtual_start +
(map->num_pages << EFI_PAGE_SHIFT)))) {
- if (!efi_runtime_tobedetached(p))
- printf("%s: Relocation at %p is out of "
- "range (%lx)\n", __func__, p, newaddr);
+ printf("%s: Relocation at %p is out of range (%lx)\n",
+ __func__, p, newaddr);
continue;
}
@@ -623,7 +642,15 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
}
}
- /* Move the actual runtime code over */
+ /*
+ * Some runtime services are implemented in a way that we can only offer
+ * them at boottime. Replace those function pointers.
+ *
+ * TODO: move this call to ExitBootServices().
+ */
+ efi_runtime_detach();
+
+ /* Relocate the runtime. See TODO above */
for (i = 0; i < n; i++) {
struct efi_mem_desc *map;
@@ -632,10 +659,8 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
ulong new_offset = map->virtual_start -
map->physical_start + gd->relocaddr;
+ efi_relocate_runtime_table(new_offset);
efi_runtime_relocate(new_offset, map);
- /* Once we're virtual, we can no longer handle
- complex callbacks */
- efi_runtime_detach(new_offset);
return EFI_EXIT(EFI_SUCCESS);
}
}
@@ -711,34 +736,6 @@ static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void)
}
/**
- * efi_device_error() - replacement function, returns EFI_DEVICE_ERROR
- *
- * This function is used after SetVirtualAddressMap() is called as replacement
- * for services that are not available anymore due to constraints of the U-Boot
- * implementation.
- *
- * Return: EFI_DEVICE_ERROR
- */
-static efi_status_t __efi_runtime EFIAPI efi_device_error(void)
-{
- return EFI_DEVICE_ERROR;
-}
-
-/**
- * efi_invalid_parameter() - replacement function, returns EFI_INVALID_PARAMETER
- *
- * This function is used after SetVirtualAddressMap() is called as replacement
- * for services that are not available anymore due to constraints of the U-Boot
- * implementation.
- *
- * Return: EFI_INVALID_PARAMETER
- */
-static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void)
-{
- return EFI_INVALID_PARAMETER;
-}
-
-/**
* efi_update_capsule() - process information from operating system
*
* This function implements the UpdateCapsule() runtime service.
@@ -782,33 +779,6 @@ efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
return EFI_UNSUPPORTED;
}
-/**
- * efi_query_variable_info() - get information about EFI variables
- *
- * This function implements the QueryVariableInfo() runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @attributes: bitmask to select variables to be
- * queried
- * @maximum_variable_storage_size: maximum size of storage area for the
- * selected variable types
- * @remaining_variable_storage_size: remaining size of storage are for the
- * selected variable types
- * @maximum_variable_size: maximum size of a variable of the
- * selected type
- * Returns: status code
- */
-efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
- u32 attributes,
- u64 *maximum_variable_storage_size,
- u64 *remaining_variable_storage_size,
- u64 *maximum_variable_size)
-{
- return EFI_UNSUPPORTED;
-}
-
struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
.hdr = {
.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
@@ -820,11 +790,11 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
.get_wakeup_time = (void *)&efi_unimplemented,
.set_wakeup_time = (void *)&efi_unimplemented,
.set_virtual_address_map = &efi_set_virtual_address_map,
- .convert_pointer = (void *)&efi_invalid_parameter,
+ .convert_pointer = (void *)&efi_unimplemented,
.get_variable = efi_get_variable,
.get_next_variable_name = efi_get_next_variable_name,
.set_variable = efi_set_variable,
- .get_next_high_mono_count = (void *)&efi_device_error,
+ .get_next_high_mono_count = (void *)&efi_unimplemented,
.reset_system = &efi_reset_system_boottime,
.update_capsule = efi_update_capsule,
.query_capsule_caps = efi_query_capsule_caps,
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index bfb57836fa..de7b616c6d 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -102,6 +102,11 @@ efi_status_t efi_init_obj_list(void)
/* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
switch_to_non_secure_mode();
+ /* Initialize variable services */
+ ret = efi_init_variables();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
/* Define supported languages */
ret = efi_init_platform_lang();
if (ret != EFI_SUCCESS)
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index d6b75ca02e..bc8ed678c9 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -520,3 +520,84 @@ out:
return EFI_EXIT(ret);
}
+
+/**
+ * efi_query_variable_info() - get information about EFI variables
+ *
+ * This function implements the QueryVariableInfo() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @attributes: bitmask to select variables to be
+ * queried
+ * @maximum_variable_storage_size: maximum size of storage area for the
+ * selected variable types
+ * @remaining_variable_storage_size: remaining size of storage are for the
+ * selected variable types
+ * @maximum_variable_size: maximum size of a variable of the
+ * selected type
+ * Returns: status code
+ */
+efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
+ u32 attributes,
+ u64 *maximum_variable_storage_size,
+ u64 *remaining_variable_storage_size,
+ u64 *maximum_variable_size)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_get_variable_runtime() - runtime implementation of GetVariable()
+ */
+static efi_status_t __efi_runtime EFIAPI
+efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
+ u32 *attributes, efi_uintn_t *data_size, void *data)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_get_next_variable_name_runtime() - runtime implementation of
+ * GetNextVariable()
+ */
+static efi_status_t __efi_runtime EFIAPI
+efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
+ u16 *variable_name, const efi_guid_t *vendor)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_set_variable_runtime() - runtime implementation of SetVariable()
+ */
+static efi_status_t __efi_runtime EFIAPI
+efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
+ u32 attributes, efi_uintn_t data_size,
+ const void *data)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
+ */
+void efi_variables_boot_exit_notify(void)
+{
+ efi_runtime_services.get_variable = efi_get_variable_runtime;
+ efi_runtime_services.get_next_variable_name =
+ efi_get_next_variable_name_runtime;
+ efi_runtime_services.set_variable = efi_set_variable_runtime;
+ efi_update_table_header_crc32(&efi_runtime_services.hdr);
+}
+
+/**
+ * efi_init_variables() - initialize variable services
+ *
+ * Return: status code
+ */
+efi_status_t efi_init_variables(void)
+{
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig
index 59f9f36801..d20f5899af 100644
--- a/lib/efi_selftest/Kconfig
+++ b/lib/efi_selftest/Kconfig
@@ -1,9 +1,9 @@
config CMD_BOOTEFI_SELFTEST
- bool "Allow booting an EFI efi_selftest"
+ bool "UEFI unit tests"
depends on CMD_BOOTEFI
imply FAT
imply FAT_WRITE
help
- This adds an EFI test application to U-Boot that can be executed
- with the 'bootefi selftest' command. It provides extended tests of
- the EFI API implementation.
+ This adds a UEFI test application to U-Boot that can be executed
+ via the 'bootefi selftest' command. It provides extended tests of
+ the UEFI API implementation.
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 3bebd0f573..88678755cc 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -35,6 +35,7 @@ efi_selftest_textoutput.o \
efi_selftest_tpl.o \
efi_selftest_util.o \
efi_selftest_variables.o \
+efi_selftest_variables_runtime.o \
efi_selftest_watchdog.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_selftest_devicepath.o
diff --git a/lib/efi_selftest/efi_selftest_variables_runtime.c b/lib/efi_selftest/efi_selftest_variables_runtime.c
new file mode 100644
index 0000000000..b3b40ad2cf
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_variables_runtime.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_variables_runtime
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the runtime services for variables after
+ * ExitBootServices():
+ * GetVariable, GetNextVariableName, SetVariable, QueryVariableInfo.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_MAX_DATA_SIZE 16
+#define EFI_ST_MAX_VARNAME_SIZE 40
+
+static struct efi_boot_services *boottime;
+static struct efi_runtime_services *runtime;
+static const efi_guid_t guid_vendor0 =
+ EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1,
+ 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6);
+
+/*
+ * Setup unit test.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ */
+static int setup(const efi_handle_t img_handle,
+ const struct efi_system_table *systable)
+{
+ boottime = systable->boottime;
+ runtime = systable->runtime;
+
+ return EFI_ST_SUCCESS;
+}
+
+/**
+ * execute() - execute unit test
+ *
+ * As runtime support is not implmented expect EFI_UNSUPPORTED to be returned.
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_uintn_t len;
+ u32 attr;
+ u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c,
+ 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,};
+ u8 data[EFI_ST_MAX_DATA_SIZE];
+ u16 varname[EFI_ST_MAX_VARNAME_SIZE];
+ efi_guid_t guid;
+ u64 max_storage, rem_storage, max_size;
+
+ 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;
+ }
+
+ ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 3, v + 4);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("SetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ len = 3;
+ ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
+ &attr, &len, data);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("GetVariable failed\n");
+ return EFI_ST_FAILURE;
+ }
+ memset(&guid, 0, 16);
+ *varname = 0;
+ ret = runtime->get_next_variable_name(&len, varname, &guid);
+ if (ret != EFI_UNSUPPORTED) {
+ efi_st_error("GetNextVariableName failed\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(variables_run) = {
+ .name = "variables at runtime",
+ .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+};