[U-Boot] [PATCH v5 19/19] efi_loader: variable: rework with new env interfaces

AKASHI Takahiro takahiro.akashi at linaro.org
Thu Sep 5 08:21:33 UTC 2019


In the previous commit, two efi-related contexts were introduced.

With this patch, EFI variables implementation will be modified to
support volatile/non-volatile attribute properly in such away as UEFI
specification expects; If a variable is non-volatile and modified,
its value will be updated in backing storage immediately and preserved
across reboot. If volatile, it will be lost after reboot.

Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
 lib/efi_loader/efi_variable.c | 91 ++++++++++++++++++++++++++++++++---
 1 file changed, 83 insertions(+), 8 deletions(-)

diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index 6687b69a400d..18b9e9e5d9f5 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -185,7 +185,9 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
 
 	EFI_PRINT("get '%s'\n", native_name);
 
-	val = env_get(native_name);
+	val = env_get(ctx_efi, native_name);
+	if (!val)
+		val = env_get(ctx_efi_volatile, native_name);
 	free(native_name);
 	if (!val)
 		return EFI_EXIT(EFI_NOT_FOUND);
@@ -388,12 +390,48 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
 		efi_cur_variable = NULL;
 
 		snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
-		list_len = hexport_r(&env_htab, '\n',
+		list_len = hexport_r(ctx_efi->htab, '\n',
 				     H_MATCH_REGEX | H_MATCH_KEY,
 				     &efi_variables_list, 0, 1, regexlist);
 		/* 1 indicates that no match was found */
-		if (list_len <= 1)
-			return EFI_EXIT(EFI_NOT_FOUND);
+		if (list_len <= 1) {
+			list_len = hexport_r(ctx_efi_volatile->htab, '\n',
+					     H_MATCH_REGEX | H_MATCH_KEY,
+					     &efi_variables_list, 0, 1,
+					     regexlist);
+
+			if (list_len <= 1)
+				return EFI_EXIT(EFI_NOT_FOUND);
+		} else {
+			char *list_volatile, *list_tmp;
+			size_t total_len;
+
+			list_volatile = NULL;
+			total_len = list_len;
+			list_len = hexport_r(ctx_efi_volatile->htab, '\n',
+					     H_MATCH_REGEX | H_MATCH_KEY,
+					     &list_volatile, 0, 1,
+					     regexlist);
+
+			/* concatenate two lists */
+			if (list_len > 1) {
+				total_len += list_len - 1;
+				list_tmp = efi_variables_list;
+
+				efi_variables_list = malloc(total_len);
+				if (efi_variables_list) {
+					strcpy(efi_variables_list, list_tmp);
+					strcat(efi_variables_list,
+					       list_volatile);
+				}
+
+				free(list_tmp);
+				free(list_volatile);
+
+				if (!efi_variables_list)
+					return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+			}
+		}
 
 		variable = efi_variables_list;
 	}
@@ -424,8 +462,9 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
 				     efi_uintn_t data_size, const void *data)
 {
 	char *native_name = NULL, *val = NULL, *s;
+	struct env_context *ctx;
+	u32 attr, non_volatile;
 	efi_status_t ret = EFI_SUCCESS;
-	u32 attr;
 
 	EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
 		  data_size, data);
@@ -447,12 +486,17 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
 
 	if ((data_size == 0) || !(attributes & ACCESS_ATTR)) {
 		/* delete the variable: */
-		env_set(native_name, NULL);
+		env_set(ctx_efi, native_name, NULL);
 		ret = EFI_SUCCESS;
 		goto out;
 	}
 
-	val = env_get(native_name);
+	if (attributes & EFI_VARIABLE_NON_VOLATILE)
+		ctx = ctx_efi;
+	else
+		ctx = ctx_efi_volatile;
+
+	val = env_get(ctx, native_name);
 	if (val) {
 		parse_attr(val, &attr);
 
@@ -485,6 +529,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
 	 * store attributes
 	 * TODO: several attributes are not supported
 	 */
+	non_volatile = (attributes & EFI_VARIABLE_NON_VOLATILE);
 	attributes &= (EFI_VARIABLE_NON_VOLATILE |
 		       EFI_VARIABLE_BOOTSERVICE_ACCESS |
 		       EFI_VARIABLE_RUNTIME_ACCESS);
@@ -512,7 +557,9 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
 
 	EFI_PRINT("setting: %s=%s\n", native_name, val);
 
-	if (env_set(native_name, val))
+	if (env_set(ctx, native_name, val))
+		ret = EFI_DEVICE_ERROR;
+	else if (non_volatile && env_save(ctx))
 		ret = EFI_DEVICE_ERROR;
 
 out:
@@ -619,5 +666,33 @@ void efi_variables_boot_exit_notify(void)
  */
 efi_status_t efi_init_variables(void)
 {
+	int ret;
+
+	/*
+	 * Volatile variables:
+	 * Context for volatile variables has no backing storage
+	 */
+	ret = env_ctx_init(ctx_efi_volatile);
+	if (ret) {
+		printf("Initializing efi variables(volatile) failed\n");
+
+		return EFI_DEVICE_ERROR;
+	}
+
+	/* Non-Volatile variables */
+	ret = env_ctx_init(ctx_efi);
+	if (ret) {
+		printf("Initializing efi variables failed\n");
+
+		return EFI_DEVICE_ERROR;
+	}
+
+	ret = env_load(ctx_efi);
+	if (ret && ret != -ENODEV) {
+		printf("Loading efi variables failed\n");
+
+		return EFI_DEVICE_ERROR;
+	}
+
 	return EFI_SUCCESS;
 }
-- 
2.21.0



More information about the U-Boot mailing list