svn commit: r323260 - head/usr.sbin/efivar

Warner Losh imp at FreeBSD.org
Thu Sep 7 07:30:22 UTC 2017


Author: imp
Date: Thu Sep  7 07:30:19 2017
New Revision: 323260
URL: https://svnweb.freebsd.org/changeset/base/323260

Log:
  Create efi utility printing routines
  
  Split out asciidump, utf8dump, bindump, and hexdump into a separate
  file efiutil.c. Implement new efi_print_load_option for printing out
  the EFI_LOADER_OPTION data structure used to specify different options
  to the UEFI boot manager.
  
  Sponsored by: Netflix

Added:
  head/usr.sbin/efivar/efiutil.c   (contents, props changed)
  head/usr.sbin/efivar/efiutil.h   (contents, props changed)
Modified:
  head/usr.sbin/efivar/Makefile
  head/usr.sbin/efivar/efivar.c

Modified: head/usr.sbin/efivar/Makefile
==============================================================================
--- head/usr.sbin/efivar/Makefile	Thu Sep  7 07:30:14 2017	(r323259)
+++ head/usr.sbin/efivar/Makefile	Thu Sep  7 07:30:19 2017	(r323260)
@@ -5,6 +5,8 @@ MAN=	efivar.8
 
 LIBADD= efivar
 
+SRCS=	efivar.c efiutil.c
+
 EFIBOOT=${SRCTOP}/sys/boot/efi
 CFLAGS+=	-I${EFIBOOT}/include
 

Added: head/usr.sbin/efivar/efiutil.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/efivar/efiutil.c	Thu Sep  7 07:30:19 2017	(r323260)
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <efivar.h>
+#include <efivar-dp.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "efiutil.h"
+#include "efichar.h"
+#include <efivar-dp.h>
+
+/*
+ * Dump the data as ASCII data, which is a pretty
+ * printed form 
+ */
+void
+asciidump(uint8_t *data, size_t datalen)
+{
+	size_t i;
+	int len;
+
+	len = 0;
+	for (i = 0; i < datalen; i++) {
+		if (isprint(data[i])) {
+			len++;
+			if (len > 80) {
+				len = 0;
+				printf("\n");
+			}
+			printf("%c", data[i]);
+		} else {
+			len +=3;
+			if (len > 80) {
+				len = 0;
+				printf("\n");
+			}
+			printf("%%%02x", data[i]);
+		}
+	}
+	printf("\n");
+}
+
+void
+utf8dump(uint8_t *data, size_t datalen)
+{
+	char *utf8 = NULL;
+	efi_char *ucs2;
+
+	/*
+	 * NUL terminate the string. Not all strings need it, but some
+	 * do and an extra NUL won't change what's printed.
+	 */
+	ucs2 = malloc(datalen + sizeof(efi_char));
+	memcpy(ucs2, data, datalen);
+	ucs2[datalen / sizeof(efi_char)] = 0;
+	ucs2_to_utf8(ucs2, &utf8);
+	printf("%s\n", utf8);
+	free(utf8);
+	free(ucs2);
+}
+
+void
+hexdump(uint8_t *data, size_t datalen)
+{
+	size_t i;
+
+	for (i = 0; i < datalen; i++) {
+		if (i % 16 == 0) {
+			if (i != 0)
+				printf("\n");
+			printf("%04x: ", (int)i);
+		}
+		printf("%02x ", data[i]);
+	}
+	printf("\n");
+}
+
+void
+bindump(uint8_t *data, size_t datalen)
+{
+	write(1, data, datalen);
+}
+
+#define LOAD_OPTION_ACTIVE 1
+
+void
+efi_print_load_option(uint8_t *data, size_t datalen, int Aflag, int bflag, int uflag)
+{
+	uint8_t *ep = data + datalen;
+	uint8_t *walker = data;
+	uint32_t attr;
+	uint16_t fplen;
+	efi_char *descr;
+	efidp dp, edp;
+	char *str;
+	char buf[1024];
+	int len;
+	void *opt;
+	int optlen;
+
+	if (datalen < sizeof(attr) + sizeof(fplen) + sizeof(efi_char))
+		return;
+	// First 4 bytes are attribute flags
+	attr = le32dec(walker);
+	walker += sizeof(attr);
+	// Next two bytes are length of the file paths
+	fplen = le16dec(walker);
+	walker += sizeof(fplen);
+	// Next we have a 0 terminated UCS2 string that we know to be aligned
+	descr = (efi_char *)(intptr_t)(void *)walker;
+	len = ucs2len(descr); // XXX need to sanity check that len < (datalen - (ep - walker) / 2)
+	walker += (len + 1) * sizeof(efi_char);
+	if (walker > ep)
+		return;
+	// Now we have fplen bytes worth of file path stuff
+	dp = (efidp)walker;
+	walker += fplen;
+	if (walker > ep)
+		return;
+	edp = (efidp)walker;
+	// Everything left is the binary option args
+	opt = walker;
+	optlen = ep - walker;
+	// We got to here, everything is good
+	printf("%c ", attr & LOAD_OPTION_ACTIVE ? '*' : ' ');
+	ucs2_to_utf8(descr, &str);
+	printf("%s", str);
+	free(str);
+	while (dp < edp) {
+		efidp_format_device_path(buf, sizeof(buf), dp,
+		    (intptr_t)(void *)edp - (intptr_t)(void *)dp);
+		dp = (efidp)((char *)dp + efidp_size(dp));
+		printf(" %s\n", buf);
+	}
+	if (optlen == 0)
+		return;
+	printf("Options: ");
+	if (Aflag)
+		asciidump(opt, optlen);
+	else if (bflag)
+		bindump(opt, optlen);
+	else if (uflag)
+		utf8dump(opt, optlen);
+	else
+		hexdump(opt, optlen);
+}

