mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-20 06:01:26 +02:00
Pull request efi-2024-07-rc1-3
Documentation: * sort env sub-commands alphabetically * update list of aliases for the env command UEFI: * allow enabling SetVariable at runtime for future OS supported writing to ubootefi.var * use event callback for initrd deregistration Others: * correct alignment of x86 firmware tables -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEK7wKXt3/btL6/yA+hO4vgnE3U0sFAmYjhhUACgkQhO4vgnE3 U0txexAAyA7uYklnrlTWp+gmLvdcKIRMlN74CiESHfmGBZHjtQlk2mfmnl5sy0R4 2U1ulT0VwQPiltHH2X+0BY7/QgU92iAWNC++IWUjxHLsPhGnGBPkl3phFHRd1bLm fk6h5KEIvsXZnWbIOGlXCzgvarja4nHE8Y2rzUW6yJf+gfNVMdPodn+1g8p8t84r SDr+r1Fb2L4RZAsfOgXe/1Sa7bBkoRjiTcEOEh+o0BOIZLh4TMvSyY9PZ3TUTHeL ua/YmxsevWl3pCI+XW06ePIpkKAMuwU2bnV0RBd1L+SZR1FXffjkRti4dEQZBJ0U BAEVf3WjjnWC9FnwZOSMSFjDDwlqqi0Y77vqOXEJWbY27muW4mF1q1npv/Zamqa7 O+T+4bl7Kd5VeZafY9CAZXdtaImvsY5CWnop7W2rLE+NgUrShz5cvOj7BT00L4+i q2ExSeQxW+fVQqkFKzp6Kcm5SDTVnJfYtknEEYseiFvAp2wz229fV24bWfh5Gidn 03iU3YW4Oc+m1rSeSEmyJ/Yr57lmLdP6PF42hIRpiT/a/FHjXX1oOwvpjxBGr4gl S4LgfO69GuY5uO6ABacldlJ79SHTF9yuhqmwTRXj34+yY7I6Lb+pMqToXIJ9iZMx YaptdlEJlE9iYDAWM5TwoKp3ATZH9EYOQcJxlp/bFHHVrPBZeGc= =7YWW -----END PGP SIGNATURE----- Merge tag 'efi-2024-07-rc1-3' of https://source.denx.de/u-boot/custodians/u-boot-efi Pull request efi-2024-07-rc1-3 Documentation: * sort env sub-commands alphabetically * update list of aliases for the env command UEFI: * allow enabling SetVariable at runtime for future OS supported writing to ubootefi.var * use event callback for initrd deregistration Others: * correct alignment of x86 firmware tables
This commit is contained in:
commit
b064bb66a1
@ -98,6 +98,8 @@ int write_tables(void)
|
||||
int size = table->size ? : CONFIG_ROM_TABLE_SIZE;
|
||||
u32 rom_table_end;
|
||||
|
||||
rom_addr = ALIGN(rom_addr, 16);
|
||||
|
||||
if (!strcmp("smbios", table->name))
|
||||
gd->arch.smbios_start = rom_addr;
|
||||
|
||||
|
@ -1419,7 +1419,7 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
|
||||
}
|
||||
|
||||
bo->initrd_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
|
||||
if (!bo->file_info.current_path) {
|
||||
if (!bo->initrd_info.current_path) {
|
||||
ret = EFI_OUT_OF_RESOURCES;
|
||||
goto out;
|
||||
}
|
||||
|
@ -16,18 +16,18 @@ Synopsis
|
||||
env default [-f] (-a | var [...])
|
||||
env delete [-f] var [...]
|
||||
env edit name
|
||||
env erase
|
||||
env exists name
|
||||
env export [-t | -b | -c] [-s size] addr [var ...]
|
||||
env flags
|
||||
env grep [-e] [-n | -v | -b] string [...]
|
||||
env import [-d] [-t [-r] | -b | -c] addr [size] [var ...]
|
||||
env info [-d] [-p] [-q]
|
||||
env load
|
||||
env print [-a | name ...]
|
||||
env print -e [-guid guid] [-n] [name ...]
|
||||
env run var [...]
|
||||
env save
|
||||
env erase
|
||||
env load
|
||||
env select [target]
|
||||
env set [-f] name [value]
|
||||
env set -e [-nv][-bs][-rt][-at][-a][-i addr:size][-v] name [value]
|
||||
@ -40,11 +40,12 @@ the UEFI variables.
|
||||
|
||||
The next commands are kept as alias and for compatibility:
|
||||
|
||||
+ :doc:`askenv <askenv>` = *env ask*
|
||||
+ *editenv* = *env edit*
|
||||
+ *grepenv* = *env grep*
|
||||
+ *setenv* = *env set*
|
||||
+ *askenv* = *env ask*
|
||||
+ :doc:`printenv <printenv>` = *env print*
|
||||
+ *run* = *env run*
|
||||
+ *setenv* = *env set*
|
||||
|
||||
Ask
|
||||
~~~
|
||||
@ -103,6 +104,11 @@ The *env edit* command edits an environment variable.
|
||||
name
|
||||
name of the variable.
|
||||
|
||||
Erase
|
||||
~~~~~
|
||||
|
||||
The *env erase* command erases the U-Boot environment.
|
||||
|
||||
Exists
|
||||
~~~~~~
|
||||
|
||||
@ -204,6 +210,11 @@ environment information.
|
||||
quiet output, use only for command result, by example with
|
||||
'test' command.
|
||||
|
||||
Load
|
||||
~~~~
|
||||
|
||||
The *env load* command loads the U-Boot environment from persistent storage.
|
||||
|
||||
Print
|
||||
~~~~~
|
||||
|
||||
@ -235,16 +246,6 @@ Save
|
||||
|
||||
The *env save* command saves the U-Boot environment in persistent storage.
|
||||
|
||||
Erase
|
||||
~~~~~
|
||||
|
||||
The *env erase* command erases the U-Boot environment.
|
||||
|
||||
Load
|
||||
~~~~
|
||||
|
||||
The *env load* command loads the U-Boot environment from persistent storage.
|
||||
|
||||
Select
|
||||
~~~~~~
|
||||
|
||||
@ -350,15 +351,15 @@ edit
|
||||
exists
|
||||
CONFIG_CMD_ENV_EXISTS
|
||||
|
||||
flags
|
||||
CONFIG_CMD_ENV_FLAGS
|
||||
|
||||
erase
|
||||
CONFIG_CMD_ERASEENV
|
||||
|
||||
export
|
||||
CONFIG_CMD_EXPORTENV
|
||||
|
||||
flags
|
||||
CONFIG_CMD_ENV_FLAGS
|
||||
|
||||
grep
|
||||
CONFIG_CMD_GREPENV, CONFIG_REGEX for '-e' option
|
||||
|
||||
|
@ -159,6 +159,10 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr,
|
||||
#define EFICONFIG_AUTO_GENERATED_ENTRY_GUID \
|
||||
EFI_GUID(0x8108ac4e, 0x9f11, 0x4d59, \
|
||||
0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2)
|
||||
#define U_BOOT_EFI_RT_VAR_FILE_GUID \
|
||||
EFI_GUID(0xb2ac5fc9, 0x92b7, 0x4acd, \
|
||||
0xae, 0xac, 0x11, 0xe8, 0x18, 0xc3, 0x13, 0x0c)
|
||||
|
||||
|
||||
/* Use internal device tree when starting UEFI application */
|
||||
#define EFI_FDT_USE_INTERNAL NULL
|
||||
|
@ -271,13 +271,16 @@ const efi_guid_t *efi_auth_var_get_guid(const u16 *name);
|
||||
*
|
||||
* @variable_name_size: size of variable_name buffer in bytes
|
||||
* @variable_name: name of uefi variable's name in u16
|
||||
* @mask: bitmask with required attributes of variables to be collected.
|
||||
* variables are only collected if all of the required
|
||||
* attributes match. Use 0 to skip matching
|
||||
* @vendor: vendor's guid
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t __efi_runtime
|
||||
efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size, u16 *variable_name,
|
||||
efi_guid_t *vendor);
|
||||
efi_guid_t *vendor, u32 mask);
|
||||
/**
|
||||
* efi_get_variable_mem() - Runtime common code across efi variable
|
||||
* implementations for GetVariable() from
|
||||
@ -289,12 +292,15 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size, u16 *variable_na
|
||||
* @data_size: size of the buffer to which the variable value is copied
|
||||
* @data: buffer to which the variable value is copied
|
||||
* @timep: authentication time (seconds since start of epoch)
|
||||
* @mask: bitmask with required attributes of variables to be collected.
|
||||
* variables are only collected if all of the required
|
||||
* attributes match. Use 0 to skip matching
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t __efi_runtime
|
||||
efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor,
|
||||
u32 *attributes, efi_uintn_t *data_size, void *data,
|
||||
u64 *timep);
|
||||
u64 *timep, u32 mask);
|
||||
|
||||
/**
|
||||
* efi_get_variable_runtime() - runtime implementation of GetVariable()
|
||||
@ -334,4 +340,10 @@ efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
|
||||
*/
|
||||
void efi_var_buf_update(struct efi_var_file *var_buf);
|
||||
|
||||
efi_status_t __efi_runtime efi_var_collect_mem(struct efi_var_file *buf,
|
||||
efi_uintn_t *lenp,
|
||||
u32 check_attr_mask);
|
||||
|
||||
u32 efi_var_entry_len(struct efi_var_entry *var);
|
||||
|
||||
#endif
|
||||
|
@ -387,7 +387,7 @@ int u16_strcasecmp(const u16 *s1, const u16 *s2)
|
||||
* > 0 if the first different u16 in s1 is greater than the
|
||||
* corresponding u16 in s2
|
||||
*/
|
||||
int u16_strncmp(const u16 *s1, const u16 *s2, size_t n)
|
||||
int __efi_runtime u16_strncmp(const u16 *s1, const u16 *s2, size_t n)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -62,6 +62,22 @@ config EFI_VARIABLE_FILE_STORE
|
||||
Select this option if you want non-volatile UEFI variables to be
|
||||
stored as file /ubootefi.var on the EFI system partition.
|
||||
|
||||
config EFI_RT_VOLATILE_STORE
|
||||
bool "Allow variable runtime services in volatile storage (e.g RAM)"
|
||||
depends on EFI_VARIABLE_FILE_STORE
|
||||
help
|
||||
When EFI variables are stored on file we don't allow SetVariableRT,
|
||||
since the OS doesn't know how to write that file. At he same time
|
||||
we copy runtime variables in DRAM and support GetVariableRT
|
||||
|
||||
Enable this option to allow SetVariableRT on the RAM backend of
|
||||
the EFI variable storage. The OS will be responsible for syncing
|
||||
the RAM contents to the file, otherwise any changes made during
|
||||
runtime won't persist reboots.
|
||||
Authenticated variables are not supported. Note that this will
|
||||
violate the EFI spec since writing auth variables will return
|
||||
EFI_INVALID_PARAMETER
|
||||
|
||||
config EFI_MM_COMM_TEE
|
||||
bool "UEFI variables storage service via the trusted world"
|
||||
depends on OPTEE
|
||||
|
@ -549,11 +549,6 @@ efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
|
||||
out:
|
||||
free(load_options);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
|
||||
if (efi_initrd_deregister() != EFI_SUCCESS)
|
||||
log_err("Failed to remove loadfile2 for initrd\n");
|
||||
}
|
||||
|
||||
/* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */
|
||||
list_for_each_entry(evt, &efi_events, link) {
|
||||
if (evt->group &&
|
||||
|
@ -183,41 +183,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_initrd_register() - create handle for loading initial RAM disk
|
||||
*
|
||||
* This function creates a new handle and installs a Linux specific vendor
|
||||
* device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
|
||||
* to identify the handle and then calls the LoadFile service of the
|
||||
* EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_initrd_register(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
/*
|
||||
* Allow the user to continue if Boot#### file path is not set for
|
||||
* an initrd
|
||||
*/
|
||||
ret = check_initrd();
|
||||
if (ret == EFI_INVALID_PARAMETER)
|
||||
return EFI_SUCCESS;
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ret = efi_install_multiple_protocol_interfaces(&efi_initrd_handle,
|
||||
/* initramfs */
|
||||
&efi_guid_device_path, &dp_lf2_handle,
|
||||
/* LOAD_FILE2 */
|
||||
&efi_guid_load_file2_protocol,
|
||||
&efi_lf2_protocol,
|
||||
NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_initrd_deregister() - delete the handle for loading initial RAM disk
|
||||
*
|
||||
@ -245,3 +210,66 @@ efi_status_t efi_initrd_deregister(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_initrd_return_notify() - return to efibootmgr callback
|
||||
*
|
||||
* @event: the event for which this notification function is registered
|
||||
* @context: event context
|
||||
*/
|
||||
static void EFIAPI efi_initrd_return_notify(struct efi_event *event,
|
||||
void *context)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
EFI_ENTRY("%p, %p", event, context);
|
||||
ret = efi_initrd_deregister();
|
||||
EFI_EXIT(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_initrd_register() - create handle for loading initial RAM disk
|
||||
*
|
||||
* This function creates a new handle and installs a Linux specific vendor
|
||||
* device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
|
||||
* to identify the handle and then calls the LoadFile service of the
|
||||
* EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_initrd_register(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
struct efi_event *event;
|
||||
|
||||
/*
|
||||
* Allow the user to continue if Boot#### file path is not set for
|
||||
* an initrd
|
||||
*/
|
||||
ret = check_initrd();
|
||||
if (ret == EFI_INVALID_PARAMETER)
|
||||
return EFI_SUCCESS;
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ret = efi_install_multiple_protocol_interfaces(&efi_initrd_handle,
|
||||
/* initramfs */
|
||||
&efi_guid_device_path, &dp_lf2_handle,
|
||||
/* LOAD_FILE2 */
|
||||
&efi_guid_load_file2_protocol,
|
||||
&efi_lf2_protocol,
|
||||
NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
log_err("installing EFI_LOAD_FILE2_PROTOCOL failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = efi_create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
|
||||
efi_initrd_return_notify, NULL,
|
||||
&efi_guid_event_group_return_to_efibootmgr,
|
||||
&event);
|
||||
if (ret != EFI_SUCCESS)
|
||||
log_err("Creating event failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <dm.h>
|
||||
#include <elf.h>
|
||||
#include <efi_loader.h>
|
||||
#include <efi_variable.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <rtc.h>
|
||||
@ -110,6 +111,7 @@ static __efi_runtime_data efi_uintn_t efi_descriptor_size;
|
||||
*/
|
||||
efi_status_t efi_init_runtime_supported(void)
|
||||
{
|
||||
const efi_guid_t efi_guid_efi_rt_var_file = U_BOOT_EFI_RT_VAR_FILE_GUID;
|
||||
efi_status_t ret;
|
||||
struct efi_rt_properties_table *rt_table;
|
||||
|
||||
@ -127,6 +129,46 @@ 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_RT_VOLATILE_STORE)) {
|
||||
u8 s = 0;
|
||||
|
||||
ret = efi_set_variable_int(u"RTStorageVolatile",
|
||||
&efi_guid_efi_rt_var_file,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY,
|
||||
sizeof(EFI_VAR_FILE_NAME),
|
||||
EFI_VAR_FILE_NAME, false);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
log_err("Failed to set RTStorageVolatile\n");
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* This variable needs to be visible so users can read it,
|
||||
* but the real contents are going to be filled during
|
||||
* GetVariable
|
||||
*/
|
||||
ret = efi_set_variable_int(u"VarToFile",
|
||||
&efi_guid_efi_rt_var_file,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY,
|
||||
sizeof(s),
|
||||
&s, false);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
log_err("Failed to set VarToFile\n");
|
||||
efi_set_variable_int(u"RTStorageVolatile",
|
||||
&efi_guid_efi_rt_var_file,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_READ_ONLY,
|
||||
0, NULL, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
rt_table->runtime_services_supported |= EFI_RT_SUPPORTED_SET_VARIABLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This value must be synced with efi_runtime_detach_list
|
||||
* as well as efi_runtime_services.
|
||||
|
@ -182,7 +182,8 @@ efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
ret = efi_get_variable_mem(variable_name, guid, attributes, data_size, data, NULL);
|
||||
ret = efi_get_variable_mem(variable_name, guid, attributes, data_size,
|
||||
data, NULL, EFI_VARIABLE_RUNTIME_ACCESS);
|
||||
|
||||
/* Remove EFI_VARIABLE_READ_ONLY flag */
|
||||
if (attributes)
|
||||
@ -195,7 +196,8 @@ efi_status_t __efi_runtime EFIAPI
|
||||
efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
|
||||
u16 *variable_name, efi_guid_t *guid)
|
||||
{
|
||||
return efi_get_next_variable_name_mem(variable_name_size, variable_name, guid);
|
||||
return efi_get_next_variable_name_mem(variable_name_size, variable_name,
|
||||
guid, EFI_VARIABLE_RUNTIME_ACCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -419,7 +421,7 @@ void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_collect() - Copy EFI variables mstching attributes mask
|
||||
* efi_var_collect() - Copy EFI variables matching attributes mask
|
||||
*
|
||||
* @bufp: buffer containing variable collection
|
||||
* @lenp: buffer length
|
||||
|
@ -61,6 +61,23 @@ efi_var_mem_compare(struct efi_var_entry *var, const efi_guid_t *guid,
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_entry_len() - Get the entry len including headers & name
|
||||
*
|
||||
* @var: pointer to variable start
|
||||
*
|
||||
* Return: 8-byte aligned variable entry length
|
||||
*/
|
||||
|
||||
u32 __efi_runtime efi_var_entry_len(struct efi_var_entry *var)
|
||||
{
|
||||
if (!var)
|
||||
return 0;
|
||||
|
||||
return ALIGN((sizeof(u16) * (u16_strlen(var->name) + 1)) +
|
||||
var->length + sizeof(*var), 8);
|
||||
}
|
||||
|
||||
struct efi_var_entry __efi_runtime
|
||||
*efi_var_mem_find(const efi_guid_t *guid, const u16 *name,
|
||||
struct efi_var_entry **next)
|
||||
@ -184,53 +201,6 @@ u64 __efi_runtime efi_var_mem_free(void)
|
||||
sizeof(struct efi_var_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_mem_bs_del() - delete boot service only variables
|
||||
*/
|
||||
static void efi_var_mem_bs_del(void)
|
||||
{
|
||||
struct efi_var_entry *var = efi_var_buf->var;
|
||||
|
||||
for (;;) {
|
||||
struct efi_var_entry *last;
|
||||
|
||||
last = (struct efi_var_entry *)
|
||||
((uintptr_t)efi_var_buf + efi_var_buf->length);
|
||||
if (var >= last)
|
||||
break;
|
||||
if (var->attr & EFI_VARIABLE_RUNTIME_ACCESS) {
|
||||
u16 *data;
|
||||
|
||||
/* skip variable */
|
||||
for (data = var->name; *data; ++data)
|
||||
;
|
||||
++data;
|
||||
var = (struct efi_var_entry *)
|
||||
ALIGN((uintptr_t)data + var->length, 8);
|
||||
} else {
|
||||
/* delete variable */
|
||||
efi_var_mem_del(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_mem_notify_exit_boot_services() - ExitBootService callback
|
||||
*
|
||||
* @event: callback event
|
||||
* @context: callback context
|
||||
*/
|
||||
static void EFIAPI
|
||||
efi_var_mem_notify_exit_boot_services(struct efi_event *event, void *context)
|
||||
{
|
||||
EFI_ENTRY("%p, %p", event, context);
|
||||
|
||||
/* Delete boot service only variables */
|
||||
efi_var_mem_bs_del();
|
||||
|
||||
EFI_EXIT(EFI_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_mem_notify_exit_boot_services() - SetVirtualMemoryMap callback
|
||||
*
|
||||
@ -261,11 +231,7 @@ efi_status_t efi_var_mem_init(void)
|
||||
efi_var_buf->magic = EFI_VAR_FILE_MAGIC;
|
||||
efi_var_buf->length = (uintptr_t)efi_var_buf->var -
|
||||
(uintptr_t)efi_var_buf;
|
||||
/* crc32 for 0 bytes = 0 */
|
||||
|
||||
ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
|
||||
efi_var_mem_notify_exit_boot_services, NULL,
|
||||
NULL, &event);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
ret = efi_create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, TPL_CALLBACK,
|
||||
@ -276,10 +242,71 @@ efi_status_t efi_var_mem_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_var_collect_mem() - Copy EFI variables matching attributes mask from
|
||||
* efi_var_buf
|
||||
*
|
||||
* @buf: buffer containing variable collection
|
||||
* @lenp: buffer length
|
||||
* @mask: mask of matched attributes
|
||||
*
|
||||
* Return: Status code
|
||||
*/
|
||||
efi_status_t __efi_runtime
|
||||
efi_var_collect_mem(struct efi_var_file *buf, efi_uintn_t *lenp, u32 mask)
|
||||
{
|
||||
static struct efi_var_file __efi_runtime_data hdr = {
|
||||
.magic = EFI_VAR_FILE_MAGIC,
|
||||
};
|
||||
struct efi_var_entry *last, *var, *var_to;
|
||||
|
||||
hdr.length = sizeof(struct efi_var_file);
|
||||
|
||||
var = efi_var_buf->var;
|
||||
last = (struct efi_var_entry *)
|
||||
((uintptr_t)efi_var_buf + efi_var_buf->length);
|
||||
if (buf)
|
||||
var_to = buf->var;
|
||||
|
||||
while (var < last) {
|
||||
u32 len = efi_var_entry_len(var);
|
||||
|
||||
if ((var->attr & mask) != mask) {
|
||||
var = (void *)((uintptr_t)var + len);
|
||||
continue;
|
||||
}
|
||||
|
||||
hdr.length += len;
|
||||
|
||||
if (buf && hdr.length <= *lenp) {
|
||||
efi_memcpy_runtime(var_to, var, len);
|
||||
var_to = (void *)var_to + len;
|
||||
}
|
||||
var = (void *)var + len;
|
||||
}
|
||||
|
||||
if (!buf && hdr.length <= *lenp) {
|
||||
*lenp = hdr.length;
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!buf || hdr.length > *lenp) {
|
||||
*lenp = hdr.length;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
hdr.crc32 = crc32(0, (u8 *)buf->var,
|
||||
hdr.length - sizeof(struct efi_var_file));
|
||||
|
||||
efi_memcpy_runtime(buf, &hdr, sizeof(hdr));
|
||||
*lenp = hdr.length;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
efi_status_t __efi_runtime
|
||||
efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor,
|
||||
u32 *attributes, efi_uintn_t *data_size, void *data,
|
||||
u64 *timep)
|
||||
u64 *timep, u32 mask)
|
||||
{
|
||||
efi_uintn_t old_size;
|
||||
struct efi_var_entry *var;
|
||||
@ -291,11 +318,22 @@ efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor,
|
||||
if (!var)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
/*
|
||||
* This function is used at runtime to dump EFI variables.
|
||||
* The memory backend we keep around has BS-only variables as
|
||||
* well. At runtime we filter them here
|
||||
*/
|
||||
if (mask && !((var->attr & mask) == mask))
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
if (attributes)
|
||||
*attributes = var->attr;
|
||||
if (timep)
|
||||
*timep = var->time;
|
||||
|
||||
if (!u16_strcmp(variable_name, u"VarToFile"))
|
||||
return efi_var_collect_mem(data, data_size, EFI_VARIABLE_NON_VOLATILE);
|
||||
|
||||
old_size = *data_size;
|
||||
*data_size = var->length;
|
||||
if (old_size < var->length)
|
||||
@ -315,7 +353,8 @@ efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor,
|
||||
|
||||
efi_status_t __efi_runtime
|
||||
efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size,
|
||||
u16 *variable_name, efi_guid_t *vendor)
|
||||
u16 *variable_name, efi_guid_t *vendor,
|
||||
u32 mask)
|
||||
{
|
||||
struct efi_var_entry *var;
|
||||
efi_uintn_t len, old_size;
|
||||
@ -324,6 +363,7 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size,
|
||||
if (!variable_name_size || !variable_name || !vendor)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
skip:
|
||||
len = *variable_name_size >> 1;
|
||||
if (u16_strnlen(variable_name, len) == len)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
@ -347,6 +387,11 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size,
|
||||
efi_memcpy_runtime(variable_name, var->name, *variable_name_size);
|
||||
efi_memcpy_runtime(vendor, &var->guid, sizeof(efi_guid_t));
|
||||
|
||||
if (mask && !((var->attr & mask) == mask)) {
|
||||
*variable_name_size = old_size;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -209,27 +209,32 @@ efi_get_variable_int(const u16 *variable_name, const efi_guid_t *vendor,
|
||||
u32 *attributes, efi_uintn_t *data_size, void *data,
|
||||
u64 *timep)
|
||||
{
|
||||
return efi_get_variable_mem(variable_name, vendor, attributes, data_size, data, timep);
|
||||
return efi_get_variable_mem(variable_name, vendor, attributes, data_size,
|
||||
data, timep, 0);
|
||||
}
|
||||
|
||||
efi_status_t __efi_runtime
|
||||
efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
|
||||
u16 *variable_name, efi_guid_t *vendor)
|
||||
{
|
||||
return efi_get_next_variable_name_mem(variable_name_size, variable_name, vendor);
|
||||
return efi_get_next_variable_name_mem(variable_name_size, variable_name,
|
||||
vendor, 0);
|
||||
}
|
||||
|
||||
efi_status_t efi_set_variable_int(const u16 *variable_name,
|
||||
const efi_guid_t *vendor,
|
||||
u32 attributes, efi_uintn_t data_size,
|
||||
const void *data, bool ro_check)
|
||||
/**
|
||||
* setvariable_allowed() - checks defined by the UEFI spec for setvariable
|
||||
*
|
||||
* @variable_name: name of the variable
|
||||
* @vendor: vendor GUID
|
||||
* @attributes: attributes of the variable
|
||||
* @data_size: size of the buffer with the variable value
|
||||
* @data: buffer with the variable value
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t __efi_runtime
|
||||
setvariable_allowed(const u16 *variable_name, const efi_guid_t *vendor,
|
||||
u32 attributes, efi_uintn_t data_size, const void *data)
|
||||
{
|
||||
struct efi_var_entry *var;
|
||||
efi_uintn_t ret;
|
||||
bool append, delete;
|
||||
u64 time = 0;
|
||||
enum efi_auth_var_type var_type;
|
||||
|
||||
if (!variable_name || !*variable_name || !vendor)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
@ -261,6 +266,25 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
|
||||
!(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)))
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
efi_status_t efi_set_variable_int(const u16 *variable_name,
|
||||
const efi_guid_t *vendor,
|
||||
u32 attributes, efi_uintn_t data_size,
|
||||
const void *data, bool ro_check)
|
||||
{
|
||||
struct efi_var_entry *var;
|
||||
efi_uintn_t ret;
|
||||
bool append, delete;
|
||||
u64 time = 0;
|
||||
enum efi_auth_var_type var_type;
|
||||
|
||||
ret = setvariable_allowed(variable_name, vendor, attributes, data_size,
|
||||
data);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* check if a variable exists */
|
||||
var = efi_var_mem_find(vendor, variable_name, NULL);
|
||||
append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
|
||||
@ -454,7 +478,79 @@ 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;
|
||||
struct efi_var_entry *var;
|
||||
efi_uintn_t ret;
|
||||
bool append, delete;
|
||||
u64 time = 0;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_EFI_RT_VOLATILE_STORE))
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
/*
|
||||
* Authenticated variables are not supported. The EFI spec
|
||||
* in §32.3.6 requires keys to be stored in non-volatile storage which
|
||||
* is tamper and delete resistant.
|
||||
* The rest of the checks are in setvariable_allowed()
|
||||
*/
|
||||
if (attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
ret = setvariable_allowed(variable_name, vendor, attributes, data_size,
|
||||
data);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* check if a variable exists */
|
||||
var = efi_var_mem_find(vendor, variable_name, NULL);
|
||||
append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
|
||||
attributes &= ~EFI_VARIABLE_APPEND_WRITE;
|
||||
delete = !append && (!data_size || !attributes);
|
||||
|
||||
/* BS only variables are hidden deny writing them */
|
||||
if (!delete && !(attributes & EFI_VARIABLE_RUNTIME_ACCESS))
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
if (var) {
|
||||
if (var->attr & EFI_VARIABLE_READ_ONLY ||
|
||||
!(var->attr & EFI_VARIABLE_NON_VOLATILE))
|
||||
return EFI_WRITE_PROTECTED;
|
||||
|
||||
/* attributes won't be changed */
|
||||
if (!delete && (((var->attr & ~EFI_VARIABLE_READ_ONLY) !=
|
||||
(attributes & ~EFI_VARIABLE_READ_ONLY))))
|
||||
return EFI_INVALID_PARAMETER;
|
||||
time = var->time;
|
||||
} else {
|
||||
if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
|
||||
return EFI_INVALID_PARAMETER;
|
||||
if (append && !data_size)
|
||||
return EFI_SUCCESS;
|
||||
if (delete)
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (delete) {
|
||||
/* EFI_NOT_FOUND has been handled before */
|
||||
attributes = var->attr;
|
||||
ret = EFI_SUCCESS;
|
||||
} else if (append && var) {
|
||||
u16 *old_data = (void *)((uintptr_t)var->name +
|
||||
sizeof(u16) * (u16_strlen(var->name) + 1));
|
||||
|
||||
ret = efi_var_mem_ins(variable_name, vendor, attributes,
|
||||
var->length, old_data, data_size, data,
|
||||
time);
|
||||
} else {
|
||||
ret = efi_var_mem_ins(variable_name, vendor, attributes,
|
||||
data_size, data, 0, NULL, time);
|
||||
}
|
||||
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
/* We are always inserting new variables, get rid of the old copy */
|
||||
efi_var_mem_del(var);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -959,11 +959,6 @@ void efi_variables_boot_exit_notify(void)
|
||||
log_err("Unable to notify the MM partition for ExitBootServices\n");
|
||||
free(comm_buf);
|
||||
|
||||
/*
|
||||
* Populate the list for runtime variables.
|
||||
* asking EFI_VARIABLE_RUNTIME_ACCESS is redundant, since
|
||||
* efi_var_mem_notify_exit_boot_services will clean those, but that's fine
|
||||
*/
|
||||
ret = efi_var_collect(&var_buf, &len, EFI_VARIABLE_RUNTIME_ACCESS);
|
||||
if (ret != EFI_SUCCESS)
|
||||
log_err("Can't populate EFI variables. No runtime variables will be available\n");
|
||||
|
@ -10,6 +10,8 @@
|
||||
*/
|
||||
|
||||
#include <efi_selftest.h>
|
||||
#include <efi_variable.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
#define EFI_ST_MAX_DATA_SIZE 16
|
||||
#define EFI_ST_MAX_VARNAME_SIZE 40
|
||||
@ -17,6 +19,8 @@
|
||||
static struct efi_boot_services *boottime;
|
||||
static struct efi_runtime_services *runtime;
|
||||
static const efi_guid_t guid_vendor0 = EFI_GLOBAL_VARIABLE_GUID;
|
||||
static const efi_guid_t __efi_runtime_data efi_rt_var_guid =
|
||||
U_BOOT_EFI_RT_VAR_FILE_GUID;
|
||||
|
||||
/*
|
||||
* Setup unit test.
|
||||
@ -41,15 +45,18 @@ static int setup(const efi_handle_t img_handle,
|
||||
static int execute(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
efi_uintn_t len;
|
||||
efi_uintn_t len, avail, append_len = 17;
|
||||
u32 attr;
|
||||
u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c,
|
||||
0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,};
|
||||
u8 v2[CONFIG_EFI_VAR_BUF_SIZE];
|
||||
u8 data[EFI_ST_MAX_DATA_SIZE];
|
||||
u8 data2[CONFIG_EFI_VAR_BUF_SIZE];
|
||||
u16 varname[EFI_ST_MAX_VARNAME_SIZE];
|
||||
efi_guid_t guid;
|
||||
u64 max_storage, rem_storage, max_size;
|
||||
|
||||
memset(v2, 0x1, sizeof(v2));
|
||||
ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
&max_storage, &rem_storage,
|
||||
&max_size);
|
||||
@ -62,9 +69,216 @@ static int execute(void)
|
||||
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;
|
||||
if (IS_ENABLED(CONFIG_EFI_RT_VOLATILE_STORE)) {
|
||||
efi_uintn_t prev_len, delta;
|
||||
struct efi_var_entry *var;
|
||||
struct efi_var_file *hdr;
|
||||
|
||||
/* At runtime only non-volatile variables may be set. */
|
||||
if (ret != EFI_INVALID_PARAMETER) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* runtime atttribute must be set */
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
3, v + 4);
|
||||
if (ret != EFI_INVALID_PARAMETER) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
len = sizeof(data);
|
||||
ret = runtime->get_variable(u"RTStorageVolatile",
|
||||
&efi_rt_var_guid,
|
||||
&attr, &len, data);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
if (len != sizeof(EFI_VAR_FILE_NAME) ||
|
||||
memcmp(data, EFI_VAR_FILE_NAME, sizeof(EFI_VAR_FILE_NAME))) {
|
||||
data[len - 1] = 0;
|
||||
efi_st_error("RTStorageVolatile = %s\n", data);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
len = sizeof(data2);
|
||||
ret = runtime->get_variable(u"VarToFile", &efi_rt_var_guid,
|
||||
&attr, &len, data2);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/*
|
||||
* VarToFile size must change once a variable is inserted
|
||||
* Store it now, we'll use it later
|
||||
*/
|
||||
prev_len = len;
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
sizeof(v2),
|
||||
v2);
|
||||
/*
|
||||
* This will try to update VarToFile as well and must fail,
|
||||
* without changing or deleting VarToFile
|
||||
*/
|
||||
if (ret != EFI_OUT_OF_RESOURCES) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = sizeof(data2);
|
||||
ret = runtime->get_variable(u"VarToFile", &efi_rt_var_guid,
|
||||
&attr, &len, data2);
|
||||
if (ret != EFI_SUCCESS || prev_len != len) {
|
||||
efi_st_error("Get/SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Add an 8byte aligned variable */
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
sizeof(v), v);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Delete it by setting the attrs to 0 */
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
0, sizeof(v), v);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Add it back */
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
sizeof(v), v);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Delete it again by setting the size to 0 */
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
0, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Delete it again and make sure it's not there */
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
0, NULL);
|
||||
if (ret != EFI_NOT_FOUND) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a non-aligned variable
|
||||
* VarToFile updates must include efi_st_var0
|
||||
*/
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
9, v + 4);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
var = efi_var_mem_find(&guid_vendor0, u"efi_st_var0", NULL);
|
||||
if (!var) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
delta = efi_var_entry_len(var);
|
||||
len = sizeof(data2);
|
||||
ret = runtime->get_variable(u"VarToFile", &efi_rt_var_guid,
|
||||
&attr, &len, data2);
|
||||
if (ret != EFI_SUCCESS || prev_len + delta != len) {
|
||||
efi_st_error("Get/SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append on an existing variable must update VarToFile
|
||||
* Our variable entries are 8-byte aligned.
|
||||
* Adding a single byte will fit on the existing space
|
||||
*/
|
||||
prev_len = len;
|
||||
avail = efi_var_entry_len(var) -
|
||||
(sizeof(u16) * (u16_strlen(var->name) + 1) + sizeof(*var)) -
|
||||
var->length;
|
||||
if (avail >= append_len)
|
||||
delta = 0;
|
||||
else
|
||||
delta = ALIGN(append_len - avail, 8);
|
||||
ret = runtime->set_variable(u"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_APPEND_WRITE |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
append_len, v2);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = sizeof(data2);
|
||||
ret = runtime->get_variable(u"VarToFile", &efi_rt_var_guid,
|
||||
&attr, &len, data2);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (prev_len + delta != len) {
|
||||
efi_st_error("Unexpected VarToFile size");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Make sure that variable contains a valid file */
|
||||
hdr = (struct efi_var_file *)data2;
|
||||
if (hdr->magic != EFI_VAR_FILE_MAGIC ||
|
||||
len != hdr->length ||
|
||||
hdr->crc32 != crc32(0, (u8 *)((uintptr_t)data2 + sizeof(struct efi_var_file)),
|
||||
len - sizeof(struct efi_var_file))) {
|
||||
efi_st_error("VarToFile invalid header\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
/* Variables that are BS, RT and volatile are RO after EBS */
|
||||
ret = runtime->set_variable(u"VarToFile", &efi_rt_var_guid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_NON_VOLATILE,
|
||||
sizeof(v), v);
|
||||
if (ret != EFI_WRITE_PROTECTED) {
|
||||
efi_st_error("Get/SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
} else {
|
||||
if (ret != EFI_UNSUPPORTED) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
}
|
||||
len = EFI_ST_MAX_DATA_SIZE;
|
||||
ret = runtime->get_variable(u"PlatformLangCodes", &guid_vendor0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user