From 0749c8fef6dcfdd9b299df9e16597a41c8d0f6a3 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Tue, 21 Mar 2017 19:57:20 +0100
Subject: [PATCH 5/5] WIP upgrade efivar(8)

---
 usr.sbin/efivar/efivar.8 | 53 +++++++++++++++++++++----------
 usr.sbin/efivar/efivar.c | 81 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 101 insertions(+), 33 deletions(-)

diff --git a/usr.sbin/efivar/efivar.8 b/usr.sbin/efivar/efivar.8
index 4abf2e8247..b1ef0f7c44 100644
--- a/usr.sbin/efivar/efivar.8
+++ b/usr.sbin/efivar/efivar.8
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2003 Netflix, Inc
+.\" Copyright (c) 2017 Netflix, Inc
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,9 +22,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/efivar/efivar.8 307224 2016-10-13 17:03:54Z imp $
+.\" $FreeBSD: head/usr.sbin/efivar/efivar.8 314927 2017-03-09 00:31:36Z imp $
 .\"
-.Dd September 29, 2016
+.Dd March 20, 2017
 .Dt EFIVAR 8
 .Os
 .Sh NAME
@@ -40,7 +40,9 @@
 .Op Fl -attributes
 .Op Fl -binary
 .Op Fl -delete
+.Op Fl -device-path
 .Op Fl -fromfile Ar file
+.Op Fl -guid
 .Op Fl -hex
 .Op Fl -list-guids
 .Op Fl -list
@@ -50,7 +52,6 @@
 .Op Fl -print-decimal
 .Op Fl -raw-guid
 .Op Fl -write
-.Ar name Ns Op = Ns Ar value
 .Sh DESCRIPTION
 This program manages
 .Dq Unified Extensible Firmware Interface
@@ -116,6 +117,13 @@ flags.
 No
 .Ar value
 may be specified.
+.It Fl d Fl -device Fl -device-path
+Interpret the variables printed as UEFI device paths and print the
+UEFI standard string representation.
+.It Fl g Fl -guid
+If the flag is specified, guids are converted to names if they are known (and
+show up in
+.Fl -list-guids ).
 .It Fl H Fl -hex
 List variable data as a hex dump.
 .It Fl L Fl -list-guids
@@ -133,34 +141,45 @@ flag is also listed, their values will be displayed.
 Do not display the variable name.
 .It Fl p Fl -print
 Print the value of the variable.
-.It Fl d Fl -print-decimal
-Treat the value of the variable as a number and print it as a
-decimal.
-This is currently unimplemented.
 .It Fl R Fl -raw-guid
 Do not substitute well known names for GUID numeric values in output.
 .It Fl w Fl -write
-Write (replace) the variable specified with the value specified.
+Write (replace) the variable specified with the value specified from
+standard input.
+No command line option to do this is available since UEFI variables
+are binary structures rather than strings.
+.Xr echo 1
+.Fl n
+can be used to specify simple strings.
 .It Ar name
 Display the
 .Ar name
 environment variable.
-.It Ar name Ns = Ns Ar value
-Set the specified
-.Ar name
-to
-.Ar value .
-This is not yet implemented.
-.El
 .Sh COMPATIBILITY
 The
 .Nm
 program is intended to be compatible (strict superset) with a program
 of the same name included in the Red Hat libefivar package.
+.Pp
+Except the
+.Fl d
+and
+.Fl -print-decimal
+flags are not implmenented and never will be.
+The
+.Fl d
+flag is a short-hand for
+.Fl -device-path .
 .Sh SEE ALSO
-.Xr efivar 3
+.Xr efivar 3 ,
+.Xr efidp 8
 .Pp
 Appendix A of the UEFI specification has the format for GUIDs.
 All GUIDs
 .Pq Dq Globally Unique Identifiers
 have the format described in RFC 4122.
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 12.0 .
diff --git a/usr.sbin/efivar/efivar.c b/usr.sbin/efivar/efivar.c
index 5c62564087..40db6086e6 100644
--- a/usr.sbin/efivar/efivar.c
+++ b/usr.sbin/efivar/efivar.c
@@ -25,10 +25,11 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/efivar/efivar.c 307390 2016-10-16 05:53:18Z imp $");
+__FBSDID("$FreeBSD: head/usr.sbin/efivar/efivar.c 314927 2017-03-09 00:31:36Z imp $");
 
 #include <ctype.h>
 #include <efivar.h>
