1 /*- 2 * Copyright (c) 2016 Netflix, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <ctype.h> 31 #include <efivar.h> 32 #include <efivar-dp.h> 33 #include <err.h> 34 #include <errno.h> 35 #include <getopt.h> 36 #include <stddef.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #define MAXSIZE 65536 /* Everyting will be smaller than this, most 1000x smaller */ 43 44 /* options descriptor */ 45 static struct option longopts[] = { 46 { "to-unix", no_argument, NULL, 'u' }, 47 { "to-efi", no_argument, NULL, 'e' }, 48 { "format", no_argument, NULL, 'f' }, 49 { "parse", no_argument, NULL, 'p' }, 50 { NULL, 0, NULL, 0 } 51 }; 52 53 54 static int flag_format, flag_parse, flag_unix, flag_efi; 55 56 static void 57 usage(void) 58 { 59 60 errx(1, "efidp [-efpu]"); 61 } 62 63 static ssize_t 64 read_file(int fd, void **rv) 65 { 66 uint8_t *retval; 67 size_t len; 68 off_t off; 69 ssize_t red; 70 71 len = MAXSIZE; 72 off = 0; 73 retval = malloc(len); 74 do { 75 red = read(fd, retval + off, len - off); 76 if (red == 0) 77 break; 78 off += red; 79 if (off == (off_t)len) 80 break; 81 } while (1); 82 *rv = retval; 83 84 return off; 85 } 86 87 static void 88 parse_args(int argc, char **argv) 89 { 90 int ch; 91 92 while ((ch = getopt_long(argc, argv, "efpu", 93 longopts, NULL)) != -1) { 94 switch (ch) { 95 case 'e': 96 flag_efi++; 97 break; 98 case 'f': 99 flag_format++; 100 break; 101 case 'p': 102 flag_parse++; 103 break; 104 case 'u': 105 flag_unix++; 106 break; 107 default: 108 usage(); 109 } 110 } 111 argc -= optind; 112 argv += optind; 113 114 if (argc >= 1) 115 usage(); 116 117 if (flag_parse + flag_format + flag_efi + flag_unix != 1) { 118 warnx("Can only use one of -p (--parse), " 119 "and -f (--format)"); 120 usage(); 121 } 122 } 123 124 static char * 125 trim(char *s) 126 { 127 char *t; 128 129 while (isspace(*s)) 130 s++; 131 t = s + strlen(s) - 1; 132 while (t > s && isspace(*t)) 133 *t-- = '\0'; 134 return s; 135 } 136 137 static void 138 unix_to_efi(void) 139 { 140 char buffer[MAXSIZE]; 141 char efi[MAXSIZE]; 142 efidp dp; 143 char *walker; 144 int rv; 145 146 dp = NULL; 147 while (fgets(buffer, sizeof(buffer), stdin)) { 148 walker= trim(buffer); 149 free(dp); 150 dp = NULL; 151 rv = efivar_unix_path_to_device_path(walker, &dp); 152 if (rv != 0 || dp == NULL) { 153 errno = rv; 154 warn("Can't convert '%s' to efi", walker); 155 continue; 156 } 157 if (efidp_format_device_path(efi, sizeof(efi), 158 dp, efidp_size(dp)) < 0) { 159 warnx("Can't format dp for '%s'", walker); 160 continue; 161 } 162 printf("%s\n", efi); 163 } 164 free(dp); 165 } 166 167 static void 168 efi_to_unix(void) 169 { 170 char buffer[MAXSIZE]; 171 char dpbuf[MAXSIZE]; 172 efidp dp; 173 size_t dplen; 174 char *walker, *dev, *relpath, *abspath; 175 int rv; 176 177 dp = (efidp)dpbuf; 178 while (fgets(buffer, sizeof(buffer), stdin)) { 179 walker= trim(buffer); 180 dplen = efidp_parse_device_path(walker, dp, sizeof(dpbuf)); 181 rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath); 182 if (rv == 0) 183 printf("%s:%s %s\n", dev, relpath, abspath); 184 else { 185 errno = rv; 186 warn("Can't convert '%s' to unix", walker); 187 } 188 } 189 } 190 191 static void 192 format(void) 193 { 194 char buffer[MAXSIZE]; 195 ssize_t fmtlen; 196 ssize_t len; 197 void *data; 198 size_t dplen; 199 const_efidp dp; 200 201 len = read_file(STDIN_FILENO, &data); 202 if (len == -1) 203 err(1, "read"); 204 dp = (const_efidp)data; 205 while (len > 0) { 206 dplen = efidp_size(dp); 207 fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 208 dp, dplen); 209 if (fmtlen > 0) 210 printf("%s\n", buffer); 211 len -= dplen; 212 dp = (const_efidp)((const char *)dp + dplen); 213 } 214 free(data); 215 } 216 217 static void 218 parse(void) 219 { 220 char buffer[MAXSIZE]; 221 efidp dp; 222 ssize_t dplen; 223 char *walker; 224 225 dplen = MAXSIZE; 226 dp = malloc(dplen); 227 if (dp == NULL) 228 errx(1, "Can't allocate memory."); 229 while (fgets(buffer, sizeof(buffer), stdin)) { 230 walker= trim(buffer); 231 dplen = efidp_parse_device_path(walker, dp, dplen); 232 if (dplen == -1) 233 errx(1, "Can't parse %s", walker); 234 write(STDOUT_FILENO, dp, dplen); 235 } 236 free(dp); 237 } 238 239 int 240 main(int argc, char **argv) 241 { 242 243 parse_args(argc, argv); 244 if (flag_unix) 245 efi_to_unix(); 246 else if (flag_efi) 247 unix_to_efi(); 248 else if (flag_format) 249 format(); 250 else if (flag_parse) 251 parse(); 252 } 253