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