From owner-svn-src-all@freebsd.org Thu Sep 7 07:30:21 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id CBB30E0DB07; Thu, 7 Sep 2017 07:30:21 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5633463557; Thu, 7 Sep 2017 07:30:21 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v877UKXl007027; Thu, 7 Sep 2017 07:30:20 GMT (envelope-from imp@FreeBSD.org) Received: (from imp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v877UKdr007023; Thu, 7 Sep 2017 07:30:20 GMT (envelope-from imp@FreeBSD.org) Message-Id: <201709070730.v877UKdr007023@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: imp set sender to imp@FreeBSD.org using -f From: Warner Losh Date: Thu, 7 Sep 2017 07:30:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r323260 - head/usr.sbin/efivar X-SVN-Group: head X-SVN-Commit-Author: imp X-SVN-Commit-Paths: head/usr.sbin/efivar X-SVN-Commit-Revision: 323260 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Sep 2017 07:30:22 -0000 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "efiutil.h" +#include "efichar.h" +#include + +/* + * 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 #include #include +#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++;