[Concept,12/20] efi: Use abuf when reading EFI variables

Message ID 20250828020732.981415-13-sjg@u-boot.org
State New
Headers
Series efi: App and devicetree improvements |

Commit Message

Simon Glass Aug. 28, 2025, 2:07 a.m. UTC
  From: Simon Glass <sjg@chromium.org>

The abuf interface provides a nicer abstraction of the data and size of
EFI variables.

Create a new efi_read_var() function and export it so it can be used
elsewhere. Adjust the existing efi_dump_single_var() to use it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/nvedit_efi.c | 62 ++++++++++++++++++++++++++++++++----------------
 include/efi.h    | 15 ++++++++++++
 2 files changed, 56 insertions(+), 21 deletions(-)
  

Patch

diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c
index 5616e73bcfd..45d6a8ef67a 100644
--- a/cmd/nvedit_efi.c
+++ b/cmd/nvedit_efi.c
@@ -5,6 +5,7 @@ 
  *  Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
  */
 
+#include <abuf.h>
 #include <charset.h>
 #include <command.h>
 #include <efi_loader.h>
@@ -50,6 +51,36 @@  struct var_info {
 	efi_guid_t guid;
 };
 
+int efi_read_var(const u16 *name, const efi_guid_t *guid, u32 *attrp,
+		 struct abuf *buf, u64 *timep)
+{
+	efi_uintn_t size;
+	efi_status_t eret;
+	u32 attr;
+	u64 time;
+
+	abuf_init(buf);
+	size = 0;
+	eret = efi_get_variable_int(name, guid, &attr, &size, NULL, &time);
+	if (eret == EFI_BUFFER_TOO_SMALL) {
+		if (!abuf_realloc(buf, size))
+			return -ENOMEM;
+
+		eret = efi_get_variable_int(name, guid, &attr, &size, buf->data,
+					    &time);
+	}
+	if (eret == EFI_NOT_FOUND)
+		return -ENOENT;
+	if (eret != EFI_SUCCESS)
+		return -EBADF;
+	if (attrp)
+		*attrp = attr;
+	if (timep)
+		*timep = time;
+
+	return 0;
+}
+
 /**
  * efi_dump_single_var() - show information about a UEFI variable
  *
@@ -63,30 +94,19 @@  struct var_info {
 static void efi_dump_single_var(u16 *name, const efi_guid_t *guid,
 				 bool verbose, bool nodump)
 {
-	u32 attributes;
-	u8 *data;
-	u64 time;
 	struct rtc_time tm;
-	efi_uintn_t size;
+	u32 attributes;
+	struct abuf buf;
 	int count, i;
-	efi_status_t ret;
-
-	data = NULL;
-	size = 0;
-	ret = efi_get_variable_int(name, guid, &attributes, &size, data, &time);
-	if (ret == EFI_BUFFER_TOO_SMALL) {
-		data = malloc(size);
-		if (!data)
-			goto out;
+	u64 time;
+	int ret;
 
-		ret = efi_get_variable_int(name, guid, &attributes, &size,
-					   data, &time);
-	}
-	if (ret == EFI_NOT_FOUND) {
+	ret = efi_read_var(name, guid, &attributes, &buf, &time);
+	if (ret == -ENOENT) {
 		printf("Error: \"%ls\" not defined\n", name);
 		goto out;
 	}
-	if (ret != EFI_SUCCESS)
+	if (ret)
 		goto out;
 
 	if (verbose) {
@@ -103,16 +123,16 @@  static void efi_dump_single_var(u16 *name, const efi_guid_t *guid,
 				count++;
 				puts(efi_var_attrs[i].text);
 			}
-		printf(", DataSize = 0x%zx\n", size);
+		printf(", DataSize = 0x%zx\n", buf.size);
 		if (!nodump)
 			print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
-				       data, size, true);
+				       buf.data, buf.size, true);
 	} else {
 		printf("%ls\n", name);
 	}
 
 out:
-	free(data);
+	abuf_uninit(&buf);
 }
 
 static bool match_name(int argc, char *const argv[], u16 *var_name16)
diff --git a/include/efi.h b/include/efi.h
index c07717811da..07d07050c01 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -23,6 +23,7 @@ 
 #include <net.h>
 #endif
 
+struct abuf;
 struct udevice;
 
 /* Type INTN in UEFI specification */
@@ -863,4 +864,18 @@  efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size,
 int efi_dp_from_bootdev(const struct udevice *dev,
 			const struct efi_device_path **dpp);
 
+/**
+ * efi_read_var() - Read an EFI variable
+ *
+ * @name: Name of variable to read
+ * @guid: GUID for the variable
+ * @attrp: Returns variable attributes if non-NULL, on success
+ * @buf: Returns allocated buffer containing the value
+ * @timep: Returns the timestamp for the variable if non_NULL
+ * Return: 0 if OK, -ENOENT if the variable was not found, -EBADF if something
+ * went wrong when reading
+ */
+int efi_read_var(const u16 *name, const efi_guid_t *guid, u32 *attrp,
+		 struct abuf *buf, u64 *timep);
+
 #endif /* _LINUX_EFI_H */