12bcbcb59SWarner Losh /*- 22bcbcb59SWarner Losh * Copyright (c) 2016 Netflix, Inc. 32bcbcb59SWarner Losh * All rights reserved. 42bcbcb59SWarner Losh * 52bcbcb59SWarner Losh * Redistribution and use in source and binary forms, with or without 62bcbcb59SWarner Losh * modification, are permitted provided that the following conditions 72bcbcb59SWarner Losh * are met: 82bcbcb59SWarner Losh * 1. Redistributions of source code must retain the above copyright 92bcbcb59SWarner Losh * notice, this list of conditions and the following disclaimer. 102bcbcb59SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 112bcbcb59SWarner Losh * notice, this list of conditions and the following disclaimer in the 122bcbcb59SWarner Losh * documentation and/or other materials provided with the distribution. 132bcbcb59SWarner Losh * 142bcbcb59SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 152bcbcb59SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 162bcbcb59SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 172bcbcb59SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 182bcbcb59SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 192bcbcb59SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202bcbcb59SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212bcbcb59SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222bcbcb59SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 232bcbcb59SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 242bcbcb59SWarner Losh * SUCH DAMAGE. 252bcbcb59SWarner Losh */ 262bcbcb59SWarner Losh 272bcbcb59SWarner Losh #include <sys/cdefs.h> 282bcbcb59SWarner Losh __FBSDID("$FreeBSD$"); 292bcbcb59SWarner Losh 30*c0a0f12fSWarner Losh #include <ctype.h> 312bcbcb59SWarner Losh #include <efivar.h> 322bcbcb59SWarner Losh #include <efivar-dp.h> 332bcbcb59SWarner Losh #include <err.h> 342bcbcb59SWarner Losh #include <getopt.h> 352bcbcb59SWarner Losh #include <stddef.h> 362bcbcb59SWarner Losh #include <stdio.h> 372bcbcb59SWarner Losh #include <stdlib.h> 382bcbcb59SWarner Losh #include <string.h> 392bcbcb59SWarner Losh #include <unistd.h> 402bcbcb59SWarner Losh 412bcbcb59SWarner Losh /* options descriptor */ 422bcbcb59SWarner Losh static struct option longopts[] = { 432bcbcb59SWarner Losh { "format", no_argument, NULL, 'f' }, 442bcbcb59SWarner Losh { "parse", no_argument, NULL, 'p' }, 452bcbcb59SWarner Losh { NULL, 0, NULL, 0 } 462bcbcb59SWarner Losh }; 472bcbcb59SWarner Losh 482bcbcb59SWarner Losh 492bcbcb59SWarner Losh static int flag_format, flag_parse; 502bcbcb59SWarner Losh 512bcbcb59SWarner Losh static void 522bcbcb59SWarner Losh usage(void) 532bcbcb59SWarner Losh { 542bcbcb59SWarner Losh 552bcbcb59SWarner Losh errx(1, "efidp [-fp]"); 562bcbcb59SWarner Losh } 572bcbcb59SWarner Losh 582bcbcb59SWarner Losh static ssize_t 592bcbcb59SWarner Losh read_file(int fd, void **rv) 602bcbcb59SWarner Losh { 612bcbcb59SWarner Losh uint8_t *retval; 622bcbcb59SWarner Losh size_t len; 632bcbcb59SWarner Losh off_t off; 642bcbcb59SWarner Losh ssize_t red; 652bcbcb59SWarner Losh 662bcbcb59SWarner Losh len = 4096; 672bcbcb59SWarner Losh off = 0; 682bcbcb59SWarner Losh retval = malloc(len); 692bcbcb59SWarner Losh do { 702bcbcb59SWarner Losh red = read(fd, retval + off, len - off); 712bcbcb59SWarner Losh off += red; 722bcbcb59SWarner Losh if (red < (ssize_t)(len - off)) 732bcbcb59SWarner Losh break; 742bcbcb59SWarner Losh len *= 2; 752bcbcb59SWarner Losh retval = reallocf(retval, len); 762bcbcb59SWarner Losh if (retval == NULL) 772bcbcb59SWarner Losh return -1; 782bcbcb59SWarner Losh } while (1); 792bcbcb59SWarner Losh *rv = retval; 802bcbcb59SWarner Losh 812bcbcb59SWarner Losh return off; 822bcbcb59SWarner Losh } 832bcbcb59SWarner Losh 842bcbcb59SWarner Losh static void 852bcbcb59SWarner Losh parse_args(int argc, char **argv) 862bcbcb59SWarner Losh { 872bcbcb59SWarner Losh int ch; 882bcbcb59SWarner Losh 892bcbcb59SWarner Losh while ((ch = getopt_long(argc, argv, "fp", 902bcbcb59SWarner Losh longopts, NULL)) != -1) { 912bcbcb59SWarner Losh switch (ch) { 922bcbcb59SWarner Losh case 'f': 932bcbcb59SWarner Losh flag_format++; 942bcbcb59SWarner Losh break; 952bcbcb59SWarner Losh case 'p': 962bcbcb59SWarner Losh flag_parse++; 972bcbcb59SWarner Losh break; 982bcbcb59SWarner Losh default: 992bcbcb59SWarner Losh usage(); 1002bcbcb59SWarner Losh } 1012bcbcb59SWarner Losh } 1022bcbcb59SWarner Losh argc -= optind; 1032bcbcb59SWarner Losh argv += optind; 1042bcbcb59SWarner Losh 1052bcbcb59SWarner Losh if (argc >= 1) 1062bcbcb59SWarner Losh usage(); 1072bcbcb59SWarner Losh 1082bcbcb59SWarner Losh if (flag_parse + flag_format != 1) { 1092bcbcb59SWarner Losh warnx("Can only use one of -p (--parse), " 1102bcbcb59SWarner Losh "and -f (--format)"); 1112bcbcb59SWarner Losh usage(); 1122bcbcb59SWarner Losh } 1132bcbcb59SWarner Losh } 1142bcbcb59SWarner Losh 1152bcbcb59SWarner Losh int 1162bcbcb59SWarner Losh main(int argc, char **argv) 1172bcbcb59SWarner Losh { 1182bcbcb59SWarner Losh void *data; 1192bcbcb59SWarner Losh ssize_t len; 1202bcbcb59SWarner Losh 1212bcbcb59SWarner Losh parse_args(argc, argv); 1222bcbcb59SWarner Losh len = read_file(STDIN_FILENO, &data); 1232bcbcb59SWarner Losh if (len == -1) 1242bcbcb59SWarner Losh err(1, "read"); 1252bcbcb59SWarner Losh if (flag_format) { 1262bcbcb59SWarner Losh char buffer[4096]; 1272bcbcb59SWarner Losh ssize_t fmtlen; 1282bcbcb59SWarner Losh 1292bcbcb59SWarner Losh fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 1302bcbcb59SWarner Losh (const_efidp)data, len); 1312bcbcb59SWarner Losh if (fmtlen > 0) 1322bcbcb59SWarner Losh printf("%s\n", buffer); 1332bcbcb59SWarner Losh free(data); 1342bcbcb59SWarner Losh } else if (flag_parse) { 1352bcbcb59SWarner Losh efidp dp; 1362bcbcb59SWarner Losh ssize_t dplen; 137*c0a0f12fSWarner Losh char *str, *walker; 1382bcbcb59SWarner Losh 139*c0a0f12fSWarner Losh dplen = 8192; 140*c0a0f12fSWarner Losh dp = malloc(dplen); 1412bcbcb59SWarner Losh str = realloc(data, len + 1); 1422bcbcb59SWarner Losh if (str == NULL || dp == NULL) 1432bcbcb59SWarner Losh errx(1, "Can't allocate memory."); 1442bcbcb59SWarner Losh str[len] = '\0'; 145*c0a0f12fSWarner Losh walker = str; 146*c0a0f12fSWarner Losh while (isspace(*walker)) 147*c0a0f12fSWarner Losh walker++; 148*c0a0f12fSWarner Losh dplen = efidp_parse_device_path(walker, dp, dplen); 1492bcbcb59SWarner Losh if (dplen == -1) 150*c0a0f12fSWarner Losh errx(1, "Can't parse %s", walker); 1512bcbcb59SWarner Losh write(STDOUT_FILENO, dp, dplen); 152*c0a0f12fSWarner Losh free(dp); 153*c0a0f12fSWarner Losh free(str); 1542bcbcb59SWarner Losh } 1552bcbcb59SWarner Losh } 156