[Concept,7/7] cmd: Add -s flag to printenv -e for sorted output

Message ID 20250821153528.141740-8-sjg@u-boot.org
State New
Headers
Series efi: Improvements to env print -e |

Commit Message

Simon Glass Aug. 21, 2025, 3:35 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Add support for sorting EFI variables by name when using printenv -e.
The -s flag sorts variables alphabetically before display, useful when
dealing with large numbers of variables.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>

---

 cmd/nvedit.c               |  5 +--
 cmd/nvedit_efi.c           | 31 +++++++++++++++--
 doc/usage/cmd/env.rst      |  4 ++-
 doc/usage/cmd/printenv.rst | 68 ++++++++++++++++++++++++++++++++++++--
 4 files changed, 99 insertions(+), 9 deletions(-)
  

Patch

diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 8dbe8a03fd5..f67c268da84 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1174,7 +1174,7 @@  U_BOOT_LONGHELP(env,
 #endif
 	"env print [-a | name ...] - print environment\n"
 #if defined(CONFIG_CMD_NVEDIT_EFI)
-	"env print -e [-guid guid] [-n] [-v] [name ...] print UEFI environment\n"
+	"env print -e [-guid guid] [-n] [-s] [-v] [name ...] print UEFI environment\n"
 #endif
 #if defined(CONFIG_CMD_RUN)
 	"env run var [...] - run commands in an environment variable\n"
@@ -1221,10 +1221,11 @@  U_BOOT_CMD_COMPLETE(
 	"print environment variables",
 	"[-a]\n    - print [all] values of all environment variables\n"
 #if defined(CONFIG_CMD_NVEDIT_EFI)
-	"printenv -e [-guid guid][-n] [-v] [name ...]\n"
+	"printenv -e [-guid guid][-n] [-s] [-v] [name ...]\n"
 	"    - print UEFI variable 'name' or all the variables\n"
 	"      \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
 	"      \"-n\": suppress dumping variable's value\n"
+	"      \"-s\": sort variables by name\n"
 	"      \"-v\": show GUID, flags, size; also dump (without -n)\n"
 #endif
 	"printenv name ...\n"
diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c
index ce3ab9f785a..5616e73bcfd 100644
--- a/cmd/nvedit_efi.c
+++ b/cmd/nvedit_efi.c
@@ -15,6 +15,7 @@ 
 #include <malloc.h>
 #include <mapmem.h>
 #include <rtc.h>
+#include <sort.h>
 #include <u-boot/uuid.h>
 #include <linux/kernel.h>
 
@@ -142,6 +143,21 @@  out:
 	return result;
 }
 
+/**
+ * var_info_cmp() - compare two var_info structures by name
+ *
+ * @a: First var_info structure
+ * @b: Second var_info structure
+ * Return: comparison result for qsort
+ */
+static int var_info_cmp(const void *a, const void *b)
+{
+	const struct var_info *va = a;
+	const struct var_info *vb = b;
+
+	return u16_strcmp(va->name, vb->name);
+}
+
 /**
  * efi_dump_var_all() - show information about all the UEFI variables
  *
@@ -150,12 +166,14 @@  out:
  * @guid_p:	GUID to filter by, or NULL for all
  * @verbose:	if true, show detailed information
  * @nodump:	if true, don't show hexadecimal dump
+ * @sort:	if true, sort variables by name before printing
  * Return:	CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
  *
  * Show information encoded in all the UEFI variables
  */
 static int efi_dump_var_all(int argc,  char *const argv[],
-			    const efi_guid_t *guid_p, bool verbose, bool nodump)
+			    const efi_guid_t *guid_p, bool verbose, bool nodump,
+			    bool sort)
 {
 	efi_uintn_t buf_size, size;
 	struct var_info *var;
@@ -209,6 +227,9 @@  static int efi_dump_var_all(int argc,  char *const argv[],
 		goto done;
 	}
 
+	if (sort && vars.count > 1)
+		qsort(vars.data, vars.count, sizeof(struct var_info), var_info_cmp);
+
 	alist_for_each(var, &vars)
 		efi_dump_single_var(var->name, &var->guid, verbose, nodump);
 
@@ -233,10 +254,11 @@  done:
  * Return:	CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
  *
  * This function is for "env print -e" or "printenv -e" command:
- *   => env print -e [-v] [-guid <guid> | -all] [var [...]]
+ *   => env print -e [-v] [-s] [-guid <guid> | -all] [var [...]]
  * If one or more variable names are specified, show information
  * named UEFI variables, otherwise show all the UEFI variables.
  * By default, only variable names are shown. Use -v for verbose output.
+ * Use -s to sort variables by name.
  */
 int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
 		     char *const argv[])