+#include <efivar-dp.h>
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
@@ -45,7 +46,10 @@ static struct option longopts[] = {
 	{ "attributes",		required_argument,	NULL,	't' },
 	{ "binary",		no_argument,		NULL,	'b' },
 	{ "delete",		no_argument,		NULL,   'D' },
+	{ "device",		no_argument,		NULL,   'd' },
+	{ "device-path",	no_argument,		NULL,   'd' },
 	{ "fromfile",		required_argument,	NULL,	'f' },
+	{ "guid",		no_argument,		NULL,	'g' },
 	{ "hex",		no_argument,		NULL,	'H' },
 	{ "list-guids",		no_argument,		NULL,	'L' },
 	{ "list",		no_argument,		NULL,	'l' },
@@ -59,7 +63,7 @@ static struct option longopts[] = {
 };
 
 
-static int aflag, Aflag, bflag, dflag, Dflag, Hflag, Nflag,
+static int aflag, Aflag, bflag, dflag, Dflag, gflag, Hflag, Nflag,
 	lflag, Lflag, Rflag, wflag, pflag;
 static char *varname;
 static u_long attrib = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
@@ -84,7 +88,7 @@ breakdown_name(char *name, efi_guid_t *guid, char **vname)
 		errx(1, "Invalid name: %s", name);
 	*vname = cp + 1;
 	*cp = '\0';
-	if (efi_str_to_guid(name, guid) < 0)
+	if (efi_name_to_guid(name, guid) < 0)
 		errx(1, "Invalid guid %s", name);
 }
 
@@ -196,6 +200,32 @@ bindump(uint8_t *data, size_t datalen)
 }
 
 static void
+devpath_dump(uint8_t *data, size_t datalen)
+{
+	char buffer[1024];
+
+	efidp_format_device_path(buffer, sizeof(buffer),
+	    (const_efidp)data, datalen);
+	if (!Nflag)
+		printf(": ");
+	printf("%s\n", buffer);
+}
+
+static void
+pretty_guid(efi_guid_t *guid, char **gname)
+{
+	char *pretty = NULL;
+
+	if (gflag)
+		efi_guid_to_name(guid, &pretty);
+
+	if (pretty == NULL)
+		efi_guid_to_str(guid, gname);
+	else
+		*gname = pretty;
+}
+
+static void
 print_var(efi_guid_t *guid, char *name)
 {
 	uint32_t att;
@@ -204,22 +234,25 @@ print_var(efi_guid_t *guid, char *name)
 	char *gname;
 	int rv;
 
-	efi_guid_to_str(guid, &gname);
-	if (!Nflag)
-		printf("%s-%s", gname, name);
+	pretty_guid(guid, &gname);
 	if (pflag) {
 		rv = efi_get_variable(*guid, name, &data, &datalen, &att);
 
 		if (rv < 0)
-			printf("\n --- Error getting value --- %d", errno);
-		else {
-			if (Aflag)
-				asciidump(data, datalen);
-			else if (bflag)
-				bindump(data, datalen);
-			else
-				hexdump(data, datalen);
-		}
+			err(1, "%s-%s", gname, name);
+
+		if (!Nflag)
+			printf("%s-%s", gname, name);
+		if (Aflag)
+			asciidump(data, datalen);
+		else if (bflag)
+			bindump(data, datalen);
+		else if (dflag)
+			devpath_dump(data, datalen);
+		else
+			hexdump(data, datalen);
+	} else {
+		printf("%s-%s", gname, name);
 	}
 	free(gname);
 	if (!Nflag)
@@ -251,11 +284,22 @@ print_variables(void)
 }
 
 static void
+print_known_guid(void)
+{
+	struct uuid_table *tbl;
+	int i, n;
+
+	n = efi_known_guid(&tbl);
+	for (i = 0; i < n; i++)
+		printf("%s %s\n", tbl[i].uuid_str, tbl[i].name);
+}
+
+static void
 parse_args(int argc, char **argv)
 {
 	int ch, i;
 
-	while ((ch = getopt_long(argc, argv, "aAbdDf:HlLNn:pRt:w",
+	while ((ch = getopt_long(argc, argv, "aAbdDf:gHlLNn:pRt:w",
 		    longopts, NULL)) != -1) {
 		switch (ch) {
 		case 'a':
@@ -273,6 +317,9 @@ parse_args(int argc, char **argv)
 		case 'D':
 			Dflag++;
 			break;
+		case 'g':
+			gflag++;
+			break;
 		case 'H':
 			Hflag++;
 			break;
@@ -332,6 +379,8 @@ parse_args(int argc, char **argv)
 		delete_variable(varname);
 	else if (wflag)
 		write_variable(varname, NULL);
+	else if (Lflag)
+		print_known_guid();
 	else if (varname) {
 		pflag++;
 		print_variable(varname);
-- 
2.11.0

