1314928Simp/*- 2314928Simp * Copyright (c) 2016 Netflix, Inc. 3314928Simp * All rights reserved. 4314928Simp * 5314928Simp * Redistribution and use in source and binary forms, with or without 6314928Simp * modification, are permitted provided that the following conditions 7314928Simp * are met: 8314928Simp * 1. Redistributions of source code must retain the above copyright 9314928Simp * notice, this list of conditions and the following disclaimer. 10314928Simp * 2. Redistributions in binary form must reproduce the above copyright 11314928Simp * notice, this list of conditions and the following disclaimer in the 12314928Simp * documentation and/or other materials provided with the distribution. 13314928Simp * 14314928Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15314928Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16314928Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17314928Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18314928Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19314928Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20314928Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21314928Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22314928Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23314928Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24314928Simp * SUCH DAMAGE. 25314928Simp */ 26314928Simp 27314928Simp#include <sys/cdefs.h> 28314928Simp__FBSDID("$FreeBSD: stable/11/usr.sbin/efidp/efidp.c 332123 2018-04-06 18:10:38Z kevans $"); 29314928Simp 30332123Skevans#include <ctype.h> 31314928Simp#include <efivar.h> 32314928Simp#include <efivar-dp.h> 33314928Simp#include <err.h> 34332123Skevans#include <errno.h> 35314928Simp#include <getopt.h> 36314928Simp#include <stddef.h> 37314928Simp#include <stdio.h> 38314928Simp#include <stdlib.h> 39314928Simp#include <string.h> 40314928Simp#include <unistd.h> 41314928Simp 42332123Skevans#define MAXSIZE 65536 /* Everyting will be smaller than this, most 1000x smaller */ 43332123Skevans 44314928Simp/* options descriptor */ 45314928Simpstatic struct option longopts[] = { 46332123Skevans { "to-unix", no_argument, NULL, 'u' }, 47332123Skevans { "to-efi", no_argument, NULL, 'e' }, 48314928Simp { "format", no_argument, NULL, 'f' }, 49314928Simp { "parse", no_argument, NULL, 'p' }, 50314928Simp { NULL, 0, NULL, 0 } 51314928Simp}; 52314928Simp 53314928Simp 54332123Skevansstatic int flag_format, flag_parse, flag_unix, flag_efi; 55314928Simp 56314928Simpstatic void 57314928Simpusage(void) 58314928Simp{ 59314928Simp 60332123Skevans errx(1, "efidp [-efpu]"); 61314928Simp} 62314928Simp 63314928Simpstatic ssize_t 64314928Simpread_file(int fd, void **rv) 65314928Simp{ 66314928Simp uint8_t *retval; 67314928Simp size_t len; 68314928Simp off_t off; 69314928Simp ssize_t red; 70314928Simp 71332123Skevans len = MAXSIZE; 72314928Simp off = 0; 73314928Simp retval = malloc(len); 74314928Simp do { 75314928Simp red = read(fd, retval + off, len - off); 76332123Skevans if (red == 0) 77332123Skevans break; 78314928Simp off += red; 79332123Skevans if (off == (off_t)len) 80314928Simp break; 81314928Simp } while (1); 82314928Simp *rv = retval; 83314928Simp 84314928Simp return off; 85314928Simp} 86314928Simp 87314928Simpstatic void 88314928Simpparse_args(int argc, char **argv) 89314928Simp{ 90314928Simp int ch; 91314928Simp 92332123Skevans while ((ch = getopt_long(argc, argv, "efpu", 93314928Simp longopts, NULL)) != -1) { 94314928Simp switch (ch) { 95332123Skevans case 'e': 96332123Skevans flag_efi++; 97332123Skevans break; 98314928Simp case 'f': 99314928Simp flag_format++; 100314928Simp break; 101314928Simp case 'p': 102314928Simp flag_parse++; 103314928Simp break; 104332123Skevans case 'u': 105332123Skevans flag_unix++; 106332123Skevans break; 107314928Simp default: 108314928Simp usage(); 109314928Simp } 110314928Simp } 111314928Simp argc -= optind; 112314928Simp argv += optind; 113314928Simp 114314928Simp if (argc >= 1) 115314928Simp usage(); 116314928Simp 117332123Skevans if (flag_parse + flag_format + flag_efi + flag_unix != 1) { 118314928Simp warnx("Can only use one of -p (--parse), " 119314928Simp "and -f (--format)"); 120314928Simp usage(); 121314928Simp } 122314928Simp} 123314928Simp 124332123Skevansstatic char * 125332123Skevanstrim(char *s) 126314928Simp{ 127332123Skevans char *t; 128332123Skevans 129332123Skevans while (isspace(*s)) 130332123Skevans s++; 131332123Skevans t = s + strlen(s) - 1; 132332123Skevans while (t > s && isspace(*t)) 133332123Skevans *t-- = '\0'; 134332123Skevans return s; 135332123Skevans} 136332123Skevans 137332123Skevansstatic void 138332123Skevansunix_to_efi(void) 139332123Skevans{ 140332123Skevans char buffer[MAXSIZE]; 141332123Skevans char efi[MAXSIZE]; 142332123Skevans efidp dp; 143332123Skevans char *walker; 144332123Skevans int rv; 145332123Skevans 146332123Skevans dp = NULL; 147332123Skevans while (fgets(buffer, sizeof(buffer), stdin)) { 148332123Skevans walker= trim(buffer); 149332123Skevans free(dp); 150332123Skevans dp = NULL; 151332123Skevans rv = efivar_unix_path_to_device_path(walker, &dp); 152332123Skevans if (rv != 0 || dp == NULL) { 153332123Skevans errno = rv; 154332123Skevans warn("Can't convert '%s' to efi", walker); 155332123Skevans continue; 156332123Skevans } 157332123Skevans if (efidp_format_device_path(efi, sizeof(efi), 158332123Skevans dp, efidp_size(dp)) < 0) { 159332123Skevans warnx("Can't format dp for '%s'", walker); 160332123Skevans continue; 161332123Skevans } 162332123Skevans printf("%s\n", efi); 163332123Skevans } 164332123Skevans free(dp); 165332123Skevans} 166332123Skevans 167332123Skevansstatic void 168332123Skevansefi_to_unix(void) 169332123Skevans{ 170332123Skevans char buffer[MAXSIZE]; 171332123Skevans char dpbuf[MAXSIZE]; 172332123Skevans efidp dp; 173332123Skevans size_t dplen; 174332123Skevans char *walker, *dev, *relpath, *abspath; 175332123Skevans int rv; 176332123Skevans 177332123Skevans dp = (efidp)dpbuf; 178332123Skevans while (fgets(buffer, sizeof(buffer), stdin)) { 179332123Skevans walker= trim(buffer); 180332123Skevans dplen = efidp_parse_device_path(walker, dp, sizeof(dpbuf)); 181332123Skevans rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath); 182332123Skevans if (rv == 0) 183332123Skevans printf("%s:%s %s\n", dev, relpath, abspath); 184332123Skevans else { 185332123Skevans errno = rv; 186332123Skevans warn("Can't convert '%s' to unix", walker); 187332123Skevans } 188332123Skevans } 189332123Skevans} 190332123Skevans 191332123Skevansstatic void 192332123Skevansformat(void) 193332123Skevans{ 194332123Skevans char buffer[MAXSIZE]; 195332123Skevans ssize_t fmtlen; 196332123Skevans ssize_t len; 197314928Simp void *data; 198332123Skevans size_t dplen; 199332123Skevans const_efidp dp; 200314928Simp 201314928Simp len = read_file(STDIN_FILENO, &data); 202314928Simp if (len == -1) 203314928Simp err(1, "read"); 204332123Skevans dp = (const_efidp)data; 205332123Skevans while (len > 0) { 206332123Skevans dplen = efidp_size(dp); 207314928Simp fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 208332123Skevans dp, dplen); 209314928Simp if (fmtlen > 0) 210314928Simp printf("%s\n", buffer); 211332123Skevans len -= dplen; 212332123Skevans dp = (const_efidp)((const char *)dp + dplen); 213332123Skevans } 214332123Skevans free(data); 215332123Skevans} 216314928Simp 217332123Skevansstatic void 218332123Skevansparse(void) 219332123Skevans{ 220332123Skevans char buffer[MAXSIZE]; 221332123Skevans efidp dp; 222332123Skevans ssize_t dplen; 223332123Skevans char *walker; 224332123Skevans 225332123Skevans dplen = MAXSIZE; 226332123Skevans dp = malloc(dplen); 227332123Skevans if (dp == NULL) 228332123Skevans errx(1, "Can't allocate memory."); 229332123Skevans while (fgets(buffer, sizeof(buffer), stdin)) { 230332123Skevans walker= trim(buffer); 231332123Skevans dplen = efidp_parse_device_path(walker, dp, dplen); 232314928Simp if (dplen == -1) 233332123Skevans errx(1, "Can't parse %s", walker); 234314928Simp write(STDOUT_FILENO, dp, dplen); 235314928Simp } 236332123Skevans free(dp); 237314928Simp} 238332123Skevans 239332123Skevansint 240332123Skevansmain(int argc, char **argv) 241332123Skevans{ 242332123Skevans 243332123Skevans parse_args(argc, argv); 244332123Skevans if (flag_unix) 245332123Skevans efi_to_unix(); 246332123Skevans else if (flag_efi) 247332123Skevans unix_to_efi(); 248332123Skevans else if (flag_format) 249332123Skevans format(); 250332123Skevans else if (flag_parse) 251332123Skevans parse(); 252332123Skevans} 253