14b844f8dSWarner Losh /*- 24b844f8dSWarner Losh * Copyright (c) 2016 Netflix, Inc. 34b844f8dSWarner Losh * All rights reserved. 44b844f8dSWarner Losh * 54b844f8dSWarner Losh * Redistribution and use in source and binary forms, with or without 64b844f8dSWarner Losh * modification, are permitted provided that the following conditions 74b844f8dSWarner Losh * are met: 84b844f8dSWarner Losh * 1. Redistributions of source code must retain the above copyright 94b844f8dSWarner Losh * notice, this list of conditions and the following disclaimer. 104b844f8dSWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 114b844f8dSWarner Losh * notice, this list of conditions and the following disclaimer in the 124b844f8dSWarner Losh * documentation and/or other materials provided with the distribution. 134b844f8dSWarner Losh * 14*b2a7ac48SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154b844f8dSWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164b844f8dSWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*b2a7ac48SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184b844f8dSWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194b844f8dSWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204b844f8dSWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214b844f8dSWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224b844f8dSWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234b844f8dSWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244b844f8dSWarner Losh * SUCH DAMAGE. 254b844f8dSWarner Losh */ 264b844f8dSWarner Losh 274b844f8dSWarner Losh #include <sys/cdefs.h> 284b844f8dSWarner Losh __FBSDID("$FreeBSD$"); 294b844f8dSWarner Losh 304b844f8dSWarner Losh #include <ctype.h> 314b844f8dSWarner Losh #include <efivar.h> 324b844f8dSWarner Losh #include <err.h> 334b844f8dSWarner Losh #include <errno.h> 344b844f8dSWarner Losh #include <getopt.h> 354b844f8dSWarner Losh #include <stddef.h> 364b844f8dSWarner Losh #include <stdio.h> 374b844f8dSWarner Losh #include <stdlib.h> 384b844f8dSWarner Losh #include <string.h> 394b844f8dSWarner Losh #include <unistd.h> 404b844f8dSWarner Losh 414b844f8dSWarner Losh /* options descriptor */ 424b844f8dSWarner Losh static struct option longopts[] = { 434b844f8dSWarner Losh { "append", no_argument, NULL, 'a' }, 444b844f8dSWarner Losh { "ascii", no_argument, NULL, 'A' }, 454b844f8dSWarner Losh { "attributes", required_argument, NULL, 't' }, 464b844f8dSWarner Losh { "binary", no_argument, NULL, 'b' }, 474b844f8dSWarner Losh { "delete", no_argument, NULL, 'D' }, 484b844f8dSWarner Losh { "fromfile", required_argument, NULL, 'f' }, 494b844f8dSWarner Losh { "hex", no_argument, NULL, 'H' }, 504b844f8dSWarner Losh { "list-guids", no_argument, NULL, 'L' }, 514b844f8dSWarner Losh { "list", no_argument, NULL, 'l' }, 524b844f8dSWarner Losh { "name", required_argument, NULL, 'n' }, 534b844f8dSWarner Losh { "no-name", no_argument, NULL, 'N' }, 544b844f8dSWarner Losh { "print", no_argument, NULL, 'p' }, 554b844f8dSWarner Losh { "print-decimal", no_argument, NULL, 'd' }, 564b844f8dSWarner Losh { "raw-guid", no_argument, NULL, 'R' }, 574b844f8dSWarner Losh { "write", no_argument, NULL, 'w' }, 584b844f8dSWarner Losh { NULL, 0, NULL, 0 } 594b844f8dSWarner Losh }; 604b844f8dSWarner Losh 614b844f8dSWarner Losh 624b844f8dSWarner Losh static int aflag, Aflag, bflag, dflag, Dflag, Hflag, Nflag, 634b844f8dSWarner Losh lflag, Lflag, Rflag, wflag, pflag; 644b844f8dSWarner Losh static char *varname; 654b844f8dSWarner Losh static u_long attrib = 0x7; 664b844f8dSWarner Losh 674b844f8dSWarner Losh static void 684b844f8dSWarner Losh usage(void) 694b844f8dSWarner Losh { 704b844f8dSWarner Losh 714b844f8dSWarner Losh errx(1, "efivar [-abdDHlLNpRtw] [-n name] [-f file] [--append] [--ascii]\n" 724b844f8dSWarner Losh "\t[--attributes] [--binary] [--delete] [--fromfile file] [--hex]\n" 734b844f8dSWarner Losh "\t[--list-guids] [--list] [--name name] [--no-name] [--print]\n" 744b844f8dSWarner Losh "\t[--print-decimal] [--raw-guid] [--write] name[=value]"); 754b844f8dSWarner Losh } 764b844f8dSWarner Losh 774b844f8dSWarner Losh static void 784b844f8dSWarner Losh breakdown_name(char *name, efi_guid_t *guid, char **vname) 794b844f8dSWarner Losh { 804b844f8dSWarner Losh char *cp; 814b844f8dSWarner Losh 824b844f8dSWarner Losh cp = strrchr(name, '-'); 834b844f8dSWarner Losh if (cp == NULL) 844b844f8dSWarner Losh errx(1, "Invalid name: %s", name); 854b844f8dSWarner Losh *vname = cp + 1; 864b844f8dSWarner Losh *cp = '\0'; 874b844f8dSWarner Losh if (efi_str_to_guid(name, guid) < 0) 884b844f8dSWarner Losh errx(1, "Invalid guid %s", name); 894b844f8dSWarner Losh } 904b844f8dSWarner Losh 914b844f8dSWarner Losh static uint8_t * 924b844f8dSWarner Losh get_value(char *val, size_t *datalen) 934b844f8dSWarner Losh { 944b844f8dSWarner Losh static char buffer[16*1024]; 954b844f8dSWarner Losh 964b844f8dSWarner Losh if (val != NULL) { 974b844f8dSWarner Losh *datalen = strlen(val); 984b844f8dSWarner Losh return ((uint8_t *)val); 994b844f8dSWarner Losh } 1004b844f8dSWarner Losh /* Read from stdin */ 1014b844f8dSWarner Losh *datalen = sizeof(buffer); 1024b844f8dSWarner Losh *datalen = read(0, buffer, *datalen); 1034b844f8dSWarner Losh return ((uint8_t *)buffer); 1044b844f8dSWarner Losh } 1054b844f8dSWarner Losh 1064b844f8dSWarner Losh static void 1074b844f8dSWarner Losh append_variable(char *name, char *val) 1084b844f8dSWarner Losh { 1094b844f8dSWarner Losh char *vname; 1104b844f8dSWarner Losh efi_guid_t guid; 1114b844f8dSWarner Losh size_t datalen; 1124b844f8dSWarner Losh uint8_t *data; 1134b844f8dSWarner Losh 1144b844f8dSWarner Losh breakdown_name(name, &guid, &vname); 1154b844f8dSWarner Losh data = get_value(val, &datalen); 1164b844f8dSWarner Losh if (efi_append_variable(guid, vname, data, datalen, attrib) < 0) 1174b844f8dSWarner Losh err(1, "efi_append_variable"); 1184b844f8dSWarner Losh } 1194b844f8dSWarner Losh 1204b844f8dSWarner Losh static void 1214b844f8dSWarner Losh delete_variable(char *name) 1224b844f8dSWarner Losh { 1234b844f8dSWarner Losh char *vname; 1244b844f8dSWarner Losh efi_guid_t guid; 1254b844f8dSWarner Losh 1264b844f8dSWarner Losh breakdown_name(name, &guid, &vname); 1274b844f8dSWarner Losh if (efi_del_variable(guid, vname) < 0) 1284b844f8dSWarner Losh err(1, "efi_del_variable"); 1294b844f8dSWarner Losh } 1304b844f8dSWarner Losh 1314b844f8dSWarner Losh static void 1324b844f8dSWarner Losh write_variable(char *name, char *val) 1334b844f8dSWarner Losh { 1344b844f8dSWarner Losh char *vname; 1354b844f8dSWarner Losh efi_guid_t guid; 1364b844f8dSWarner Losh size_t datalen; 1374b844f8dSWarner Losh uint8_t *data; 1384b844f8dSWarner Losh 1394b844f8dSWarner Losh breakdown_name(name, &guid, &vname); 1404b844f8dSWarner Losh data = get_value(val, &datalen); 1414b844f8dSWarner Losh if (efi_set_variable(guid, vname, data, datalen, attrib, 0) < 0) 1424b844f8dSWarner Losh err(1, "efi_set_variable"); 1434b844f8dSWarner Losh } 1444b844f8dSWarner Losh 1454b844f8dSWarner Losh static void 1464b844f8dSWarner Losh asciidump(uint8_t *data, size_t datalen) 1474b844f8dSWarner Losh { 1484b844f8dSWarner Losh size_t i; 1494b844f8dSWarner Losh int len; 1504b844f8dSWarner Losh 1514b844f8dSWarner Losh len = 0; 1524b844f8dSWarner Losh if (!Nflag) 1534b844f8dSWarner Losh printf("\n"); 1544b844f8dSWarner Losh for (i = 0; i < datalen; i++) { 1554b844f8dSWarner Losh if (isprint(data[i])) { 1564b844f8dSWarner Losh len++; 1574b844f8dSWarner Losh if (len > 80) { 1584b844f8dSWarner Losh len = 0; 1594b844f8dSWarner Losh printf("\n"); 1604b844f8dSWarner Losh } 1614b844f8dSWarner Losh printf("%c", data[i]); 1624b844f8dSWarner Losh } else { 1634b844f8dSWarner Losh len +=3; 1644b844f8dSWarner Losh if (len > 80) { 1654b844f8dSWarner Losh len = 0; 1664b844f8dSWarner Losh printf("\n"); 1674b844f8dSWarner Losh } 1684b844f8dSWarner Losh printf("%%%02x", data[i]); 1694b844f8dSWarner Losh } 1704b844f8dSWarner Losh } 1714b844f8dSWarner Losh printf("\n"); 1724b844f8dSWarner Losh } 1734b844f8dSWarner Losh 1744b844f8dSWarner Losh static void 1754b844f8dSWarner Losh hexdump(uint8_t *data, size_t datalen) 1764b844f8dSWarner Losh { 1774b844f8dSWarner Losh size_t i; 1784b844f8dSWarner Losh 1794b844f8dSWarner Losh if (!Nflag) 1804b844f8dSWarner Losh printf("\n"); 1814b844f8dSWarner Losh for (i = 0; i < datalen; i++) { 1824b844f8dSWarner Losh if (i % 16 == 0) { 1834b844f8dSWarner Losh if (i != 0) 1844b844f8dSWarner Losh printf("\n"); 1854b844f8dSWarner Losh printf("%04x: ", (int)i); 1864b844f8dSWarner Losh } 1874b844f8dSWarner Losh printf("%02x ", data[i]); 1884b844f8dSWarner Losh } 1894b844f8dSWarner Losh printf("\n"); 1904b844f8dSWarner Losh } 1914b844f8dSWarner Losh 1924b844f8dSWarner Losh static void 1934b844f8dSWarner Losh bindump(uint8_t *data, size_t datalen) 1944b844f8dSWarner Losh { 1954b844f8dSWarner Losh write(1, data, datalen); 1964b844f8dSWarner Losh } 1974b844f8dSWarner Losh 1984b844f8dSWarner Losh static void 1994b844f8dSWarner Losh print_var(efi_guid_t *guid, char *name) 2004b844f8dSWarner Losh { 2014b844f8dSWarner Losh uint32_t att; 2024b844f8dSWarner Losh uint8_t *data; 2034b844f8dSWarner Losh size_t datalen; 2044b844f8dSWarner Losh char *gname; 2054b844f8dSWarner Losh int rv; 2064b844f8dSWarner Losh 2074b844f8dSWarner Losh efi_guid_to_str(guid, &gname); 2084b844f8dSWarner Losh if (!Nflag) 2094b844f8dSWarner Losh printf("%s-%s", gname, name); 2104b844f8dSWarner Losh if (pflag) { 2114b844f8dSWarner Losh rv = efi_get_variable(*guid, name, &data, &datalen, &att); 2124b844f8dSWarner Losh 2134b844f8dSWarner Losh if (rv < 0) 2144b844f8dSWarner Losh printf("\n --- Error getting value --- %d", errno); 2154b844f8dSWarner Losh else { 2164b844f8dSWarner Losh if (Aflag) 2174b844f8dSWarner Losh asciidump(data, datalen); 2184b844f8dSWarner Losh else if (bflag) 2194b844f8dSWarner Losh bindump(data, datalen); 2204b844f8dSWarner Losh else 2214b844f8dSWarner Losh hexdump(data, datalen); 2224b844f8dSWarner Losh } 2234b844f8dSWarner Losh } 2244b844f8dSWarner Losh free(gname); 2254b844f8dSWarner Losh if (!Nflag) 2264b844f8dSWarner Losh printf("\n"); 2274b844f8dSWarner Losh } 2284b844f8dSWarner Losh 2294b844f8dSWarner Losh static void 2304b844f8dSWarner Losh print_variable(char *name) 2314b844f8dSWarner Losh { 2324b844f8dSWarner Losh char *vname; 2334b844f8dSWarner Losh efi_guid_t guid; 2344b844f8dSWarner Losh 2354b844f8dSWarner Losh breakdown_name(name, &guid, &vname); 2364b844f8dSWarner Losh print_var(&guid, vname); 2374b844f8dSWarner Losh } 2384b844f8dSWarner Losh 2394b844f8dSWarner Losh static void 2404b844f8dSWarner Losh print_variables(void) 2414b844f8dSWarner Losh { 2424b844f8dSWarner Losh int rv; 2434b844f8dSWarner Losh char *name = NULL; 2444b844f8dSWarner Losh efi_guid_t *guid = NULL; 2454b844f8dSWarner Losh 2464b844f8dSWarner Losh while ((rv = efi_get_next_variable_name(&guid, &name)) > 0) 2474b844f8dSWarner Losh print_var(guid, name); 2484b844f8dSWarner Losh 2494b844f8dSWarner Losh if (rv < 0) 2504b844f8dSWarner Losh err(1, "Error listing names"); 2514b844f8dSWarner Losh } 2524b844f8dSWarner Losh 2534b844f8dSWarner Losh static void 2544b844f8dSWarner Losh parse_args(int argc, char **argv) 2554b844f8dSWarner Losh { 2564b844f8dSWarner Losh int ch, i; 2574b844f8dSWarner Losh 2584b844f8dSWarner Losh while ((ch = getopt_long(argc, argv, "aAbdDf:HlLNn:pRt:w", 2594b844f8dSWarner Losh longopts, NULL)) != -1) { 2604b844f8dSWarner Losh switch (ch) { 2614b844f8dSWarner Losh case 'a': 2624b844f8dSWarner Losh aflag++; 2634b844f8dSWarner Losh break; 2644b844f8dSWarner Losh case 'A': 2654b844f8dSWarner Losh Aflag++; 2664b844f8dSWarner Losh break; 2674b844f8dSWarner Losh case 'b': 2684b844f8dSWarner Losh bflag++; 2694b844f8dSWarner Losh break; 2704b844f8dSWarner Losh case 'd': 2714b844f8dSWarner Losh dflag++; 2724b844f8dSWarner Losh break; 2734b844f8dSWarner Losh case 'D': 2744b844f8dSWarner Losh Dflag++; 2754b844f8dSWarner Losh break; 2764b844f8dSWarner Losh case 'H': 2774b844f8dSWarner Losh Hflag++; 2784b844f8dSWarner Losh break; 2794b844f8dSWarner Losh case 'l': 2804b844f8dSWarner Losh lflag++; 2814b844f8dSWarner Losh break; 2824b844f8dSWarner Losh case 'L': 2834b844f8dSWarner Losh Lflag++; 2844b844f8dSWarner Losh break; 2854b844f8dSWarner Losh case 'n': 2864b844f8dSWarner Losh varname = optarg; 2874b844f8dSWarner Losh break; 2884b844f8dSWarner Losh case 'N': 2894b844f8dSWarner Losh Nflag++; 2904b844f8dSWarner Losh break; 2914b844f8dSWarner Losh case 'p': 2924b844f8dSWarner Losh pflag++; 2934b844f8dSWarner Losh break; 2944b844f8dSWarner Losh case 'R': 2954b844f8dSWarner Losh Rflag++; 2964b844f8dSWarner Losh break; 2974b844f8dSWarner Losh case 'w': 2984b844f8dSWarner Losh wflag++; 2994b844f8dSWarner Losh break; 3004b844f8dSWarner Losh case 'f': 3014b844f8dSWarner Losh case 't': 3024b844f8dSWarner Losh case 0: 3034b844f8dSWarner Losh errx(1, "unknown or unimplemented option\n"); 3044b844f8dSWarner Losh break; 3054b844f8dSWarner Losh default: 3064b844f8dSWarner Losh usage(); 3074b844f8dSWarner Losh } 3084b844f8dSWarner Losh } 3094b844f8dSWarner Losh argc -= optind; 3104b844f8dSWarner Losh argv += optind; 3114b844f8dSWarner Losh 3124b844f8dSWarner Losh if (argc == 1) 3134b844f8dSWarner Losh varname = argv[0]; 3144b844f8dSWarner Losh 3154b844f8dSWarner Losh if (aflag + Dflag + wflag > 1) { 3164b844f8dSWarner Losh warnx("Can only use one of -a (--append), " 3174b844f8dSWarner Losh "-D (--delete) and -w (--write)"); 3184b844f8dSWarner Losh usage(); 3194b844f8dSWarner Losh } 3204b844f8dSWarner Losh 3214b844f8dSWarner Losh if (aflag + Dflag + wflag > 0 && varname == NULL) { 3224b844f8dSWarner Losh warnx("Must specify a variable for -a (--append), " 3234b844f8dSWarner Losh "-D (--delete) or -w (--write)"); 3244b844f8dSWarner Losh usage(); 3254b844f8dSWarner Losh } 3264b844f8dSWarner Losh 3274b844f8dSWarner Losh if (aflag) 3284b844f8dSWarner Losh append_variable(varname, NULL); 3294b844f8dSWarner Losh else if (Dflag) 3304b844f8dSWarner Losh delete_variable(varname); 3314b844f8dSWarner Losh else if (wflag) 3324b844f8dSWarner Losh write_variable(varname, NULL); 3334b844f8dSWarner Losh else if (varname) { 3344b844f8dSWarner Losh pflag++; 3354b844f8dSWarner Losh print_variable(varname); 3364b844f8dSWarner Losh } else if (argc > 0) { 3374b844f8dSWarner Losh pflag++; 3384b844f8dSWarner Losh for (i = 0; i < argc; i++) 3394b844f8dSWarner Losh print_variable(argv[i]); 3404b844f8dSWarner Losh } else 3414b844f8dSWarner Losh print_variables(); 3424b844f8dSWarner Losh } 3434b844f8dSWarner Losh 3444b844f8dSWarner Losh int 3454b844f8dSWarner Losh main(int argc, char **argv) 3464b844f8dSWarner Losh { 3474b844f8dSWarner Losh 3484b844f8dSWarner Losh parse_args(argc, argv); 3494b844f8dSWarner Losh } 350