diff options
author | Warner Losh <imp@FreeBSD.org> | 2017-09-07 07:30:19 +0000 |
---|---|---|
committer | Warner Losh <imp@FreeBSD.org> | 2017-09-07 07:30:19 +0000 |
commit | 5709a4b5a1a863328e7a7cfc519ebdabb885bbf6 (patch) | |
tree | 9b27b830764dc45ab50ed89050c85aa724def1bd /usr.sbin/efivar/efiutil.c | |
parent | 1028a2d4b3c644dde39f8f091c24438c15f0cdfa (diff) | |
download | src-5709a4b5a1a863328e7a7cfc519ebdabb885bbf6.tar.gz src-5709a4b5a1a863328e7a7cfc519ebdabb885bbf6.zip |
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
Notes
Notes:
svn path=/head/; revision=323260
Diffstat (limited to 'usr.sbin/efivar/efiutil.c')
-rw-r--r-- | usr.sbin/efivar/efiutil.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/usr.sbin/efivar/efiutil.c b/usr.sbin/efivar/efiutil.c new file mode 100644 index 000000000000..20efab54f1a3 --- /dev/null +++ b/usr.sbin/efivar/efiutil.c @@ -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); +} |