12bcbcb59SWarner Losh /*- 22bcbcb59SWarner Losh * Copyright (c) 2016 Netflix, Inc. 32bcbcb59SWarner Losh * 42bcbcb59SWarner Losh * Redistribution and use in source and binary forms, with or without 52bcbcb59SWarner Losh * modification, are permitted provided that the following conditions 62bcbcb59SWarner Losh * are met: 72bcbcb59SWarner Losh * 1. Redistributions of source code must retain the above copyright 82bcbcb59SWarner Losh * notice, this list of conditions and the following disclaimer. 92bcbcb59SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 102bcbcb59SWarner Losh * notice, this list of conditions and the following disclaimer in the 112bcbcb59SWarner Losh * documentation and/or other materials provided with the distribution. 122bcbcb59SWarner Losh * 132bcbcb59SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 142bcbcb59SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 152bcbcb59SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 162bcbcb59SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 172bcbcb59SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 182bcbcb59SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 192bcbcb59SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 202bcbcb59SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 212bcbcb59SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 222bcbcb59SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 232bcbcb59SWarner Losh * SUCH DAMAGE. 242bcbcb59SWarner Losh */ 252bcbcb59SWarner Losh 262bcbcb59SWarner Losh #include <sys/cdefs.h> 272bcbcb59SWarner Losh __FBSDID("$FreeBSD$"); 282bcbcb59SWarner Losh 29c0a0f12fSWarner Losh #include <ctype.h> 302bcbcb59SWarner Losh #include <efivar.h> 312bcbcb59SWarner Losh #include <efivar-dp.h> 322bcbcb59SWarner Losh #include <err.h> 33693ba58fSWarner Losh #include <errno.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 4164f77f09SWarner Losh #define MAXSIZE 65536 /* Everyting will be smaller than this, most 1000x smaller */ 4264f77f09SWarner Losh 432bcbcb59SWarner Losh /* options descriptor */ 442bcbcb59SWarner Losh static struct option longopts[] = { 45693ba58fSWarner Losh { "to-unix", no_argument, NULL, 'u' }, 46693ba58fSWarner Losh { "to-efi", no_argument, NULL, 'e' }, 472bcbcb59SWarner Losh { "format", no_argument, NULL, 'f' }, 482bcbcb59SWarner Losh { "parse", no_argument, NULL, 'p' }, 492bcbcb59SWarner Losh { NULL, 0, NULL, 0 } 502bcbcb59SWarner Losh }; 512bcbcb59SWarner Losh 522bcbcb59SWarner Losh 53693ba58fSWarner Losh static int flag_format, flag_parse, flag_unix, flag_efi; 542bcbcb59SWarner Losh 552bcbcb59SWarner Losh static void 562bcbcb59SWarner Losh usage(void) 572bcbcb59SWarner Losh { 582bcbcb59SWarner Losh 59693ba58fSWarner Losh errx(1, "efidp [-efpu]"); 602bcbcb59SWarner Losh } 612bcbcb59SWarner Losh 622bcbcb59SWarner Losh static ssize_t 632bcbcb59SWarner Losh read_file(int fd, void **rv) 642bcbcb59SWarner Losh { 652bcbcb59SWarner Losh uint8_t *retval; 662bcbcb59SWarner Losh size_t len; 672bcbcb59SWarner Losh off_t off; 682bcbcb59SWarner Losh ssize_t red; 692bcbcb59SWarner Losh 7064f77f09SWarner Losh len = MAXSIZE; 712bcbcb59SWarner Losh off = 0; 722bcbcb59SWarner Losh retval = malloc(len); 732bcbcb59SWarner Losh do { 742bcbcb59SWarner Losh red = read(fd, retval + off, len - off); 7564f77f09SWarner Losh if (red == 0) 762bcbcb59SWarner Losh break; 7764f77f09SWarner Losh off += red; 7864f77f09SWarner Losh if (off == (off_t)len) 7964f77f09SWarner Losh break; 802bcbcb59SWarner Losh } while (1); 812bcbcb59SWarner Losh *rv = retval; 822bcbcb59SWarner Losh 832bcbcb59SWarner Losh return off; 842bcbcb59SWarner Losh } 852bcbcb59SWarner Losh 862bcbcb59SWarner Losh static void 872bcbcb59SWarner Losh parse_args(int argc, char **argv) 882bcbcb59SWarner Losh { 892bcbcb59SWarner Losh int ch; 902bcbcb59SWarner Losh 91693ba58fSWarner Losh while ((ch = getopt_long(argc, argv, "efpu", 922bcbcb59SWarner Losh longopts, NULL)) != -1) { 932bcbcb59SWarner Losh switch (ch) { 94693ba58fSWarner Losh case 'e': 95693ba58fSWarner Losh flag_efi++; 96693ba58fSWarner Losh break; 972bcbcb59SWarner Losh case 'f': 982bcbcb59SWarner Losh flag_format++; 992bcbcb59SWarner Losh break; 1002bcbcb59SWarner Losh case 'p': 1012bcbcb59SWarner Losh flag_parse++; 1022bcbcb59SWarner Losh break; 103693ba58fSWarner Losh case 'u': 104693ba58fSWarner Losh flag_unix++; 105693ba58fSWarner Losh break; 1062bcbcb59SWarner Losh default: 1072bcbcb59SWarner Losh usage(); 1082bcbcb59SWarner Losh } 1092bcbcb59SWarner Losh } 1102bcbcb59SWarner Losh argc -= optind; 1112bcbcb59SWarner Losh argv += optind; 1122bcbcb59SWarner Losh 1132bcbcb59SWarner Losh if (argc >= 1) 1142bcbcb59SWarner Losh usage(); 1152bcbcb59SWarner Losh 116693ba58fSWarner Losh if (flag_parse + flag_format + flag_efi + flag_unix != 1) { 1172bcbcb59SWarner Losh warnx("Can only use one of -p (--parse), " 1182bcbcb59SWarner Losh "and -f (--format)"); 1192bcbcb59SWarner Losh usage(); 1202bcbcb59SWarner Losh } 1212bcbcb59SWarner Losh } 1222bcbcb59SWarner Losh 12364f77f09SWarner Losh static char * 12464f77f09SWarner Losh trim(char *s) 12564f77f09SWarner Losh { 12664f77f09SWarner Losh char *t; 12764f77f09SWarner Losh 12864f77f09SWarner Losh while (isspace(*s)) 12964f77f09SWarner Losh s++; 13064f77f09SWarner Losh t = s + strlen(s) - 1; 13164f77f09SWarner Losh while (t > s && isspace(*t)) 13264f77f09SWarner Losh *t-- = '\0'; 13364f77f09SWarner Losh return s; 13464f77f09SWarner Losh } 13564f77f09SWarner Losh 136693ba58fSWarner Losh static void 137693ba58fSWarner Losh unix_to_efi(void) 1382bcbcb59SWarner Losh { 13964f77f09SWarner Losh char buffer[MAXSIZE]; 140693ba58fSWarner Losh char efi[MAXSIZE]; 141693ba58fSWarner Losh efidp dp; 142693ba58fSWarner Losh char *walker; 143693ba58fSWarner Losh int rv; 1442bcbcb59SWarner Losh 145167b7a41SWarner Losh dp = NULL; 146693ba58fSWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) { 147693ba58fSWarner Losh walker= trim(buffer); 148167b7a41SWarner Losh free(dp); 149167b7a41SWarner Losh dp = NULL; 150693ba58fSWarner Losh rv = efivar_unix_path_to_device_path(walker, &dp); 151167b7a41SWarner Losh if (rv != 0 || dp == NULL) { 152693ba58fSWarner Losh errno = rv; 153693ba58fSWarner Losh warn("Can't convert '%s' to efi", walker); 154693ba58fSWarner Losh continue; 155693ba58fSWarner Losh } 156693ba58fSWarner Losh if (efidp_format_device_path(efi, sizeof(efi), 157693ba58fSWarner Losh dp, efidp_size(dp)) < 0) { 158693ba58fSWarner Losh warnx("Can't format dp for '%s'", walker); 159693ba58fSWarner Losh continue; 160693ba58fSWarner Losh } 161693ba58fSWarner Losh printf("%s\n", efi); 162693ba58fSWarner Losh } 163167b7a41SWarner Losh free(dp); 164693ba58fSWarner Losh } 165693ba58fSWarner Losh 166693ba58fSWarner Losh static void 167693ba58fSWarner Losh efi_to_unix(void) 168693ba58fSWarner Losh { 169693ba58fSWarner Losh char buffer[MAXSIZE]; 170693ba58fSWarner Losh char dpbuf[MAXSIZE]; 171693ba58fSWarner Losh efidp dp; 172693ba58fSWarner Losh char *walker, *dev, *relpath, *abspath; 173693ba58fSWarner Losh int rv; 174693ba58fSWarner Losh 175693ba58fSWarner Losh dp = (efidp)dpbuf; 176693ba58fSWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) { 177693ba58fSWarner Losh walker= trim(buffer); 178*547fb142SWarner Losh efidp_parse_device_path(walker, dp, sizeof(dpbuf)); 179693ba58fSWarner Losh rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath); 180693ba58fSWarner Losh if (rv == 0) 181693ba58fSWarner Losh printf("%s:%s %s\n", dev, relpath, abspath); 182693ba58fSWarner Losh else { 183693ba58fSWarner Losh errno = rv; 184693ba58fSWarner Losh warn("Can't convert '%s' to unix", walker); 185693ba58fSWarner Losh } 186693ba58fSWarner Losh } 187693ba58fSWarner Losh } 188693ba58fSWarner Losh 189693ba58fSWarner Losh static void 190693ba58fSWarner Losh format(void) 191693ba58fSWarner Losh { 192693ba58fSWarner Losh char buffer[MAXSIZE]; 19364f77f09SWarner Losh ssize_t fmtlen; 19464f77f09SWarner Losh ssize_t len; 19564f77f09SWarner Losh void *data; 19664f77f09SWarner Losh size_t dplen; 19764f77f09SWarner Losh const_efidp dp; 19864f77f09SWarner Losh 1992bcbcb59SWarner Losh len = read_file(STDIN_FILENO, &data); 2002bcbcb59SWarner Losh if (len == -1) 2012bcbcb59SWarner Losh err(1, "read"); 20264f77f09SWarner Losh dp = (const_efidp)data; 20364f77f09SWarner Losh while (len > 0) { 20464f77f09SWarner Losh dplen = efidp_size(dp); 2052bcbcb59SWarner Losh fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 20664f77f09SWarner Losh dp, dplen); 2072bcbcb59SWarner Losh if (fmtlen > 0) 2082bcbcb59SWarner Losh printf("%s\n", buffer); 20964f77f09SWarner Losh len -= dplen; 21064f77f09SWarner Losh dp = (const_efidp)((const char *)dp + dplen); 21164f77f09SWarner Losh } 2122bcbcb59SWarner Losh free(data); 213693ba58fSWarner Losh } 214693ba58fSWarner Losh 215693ba58fSWarner Losh static void 216693ba58fSWarner Losh parse(void) 217693ba58fSWarner Losh { 218693ba58fSWarner Losh char buffer[MAXSIZE]; 2192bcbcb59SWarner Losh efidp dp; 2202bcbcb59SWarner Losh ssize_t dplen; 22164f77f09SWarner Losh char *walker; 2222bcbcb59SWarner Losh 22364f77f09SWarner Losh dplen = MAXSIZE; 224c0a0f12fSWarner Losh dp = malloc(dplen); 22564f77f09SWarner Losh if (dp == NULL) 2262bcbcb59SWarner Losh errx(1, "Can't allocate memory."); 22764f77f09SWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) { 22864f77f09SWarner Losh walker= trim(buffer); 229c0a0f12fSWarner Losh dplen = efidp_parse_device_path(walker, dp, dplen); 2302bcbcb59SWarner Losh if (dplen == -1) 231c0a0f12fSWarner Losh errx(1, "Can't parse %s", walker); 2322bcbcb59SWarner Losh write(STDOUT_FILENO, dp, dplen); 23364f77f09SWarner Losh } 234c0a0f12fSWarner Losh free(dp); 2352bcbcb59SWarner Losh } 236693ba58fSWarner Losh 237693ba58fSWarner Losh int 238693ba58fSWarner Losh main(int argc, char **argv) 239693ba58fSWarner Losh { 240693ba58fSWarner Losh 241693ba58fSWarner Losh parse_args(argc, argv); 242693ba58fSWarner Losh if (flag_unix) 243693ba58fSWarner Losh efi_to_unix(); 244693ba58fSWarner Losh else if (flag_efi) 245693ba58fSWarner Losh unix_to_efi(); 246693ba58fSWarner Losh else if (flag_format) 247693ba58fSWarner Losh format(); 248693ba58fSWarner Losh else if (flag_parse) 249693ba58fSWarner Losh parse(); 2502bcbcb59SWarner Losh } 251