15709a4b5SWarner Losh /*- 25709a4b5SWarner Losh * Copyright (c) 2017 Netflix, Inc. 35709a4b5SWarner Losh * All rights reserved. 45709a4b5SWarner Losh * 55709a4b5SWarner Losh * Redistribution and use in source and binary forms, with or without 65709a4b5SWarner Losh * modification, are permitted provided that the following conditions 75709a4b5SWarner Losh * are met: 85709a4b5SWarner Losh * 1. Redistributions of source code must retain the above copyright 95709a4b5SWarner Losh * notice, this list of conditions and the following disclaimer. 105709a4b5SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 115709a4b5SWarner Losh * notice, this list of conditions and the following disclaimer in the 125709a4b5SWarner Losh * documentation and/or other materials provided with the distribution. 135709a4b5SWarner Losh * 145709a4b5SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 155709a4b5SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 165709a4b5SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 175709a4b5SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 185709a4b5SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 195709a4b5SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 205709a4b5SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 215709a4b5SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 225709a4b5SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 235709a4b5SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 245709a4b5SWarner Losh * SUCH DAMAGE. 255709a4b5SWarner Losh */ 265709a4b5SWarner Losh 275709a4b5SWarner Losh #include <sys/cdefs.h> 285709a4b5SWarner Losh __FBSDID("$FreeBSD$"); 295709a4b5SWarner Losh 305709a4b5SWarner Losh #include <ctype.h> 315709a4b5SWarner Losh #include <efivar.h> 325709a4b5SWarner Losh #include <efivar-dp.h> 335709a4b5SWarner Losh #include <err.h> 345709a4b5SWarner Losh #include <errno.h> 355709a4b5SWarner Losh #include <getopt.h> 365709a4b5SWarner Losh #include <stddef.h> 375709a4b5SWarner Losh #include <stdio.h> 385709a4b5SWarner Losh #include <stdlib.h> 395709a4b5SWarner Losh #include <string.h> 405709a4b5SWarner Losh #include <unistd.h> 415709a4b5SWarner Losh #include "efiutil.h" 425709a4b5SWarner Losh #include "efichar.h" 435709a4b5SWarner Losh #include <efivar-dp.h> 445709a4b5SWarner Losh 455709a4b5SWarner Losh /* 465709a4b5SWarner Losh * Dump the data as ASCII data, which is a pretty 475709a4b5SWarner Losh * printed form 485709a4b5SWarner Losh */ 495709a4b5SWarner Losh void 505709a4b5SWarner Losh asciidump(uint8_t *data, size_t datalen) 515709a4b5SWarner Losh { 525709a4b5SWarner Losh size_t i; 535709a4b5SWarner Losh int len; 545709a4b5SWarner Losh 555709a4b5SWarner Losh len = 0; 565709a4b5SWarner Losh for (i = 0; i < datalen; i++) { 575709a4b5SWarner Losh if (isprint(data[i])) { 585709a4b5SWarner Losh len++; 595709a4b5SWarner Losh if (len > 80) { 605709a4b5SWarner Losh len = 0; 615709a4b5SWarner Losh printf("\n"); 625709a4b5SWarner Losh } 635709a4b5SWarner Losh printf("%c", data[i]); 645709a4b5SWarner Losh } else { 655709a4b5SWarner Losh len +=3; 665709a4b5SWarner Losh if (len > 80) { 675709a4b5SWarner Losh len = 0; 685709a4b5SWarner Losh printf("\n"); 695709a4b5SWarner Losh } 705709a4b5SWarner Losh printf("%%%02x", data[i]); 715709a4b5SWarner Losh } 725709a4b5SWarner Losh } 735709a4b5SWarner Losh printf("\n"); 745709a4b5SWarner Losh } 755709a4b5SWarner Losh 765709a4b5SWarner Losh void 775709a4b5SWarner Losh utf8dump(uint8_t *data, size_t datalen) 785709a4b5SWarner Losh { 795709a4b5SWarner Losh char *utf8 = NULL; 805709a4b5SWarner Losh efi_char *ucs2; 815709a4b5SWarner Losh 825709a4b5SWarner Losh /* 835709a4b5SWarner Losh * NUL terminate the string. Not all strings need it, but some 845709a4b5SWarner Losh * do and an extra NUL won't change what's printed. 855709a4b5SWarner Losh */ 865709a4b5SWarner Losh ucs2 = malloc(datalen + sizeof(efi_char)); 875709a4b5SWarner Losh memcpy(ucs2, data, datalen); 885709a4b5SWarner Losh ucs2[datalen / sizeof(efi_char)] = 0; 895709a4b5SWarner Losh ucs2_to_utf8(ucs2, &utf8); 905709a4b5SWarner Losh printf("%s\n", utf8); 915709a4b5SWarner Losh free(utf8); 925709a4b5SWarner Losh free(ucs2); 935709a4b5SWarner Losh } 945709a4b5SWarner Losh 955709a4b5SWarner Losh void 965709a4b5SWarner Losh hexdump(uint8_t *data, size_t datalen) 975709a4b5SWarner Losh { 985709a4b5SWarner Losh size_t i; 995709a4b5SWarner Losh 1005709a4b5SWarner Losh for (i = 0; i < datalen; i++) { 1015709a4b5SWarner Losh if (i % 16 == 0) { 1025709a4b5SWarner Losh if (i != 0) 1035709a4b5SWarner Losh printf("\n"); 1045709a4b5SWarner Losh printf("%04x: ", (int)i); 1055709a4b5SWarner Losh } 1065709a4b5SWarner Losh printf("%02x ", data[i]); 1075709a4b5SWarner Losh } 1085709a4b5SWarner Losh printf("\n"); 1095709a4b5SWarner Losh } 1105709a4b5SWarner Losh 1115709a4b5SWarner Losh void 1125709a4b5SWarner Losh bindump(uint8_t *data, size_t datalen) 1135709a4b5SWarner Losh { 1145709a4b5SWarner Losh write(1, data, datalen); 1155709a4b5SWarner Losh } 1165709a4b5SWarner Losh 1175709a4b5SWarner Losh #define LOAD_OPTION_ACTIVE 1 1185709a4b5SWarner Losh 1195709a4b5SWarner Losh void 1205709a4b5SWarner Losh efi_print_load_option(uint8_t *data, size_t datalen, int Aflag, int bflag, int uflag) 1215709a4b5SWarner Losh { 1225709a4b5SWarner Losh uint8_t *ep = data + datalen; 1235709a4b5SWarner Losh uint8_t *walker = data; 1245709a4b5SWarner Losh uint32_t attr; 1255709a4b5SWarner Losh uint16_t fplen; 1265709a4b5SWarner Losh efi_char *descr; 1275709a4b5SWarner Losh efidp dp, edp; 1285709a4b5SWarner Losh char *str; 1295709a4b5SWarner Losh char buf[1024]; 1305709a4b5SWarner Losh int len; 1315709a4b5SWarner Losh void *opt; 1325709a4b5SWarner Losh int optlen; 1335709a4b5SWarner Losh 1345709a4b5SWarner Losh if (datalen < sizeof(attr) + sizeof(fplen) + sizeof(efi_char)) 1355709a4b5SWarner Losh return; 1365709a4b5SWarner Losh // First 4 bytes are attribute flags 1375709a4b5SWarner Losh attr = le32dec(walker); 1385709a4b5SWarner Losh walker += sizeof(attr); 1395709a4b5SWarner Losh // Next two bytes are length of the file paths 1405709a4b5SWarner Losh fplen = le16dec(walker); 1415709a4b5SWarner Losh walker += sizeof(fplen); 1425709a4b5SWarner Losh // Next we have a 0 terminated UCS2 string that we know to be aligned 1435709a4b5SWarner Losh descr = (efi_char *)(intptr_t)(void *)walker; 1445709a4b5SWarner Losh len = ucs2len(descr); // XXX need to sanity check that len < (datalen - (ep - walker) / 2) 1455709a4b5SWarner Losh walker += (len + 1) * sizeof(efi_char); 1465709a4b5SWarner Losh if (walker > ep) 1475709a4b5SWarner Losh return; 1485709a4b5SWarner Losh // Now we have fplen bytes worth of file path stuff 1495709a4b5SWarner Losh dp = (efidp)walker; 1505709a4b5SWarner Losh walker += fplen; 1515709a4b5SWarner Losh if (walker > ep) 1525709a4b5SWarner Losh return; 1535709a4b5SWarner Losh edp = (efidp)walker; 1545709a4b5SWarner Losh // Everything left is the binary option args 1555709a4b5SWarner Losh opt = walker; 1565709a4b5SWarner Losh optlen = ep - walker; 1575709a4b5SWarner Losh // We got to here, everything is good 1585709a4b5SWarner Losh printf("%c ", attr & LOAD_OPTION_ACTIVE ? '*' : ' '); 1595709a4b5SWarner Losh ucs2_to_utf8(descr, &str); 1605709a4b5SWarner Losh printf("%s", str); 1615709a4b5SWarner Losh free(str); 1625709a4b5SWarner Losh while (dp < edp) { 1635709a4b5SWarner Losh efidp_format_device_path(buf, sizeof(buf), dp, 1645709a4b5SWarner Losh (intptr_t)(void *)edp - (intptr_t)(void *)dp); 1655709a4b5SWarner Losh dp = (efidp)((char *)dp + efidp_size(dp)); 1665709a4b5SWarner Losh printf(" %s\n", buf); 1675709a4b5SWarner Losh } 1685709a4b5SWarner Losh if (optlen == 0) 1695709a4b5SWarner Losh return; 1705709a4b5SWarner Losh printf("Options: "); 1715709a4b5SWarner Losh if (Aflag) 1725709a4b5SWarner Losh asciidump(opt, optlen); 1735709a4b5SWarner Losh else if (bflag) 1745709a4b5SWarner Losh bindump(opt, optlen); 1755709a4b5SWarner Losh else if (uflag) 1765709a4b5SWarner Losh utf8dump(opt, optlen); 1775709a4b5SWarner Losh else 1785709a4b5SWarner Losh hexdump(opt, optlen); 1795709a4b5SWarner Losh } 180