Added: head/usr.sbin/efivar/efiutil.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/efivar/efiutil.h	Thu Sep  7 07:30:19 2017	(r323260)
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2017 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * differnt routines to dump data.
+ */
+
+void asciidump(uint8_t *data, size_t datalen);
+void bindump(uint8_t *data, size_t datalen);
+void efi_print_load_option(uint8_t *, size_t, int, int, int);
+void hexdump(uint8_t *data, size_t datalen);
+void utf8dump(uint8_t *data, size_t datalen);
+

Modified: head/usr.sbin/efivar/efivar.c
==============================================================================
--- head/usr.sbin/efivar/efivar.c	Thu Sep  7 07:30:14 2017	(r323259)
+++ head/usr.sbin/efivar/efivar.c	Thu Sep  7 07:30:19 2017	(r323260)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include "efiutil.h"
 #include "efichar.h"
 
 /* options descriptor */
@@ -54,6 +55,7 @@ static struct option longopts[] = {
 	{ "hex",		no_argument,		NULL,	'H' },
 	{ "list-guids",		no_argument,		NULL,	'L' },
 	{ "list",		no_argument,		NULL,	'l' },
+	{ "load-option",	no_argument,		NULL,	'O' },
 	{ "name",		required_argument,	NULL,	'n' },
 	{ "no-name",		no_argument,		NULL,	'N' },
 	{ "print",		no_argument,		NULL,	'p' },
@@ -66,7 +68,7 @@ static struct option longopts[] = {
 
 
 static int aflag, Aflag, bflag, dflag, Dflag, gflag, Hflag, Nflag,
-	lflag, Lflag, Rflag, wflag, pflag, uflag;
+	lflag, Lflag, Rflag, wflag, pflag, uflag, load_opt_flag;
 static char *varname;
 static u_long attrib = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
 
@@ -74,10 +76,11 @@ static void
 usage(void)
 {
 
-	errx(1, "efivar [-abdDHlLNpRtw] [-n name] [-f file] [--append] [--ascii]\n"
+	errx(1, "efivar [-abdDHlLNpRtuw] [-n name] [-f file] [--append] [--ascii]\n"
 	    "\t[--attributes] [--binary] [--delete] [--fromfile file] [--hex]\n"
-	    "\t[--list-guids] [--list] [--name name] [--no-name] [--print]\n"
-	    "\t[--print-decimal] [--raw-guid] [--write] name[=value]");
+	    "\t[--list-guids] [--list] [--load-option] [--name name] [--no-name]\n"
+	    "\t[--print] [--print-decimal] [--raw-guid] [--utf8] [--write]\n"
+	    "\tname[=value]");
 }
 
 static void
@@ -149,80 +152,6 @@ write_variable(char *name, char *val)
 }
 
 static void
-asciidump(uint8_t *data, size_t datalen)
-{
-	size_t i;
-	int len;
-
-	len = 0;
-	if (!Nflag)
-		printf("\n");
-	for (i = 0; i < datalen; i++) {
-		if (isprint(data[i])) {
-			len++;
-			if (len > 80) {
-				len = 0;
-				printf("\n");
-			}
-			printf("%c", data[i]);
-		} else {
-			len +=3;
-			if (len > 80) {
-				len = 0;
-				printf("\n");
-			}
-			printf("%%%02x", data[i]);
-		}
-	}
-	printf("\n");
-}
-
-static void
-utf8dump(uint8_t *data, size_t datalen)
-{
-	char *utf8 = NULL;
-	efi_char *ucs2;
-
-	/*
-	 * NUL terminate the string. Not all strings need it, but some
-	 * do and an extra NUL won't change what's printed.
-	 */
-	ucs2 = malloc(datalen + sizeof(efi_char));
-	memcpy(ucs2, data, datalen);
-	ucs2[datalen / sizeof(efi_char)] = 0;
-	ucs2_to_utf8(ucs2, &utf8);
-	if (!Nflag)
-		printf("\n");
-	printf("%s\n", utf8);
-	free(utf8);
-	free(ucs2);
-}
-
-static void
-hexdump(uint8_t *data, size_t datalen)
-{
-	size_t i;
-
-	if (!Nflag)
-		printf("\n");
-	for (i = 0; i < datalen; i++) {
-		if (i % 16 == 0) {
-			if (i != 0)
-				printf("\n");
-			printf("%04x: ", (int)i);
-		}
-		printf("%02x ", data[i]);
-	}
-	printf("\n");
-}
-
-static void
-bindump(uint8_t *data, size_t datalen)
-{
-	write(1, data, datalen);
-}
-
-static void
 devpath_dump(uint8_t *data, size_t datalen)
 {
 	char buffer[1024];
@@ -265,8 +194,10 @@ print_var(efi_guid_t *guid, char *name)
 			err(1, "%s-%s", gname, name);
 
 		if (!Nflag)
-			printf("%s-%s", gname, name);
-		if (Aflag)
+			printf("%s-%s\n", gname, name);
+		if (load_opt_flag)
+			efi_print_load_option(data, datalen, Aflag, bflag, uflag);
+		else if (Aflag)
 			asciidump(data, datalen);
 		else if (uflag)
 			utf8dump(data, datalen);
@@ -324,7 +255,7 @@ parse_args(int argc, char **argv)
 {
 	int ch, i;
 
-	while ((ch = getopt_long(argc, argv, "aAbdDf:gHlLNn:pRt:w",
+	while ((ch = getopt_long(argc, argv, "aAbdDf:gHlLNn:OpRt:w",
 		    longopts, NULL)) != -1) {
 		switch (ch) {
 		case 'a':
@@ -359,6 +290,9 @@ parse_args(int argc, char **argv)
 			break;
 		case 'N':
 			Nflag++;
+			break;
+		case 'O':
+			load_opt_flag++;
 			break;
 		case 'p':
 			pflag++;


More information about the svn-src-head mailing list