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++;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to