
Hi Heinrich
On Wed, Jul 08, 2020 at 06:29:34PM +0200, Heinrich Schuchardt wrote:
Saving UEFI variable as encoded U-Boot environment variables does not allow implement run-time support.
Use a memory buffer for storing UEFI variables.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
lib/efi_loader/efi_variable.c | 556 ++++++---------------------------- 1 file changed, 93 insertions(+), 463 deletions(-)
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index f2f787fc8d..13123e7e41 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -30,145 +30,6 @@ static bool efi_secure_boot; static enum efi_secure_mode efi_secure_mode; -}
[...]
/** } #endif /* CONFIG_EFI_SECURE_BOOT */
-efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
u32 *attributes, efi_uintn_t *data_size,
void *data, u64 *timep)
+efi_status_t __efi_runtime +efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
u32 *attributes, efi_uintn_t *data_size, void *data,
u64 *timep)
{
- char *native_name;
- efi_status_t ret;
- unsigned long in_size;
- const char *val = NULL, *s;
- u64 time = 0;
- u32 attr;
efi_uintn_t old_size;
struct efi_var_entry *var;
u16 *pdata;
if (!variable_name || !vendor || !data_size) return EFI_INVALID_PARAMETER;
- ret = efi_to_native(&native_name, variable_name, vendor);
- if (ret)
return ret;
- EFI_PRINT("get '%s'\n", native_name);
- val = env_get(native_name);
- free(native_name);
- if (!val)
- var = efi_var_mem_find(vendor, variable_name, NULL);
- if (!var) return EFI_NOT_FOUND;
- val = parse_attr(val, &attr, &time);
- if (timep)
*timep = time;
- in_size = *data_size;
- if ((s = prefix(val, "(blob)"))) {
size_t len = strlen(s);
/* number of hexadecimal digits must be even */
if (len & 1)
return EFI_DEVICE_ERROR;
/* two characters per byte: */
len /= 2;
*data_size = len;
if (in_size < len) {
ret = EFI_BUFFER_TOO_SMALL;
goto out;
}
if (!data) {
EFI_PRINT("Variable with no data shouldn't exist.\n");
return EFI_INVALID_PARAMETER;
}
if (hex2bin(data, s, len))
return EFI_DEVICE_ERROR;
EFI_PRINT("got value: \"%s\"\n", s);
- } else if ((s = prefix(val, "(utf8)"))) {
unsigned len = strlen(s) + 1;
*data_size = len;
if (in_size < len) {
ret = EFI_BUFFER_TOO_SMALL;
goto out;
}
if (!data) {
EFI_PRINT("Variable with no data shouldn't exist.\n");
return EFI_INVALID_PARAMETER;
}
memcpy(data, s, len);
((char *)data)[len] = '\0';
EFI_PRINT("got value: \"%s\"\n", (char *)data);
- } else {
EFI_PRINT("invalid value: '%s'\n", val);
return EFI_DEVICE_ERROR;
- }
-out: if (attributes)
*attributes = attr;
- return ret;
-}
-static char *efi_variables_list; -static char *efi_cur_variable;
-/**
- parse_uboot_variable() - parse a u-boot variable and get uefi-related
information
- @variable: whole data of u-boot variable (ie. name=value)
- @variable_name_size: size of variable_name buffer in byte
- @variable_name: name of uefi variable in u16, null-terminated
- @vendor: vendor's guid
- @attributes: attributes
- A uefi variable is encoded into a u-boot variable as described above.
- This function parses such a u-boot variable and retrieve uefi-related
- information into respective parameters. In return, variable_name_size
- is the size of variable name including NULL.
- Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
the entire variable list has been returned,
otherwise non-zero status code
- */
[...]
}
-efi_status_t efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
u16 *variable_name,
efi_guid_t *vendor)
+efi_status_t __efi_runtime +efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
u16 *variable_name, efi_guid_t *vendor)
{
- char *native_name, *variable;
- ssize_t name_len, list_len;
- char regex[256];
- char * const regexlist[] = {regex};
- u32 attributes;
- int i;
- efi_status_t ret;
struct efi_var_entry *var;
efi_uintn_t old_size;
u16 *pdata;
if (!variable_name_size || !variable_name || !vendor) return EFI_INVALID_PARAMETER;
- if (variable_name[0]) {
/* check null-terminated string */
for (i = 0; i < *variable_name_size; i++)
if (!variable_name[i])
break;
if (i >= *variable_name_size)
return EFI_INVALID_PARAMETER;
/* search for the last-returned variable */
ret = efi_to_native(&native_name, variable_name, vendor);
if (ret)
return ret;
- efi_var_mem_find(vendor, variable_name, &var);
name_len = strlen(native_name);
for (variable = efi_variables_list; variable && *variable;) {
if (!strncmp(variable, native_name, name_len) &&
variable[name_len] == '=')
break;
- if (!var)
return EFI_NOT_FOUND;
variable = strchr(variable, '\n');
if (variable)
variable++;
}
- for (pdata = var->name; *pdata; ++pdata)
;
- ++pdata;
free(native_name);
if (!(variable && *variable))
return EFI_INVALID_PARAMETER;
- old_size = *variable_name_size;
- *variable_name_size = (uintptr_t)pdata - (uintptr_t)var->name;
/* next variable */
variable = strchr(variable, '\n');
if (variable)
variable++;
if (!(variable && *variable))
return EFI_NOT_FOUND;
- } else {
/*
*new search: free a list used in the previous search
*/
free(efi_variables_list);
efi_variables_list = NULL;
efi_cur_variable = NULL;
snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
list_len = hexport_r(&env_htab, '\n',
H_MATCH_REGEX | H_MATCH_KEY,
&efi_variables_list, 0, 1, regexlist);
if (list_len <= 1)
return EFI_NOT_FOUND;
variable = efi_variables_list;
- }
- if (old_size < *variable_name_size)
return EFI_BUFFER_TOO_SMALL;
- ret = parse_uboot_variable(variable, variable_name_size, variable_name,
vendor, &attributes);
- efi_memcpy_runtime(variable_name, var->name, *variable_name_size);
- efi_memcpy_runtime(vendor, &var->guid, sizeof(efi_guid_t));
- return ret;
- return EFI_SUCCESS;
}
In order to provide memory backed runtime variable support on the tee-backed variables, I'll have to use identical functions for efi_get_variable_int() and efi_get_next_variable_name_int(). I think it would make more sense to move all the variants that involve talking to the memory based backend to efi_var_common.c. That way you can call the common function in your non-runtime code (as well), while I can call that after EBS, on all my *_runtime variants.
Cheers /Ilias