[PATCH v3 15/17] efi_loader: use memory based variable storage
ilias.apalodimas at linaro.org
ilias.apalodimas at linaro.org
Thu Jul 9 16:49:04 CEST 2020
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 at 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
More information about the U-Boot
mailing list