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 30c0a0f12fSWarner Losh #include <ctype.h> 312bcbcb59SWarner Losh #include <efivar.h> 322bcbcb59SWarner Losh #include <efivar-dp.h> 332bcbcb59SWarner Losh #include <err.h> 34*693ba58fSWarner Losh #include <errno.h> 352bcbcb59SWarner Losh #include <getopt.h> 362bcbcb59SWarner Losh #include <stddef.h> 372bcbcb59SWarner Losh #include <stdio.h> 382bcbcb59SWarner Losh #include <stdlib.h> 392bcbcb59SWarner Losh #include <string.h> 402bcbcb59SWarner Losh #include <unistd.h> 412bcbcb59SWarner Losh 4264f77f09SWarner Losh #define MAXSIZE 65536 /* Everyting will be smaller than this, most 1000x smaller */ 4364f77f09SWarner Losh 442bcbcb59SWarner Losh /* options descriptor */ 452bcbcb59SWarner Losh static struct option longopts[] = { 46*693ba58fSWarner Losh { "to-unix", no_argument, NULL, 'u' }, 47*693ba58fSWarner Losh { "to-efi", no_argument, NULL, 'e' }, 482bcbcb59SWarner Losh { "format", no_argument, NULL, 'f' }, 492bcbcb59SWarner Losh { "parse", no_argument, NULL, 'p' }, 502bcbcb59SWarner Losh { NULL, 0, NULL, 0 } 512bcbcb59SWarner Losh }; 522bcbcb59SWarner Losh 532bcbcb59SWarner Losh 54*693ba58fSWarner Losh static int flag_format, flag_parse, flag_unix, flag_efi; 552bcbcb59SWarner Losh 562bcbcb59SWarner Losh static void 572bcbcb59SWarner Losh usage(void) 582bcbcb59SWarner Losh { 592bcbcb59SWarner Losh 60*693ba58fSWarner Losh errx(1, "efidp [-efpu]"); 612bcbcb59SWarner Losh } 622bcbcb59SWarner Losh 632bcbcb59SWarner Losh static ssize_t 642bcbcb59SWarner Losh read_file(int fd, void **rv) 652bcbcb59SWarner Losh { 662bcbcb59SWarner Losh uint8_t *retval; 672bcbcb59SWarner Losh size_t len; 682bcbcb59SWarner Losh off_t off; 692bcbcb59SWarner Losh ssize_t red; 702bcbcb59SWarner Losh 7164f77f09SWarner Losh len = MAXSIZE; 722bcbcb59SWarner Losh off = 0; 732bcbcb59SWarner Losh retval = malloc(len); 742bcbcb59SWarner Losh do { 752bcbcb59SWarner Losh red = read(fd, retval + off, len - off); 7664f77f09SWarner Losh if (red == 0) 772bcbcb59SWarner Losh break; 7864f77f09SWarner Losh off += red; 7964f77f09SWarner Losh if (off == (off_t)len) 8064f77f09SWarner Losh break; 812bcbcb59SWarner Losh } while (1); 822bcbcb59SWarner Losh *rv = retval; 832bcbcb59SWarner Losh 842bcbcb59SWarner Losh return off; 852bcbcb59SWarner Losh } 862bcbcb59SWarner Losh 872bcbcb59SWarner Losh static void 882bcbcb59SWarner Losh parse_args(int argc, char **argv) 892bcbcb59SWarner Losh { 902bcbcb59SWarner Losh int ch; 912bcbcb59SWarner Losh 92*693ba58fSWarner Losh while ((ch = getopt_long(argc, argv, "efpu", 932bcbcb59SWarner Losh longopts, NULL)) != -1) { 942bcbcb59SWarner Losh switch (ch) { 95*693ba58fSWarner Losh case 'e': 96*693ba58fSWarner Losh flag_efi++; 97*693ba58fSWarner Losh break; 982bcbcb59SWarner Losh case 'f': 992bcbcb59SWarner Losh flag_format++; 1002bcbcb59SWarner Losh break; 1012bcbcb59SWarner Losh case 'p': 1022bcbcb59SWarner Losh flag_parse++; 1032bcbcb59SWarner Losh break; 104*693ba58fSWarner Losh case 'u': 105*693ba58fSWarner Losh flag_unix++; 106*693ba58fSWarner Losh break; 1072bcbcb59SWarner Losh default: 1082bcbcb59SWarner Losh usage(); 1092bcbcb59SWarner Losh } 1102bcbcb59SWarner Losh } 1112bcbcb59SWarner Losh argc -= optind; 1122bcbcb59SWarner Losh argv += optind; 1132bcbcb59SWarner Losh 1142bcbcb59SWarner Losh if (argc >= 1) 1152bcbcb59SWarner Losh usage(); 1162bcbcb59SWarner Losh 117*693ba58fSWarner Losh if (flag_parse + flag_format + flag_efi + flag_unix != 1) { 1182bcbcb59SWarner Losh warnx("Can only use one of -p (--parse), " 1192bcbcb59SWarner Losh "and -f (--format)"); 1202bcbcb59SWarner Losh usage(); 1212bcbcb59SWarner Losh } 1222bcbcb59SWarner Losh } 1232bcbcb59SWarner Losh 12464f77f09SWarner Losh static char * 12564f77f09SWarner Losh trim(char *s) 12664f77f09SWarner Losh { 12764f77f09SWarner Losh char *t; 12864f77f09SWarner Losh 12964f77f09SWarner Losh while (isspace(*s)) 13064f77f09SWarner Losh s++; 13164f77f09SWarner Losh t = s + strlen(s) - 1; 13264f77f09SWarner Losh while (t > s && isspace(*t)) 13364f77f09SWarner Losh *t-- = '\0'; 13464f77f09SWarner Losh return s; 13564f77f09SWarner Losh } 13664f77f09SWarner Losh 137*693ba58fSWarner Losh static void 138*693ba58fSWarner Losh unix_to_efi(void) 1392bcbcb59SWarner Losh { 14064f77f09SWarner Losh char buffer[MAXSIZE]; 141*693ba58fSWarner Losh char efi[MAXSIZE]; 142*693ba58fSWarner Losh efidp dp; 143*693ba58fSWarner Losh char *walker; 144*693ba58fSWarner Losh int rv; 1452bcbcb59SWarner Losh 146*693ba58fSWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) { 147*693ba58fSWarner Losh walker= trim(buffer); 148*693ba58fSWarner Losh rv = efivar_unix_path_to_device_path(walker, &dp); 149*693ba58fSWarner Losh if (rv != 0) { 150*693ba58fSWarner Losh errno = rv; 151*693ba58fSWarner Losh warn("Can't convert '%s' to efi", walker); 152*693ba58fSWarner Losh continue; 153*693ba58fSWarner Losh } 154*693ba58fSWarner Losh if (efidp_format_device_path(efi, sizeof(efi), 155*693ba58fSWarner Losh dp, efidp_size(dp)) < 0) { 156*693ba58fSWarner Losh warnx("Can't format dp for '%s'", walker); 157*693ba58fSWarner Losh continue; 158*693ba58fSWarner Losh } 159*693ba58fSWarner Losh printf("%s\n", efi); 160*693ba58fSWarner Losh } 161*693ba58fSWarner Losh } 162*693ba58fSWarner Losh 163*693ba58fSWarner Losh static void 164*693ba58fSWarner Losh efi_to_unix(void) 165*693ba58fSWarner Losh { 166*693ba58fSWarner Losh char buffer[MAXSIZE]; 167*693ba58fSWarner Losh char dpbuf[MAXSIZE]; 168*693ba58fSWarner Losh efidp dp; 169*693ba58fSWarner Losh size_t dplen; 170*693ba58fSWarner Losh char *walker, *dev, *relpath, *abspath; 171*693ba58fSWarner Losh int rv; 172*693ba58fSWarner Losh 173*693ba58fSWarner Losh dp = (efidp)dpbuf; 174*693ba58fSWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) { 175*693ba58fSWarner Losh walker= trim(buffer); 176*693ba58fSWarner Losh dplen = efidp_parse_device_path(walker, dp, sizeof(dpbuf)); 177*693ba58fSWarner Losh rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath); 178*693ba58fSWarner Losh if (rv == 0) 179*693ba58fSWarner Losh printf("%s:%s %s\n", dev, relpath, abspath); 180*693ba58fSWarner Losh else { 181*693ba58fSWarner Losh errno = rv; 182*693ba58fSWarner Losh warn("Can't convert '%s' to unix", walker); 183*693ba58fSWarner Losh } 184*693ba58fSWarner Losh } 185*693ba58fSWarner Losh } 186*693ba58fSWarner Losh 187*693ba58fSWarner Losh static void 188*693ba58fSWarner Losh format(void) 189*693ba58fSWarner Losh { 190*693ba58fSWarner Losh char buffer[MAXSIZE]; 19164f77f09SWarner Losh ssize_t fmtlen; 19264f77f09SWarner Losh ssize_t len; 19364f77f09SWarner Losh void *data; 19464f77f09SWarner Losh size_t dplen; 19564f77f09SWarner Losh const_efidp dp; 19664f77f09SWarner Losh 1972bcbcb59SWarner Losh len = read_file(STDIN_FILENO, &data); 1982bcbcb59SWarner Losh if (len == -1) 1992bcbcb59SWarner Losh err(1, "read"); 20064f77f09SWarner Losh dp = (const_efidp)data; 20164f77f09SWarner Losh while (len > 0) { 20264f77f09SWarner Losh dplen = efidp_size(dp); 2032bcbcb59SWarner Losh fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 20464f77f09SWarner Losh dp, dplen); 2052bcbcb59SWarner Losh if (fmtlen > 0) 2062bcbcb59SWarner Losh printf("%s\n", buffer); 20764f77f09SWarner Losh len -= dplen; 20864f77f09SWarner Losh dp = (const_efidp)((const char *)dp + dplen); 20964f77f09SWarner Losh } 2102bcbcb59SWarner Losh free(data); 211*693ba58fSWarner Losh } 212*693ba58fSWarner Losh 213*693ba58fSWarner Losh static void 214*693ba58fSWarner Losh parse(void) 215*693ba58fSWarner Losh { 216*693ba58fSWarner Losh char buffer[MAXSIZE]; 2172bcbcb59SWarner Losh efidp dp; 2182bcbcb59SWarner Losh ssize_t dplen; 21964f77f09SWarner Losh char *walker; 2202bcbcb59SWarner Losh 22164f77f09SWarner Losh dplen = MAXSIZE; 222c0a0f12fSWarner Losh dp = malloc(dplen); 22364f77f09SWarner Losh if (dp == NULL) 2242bcbcb59SWarner Losh errx(1, "Can't allocate memory."); 22564f77f09SWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) { 22664f77f09SWarner Losh walker= trim(buffer); 227c0a0f12fSWarner Losh dplen = efidp_parse_device_path(walker, dp, dplen); 2282bcbcb59SWarner Losh if (dplen == -1) 229c0a0f12fSWarner Losh errx(1, "Can't parse %s", walker); 2302bcbcb59SWarner Losh write(STDOUT_FILENO, dp, dplen); 23164f77f09SWarner Losh } 232c0a0f12fSWarner Losh free(dp); 2332bcbcb59SWarner Losh } 234*693ba58fSWarner Losh 235*693ba58fSWarner Losh int 236*693ba58fSWarner Losh main(int argc, char **argv) 237*693ba58fSWarner Losh { 238*693ba58fSWarner Losh 239*693ba58fSWarner Losh parse_args(argc, argv); 240*693ba58fSWarner Losh if (flag_unix) 241*693ba58fSWarner Losh efi_to_unix(); 242*693ba58fSWarner Losh else if (flag_efi) 243*693ba58fSWarner Losh unix_to_efi(); 244*693ba58fSWarner Losh else if (flag_format) 245*693ba58fSWarner Losh format(); 246*693ba58fSWarner Losh else if (flag_parse) 247*693ba58fSWarner Losh parse(); 2482bcbcb59SWarner Losh } 249