@@ -245,6 +267,7 @@  int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
 	efi_guid_t guid;
 	bool verbose = false;
 	bool nodump = false;
+	bool sort = false;
 	efi_status_t ret;
 
 	/* Initialize EFI drivers */
@@ -270,13 +293,15 @@  int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
 			nodump = true;
 		} else if (!strcmp(argv[0], "-v")) {
 			verbose = true;
+		} else if (!strcmp(argv[0], "-s")) {
+			sort = true;
 		} else {
 			return CMD_RET_USAGE;
 		}
 	}
 
 	/* enumerate and show all UEFI variables */
-	return efi_dump_var_all(argc, argv, guid_p, verbose, nodump);
+	return efi_dump_var_all(argc, argv, guid_p, verbose, nodump, sort);
 }
 
 /**
diff --git a/doc/usage/cmd/env.rst b/doc/usage/cmd/env.rst
index a1d90c6fca3..c96dd038f02 100644
--- a/doc/usage/cmd/env.rst
+++ b/doc/usage/cmd/env.rst
@@ -25,7 +25,7 @@  Synopsis
 	env info [-d] [-p] [-q]
 	env load
 	env print [-a | name ...]
-	env print -e [-guid guid] [-n] [-v] [name ...]
+	env print -e [-guid guid] [-n] [-s] [-v] [name ...]
 	env run var [...]
 	env save
 	env select [target]
@@ -233,6 +233,8 @@  in UEFI variables.
         with guid format = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".
     \-n
         don't show hexadecimal dump of value for UEFI variables.
+    \-s
+        sort UEFI variables by name before displaying.
     \-v
         show verbose output for UEFI variables including GUID, attributes, data
         size and hexadecimal dump of value.
diff --git a/doc/usage/cmd/printenv.rst b/doc/usage/cmd/printenv.rst
index cecfcf8bcda..5ba3a6e63f7 100644
--- a/doc/usage/cmd/printenv.rst
+++ b/doc/usage/cmd/printenv.rst
@@ -12,7 +12,7 @@  Synopsis
 ::
 
     printenv [-a] [name ...]
-    printenv -e [-guid guid][-n][-v] [name]
+    printenv -e [-guid guid][-n][-s][-v] [name]
 
 Description
 -----------
@@ -32,6 +32,9 @@  The printenv command is used to print environment or UEFI variables.
 \-n
     don't show hexadecimal dump of value
 
+\-s
+    sort variables by name before displaying
+
 \-v
     show verbose output including GUID, attributes, data size and hexadecimal
     dump of value (if not -n)
@@ -71,7 +74,8 @@  environment variables:
 The next example shows the different output modes when displaying UEFI
 variables and how to specify a vendor GUID. By default, only the variable
 name is shown. The *-v* flag shows full verbose output, while *-n* shows
-details but omits the hexadecimal dump:
+details but omits the hexadecimal dump. The *-s* flag sorts variables by
+name:
 
 ::
 
@@ -86,7 +90,65 @@  details but omits the hexadecimal dump:
         8be4df61-93ca-11d2-aa0d-00e098032b8c (EFI_GLOBAL_VARIABLE_GUID)
         BS|RT|RO, DataSize = 0x6
         00000000: 65 6e 2d 55 53 00                                en-US.
-    =>
+    => print -e -s
+    525400123456
+    525400123456
+    Attempt 1
+    Attempt 2
+    Attempt 3
+    Attempt 4
+    Attempt 5
+    Attempt 6
+    Attempt 7
+    Attempt 8
+    Boot0000
+    Boot0001
+    Boot0002
+    Boot0003
+    BootCurrent
+    BootOptionSupport
+    BootOrder
+    ClientId
+    ConIn
+    ConInDev
+    ConOut
+    ConOutDev
+    ErrOut
+    ErrOutDev
+    HDDP
+    InitialAttemptOrder
+    Key0000
+    Key0001
+    Lang
+    LangCodes
+    MTC
+    MemoryTypeInformation
+    OsIndicationsSupported
+    PlatformLang
+    PlatformLangCodes
+    PlatformRecovery0000
+    SbatLevel
+    Timeout
+    VarErrorFlag
+    cat
+    cd..
+    cd\
+    copy
+    debuglasterror
+    del
+    dir
+    lasterror
+    md
+    mem
+    mount
+    move
+    nonesting
+    path
+    profiles
+    ren
+    uefishellsupport
+    uefishellversion
+    uefiversion
 
 Configuration
 -------------