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.g...@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

Reply via email to