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 while (fgets(buffer, sizeof(buffer), stdin)) { 147 walker= trim(buffer); 148 rv = efivar_unix_path_to_device_path(walker, &dp); 149 if (rv != 0) { 150 errno = rv; 151 warn("Can't convert '%s' to efi", walker); 152 continue; 153 } 154 if (efidp_format_device_path(efi, sizeof(efi), 155 dp, efidp_size(dp)) < 0) { 156 warnx("Can't format dp for '%s'", walker); 157 continue; 158 } 159 printf("%s\n", efi); 160 } 161 } 162 163 static void 164 efi_to_unix(void) 165 { 166 char buffer[MAXSIZE]; 167 char dpbuf[MAXSIZE]; 168 efidp dp; 169 size_t dplen; 170 char *walker, *dev, *relpath, *abspath; 171 int rv; 172 173 dp = (efidp)dpbuf; 174 while (fgets(buffer, sizeof(buffer), stdin)) { 175 walker= trim(buffer); 176 dplen = efidp_parse_device_path(walker, dp, sizeof(dpbuf)); 177 rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath); 178 if (rv == 0) 179 printf("%s:%s %s\n", dev, relpath, abspath); 180 else { 181 errno = rv; 182 warn("Can't convert '%s' to unix", walker); 183 } 184 } 185 } 186 187 static void 188 format(void) 189 { 190 char buffer[MAXSIZE]; 191 ssize_t fmtlen; 192 ssize_t len; 193 void *data; 194 size_t dplen; 195 const_efidp dp; 196 197 len = read_file(STDIN_FILENO, &data); 198 if (len == -1) 199 err(1, "read"); 200 dp = (const_efidp)data; 201 while (len > 0) { 202 dplen = efidp_size(dp); 203 fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 204 dp, dplen); 205 if (fmtlen > 0) 206 printf("%s\n", buffer); 207 len -= dplen; 208 dp = (const_efidp)((const char *)dp + dplen); 209 } 210 free(data); 211 } 212 213 static void 214 parse(void) 215 { 216 char buffer[MAXSIZE]; 217 efidp dp; 218 ssize_t dplen; 219 char *walker; 220 221 dplen = MAXSIZE; 222 dp = malloc(dplen); 223 if (dp == NULL) 224 errx(1, "Can't allocate memory."); 225 while (fgets(buffer, sizeof(buffer), stdin)) { 226 walker= trim(buffer); 227 dplen = efidp_parse_device_path(walker, dp, dplen); 228 if (dplen == -1) 229 errx(1, "Can't parse %s", walker); 230 write(STDOUT_FILENO, dp, dplen); 231 } 232 free(dp); 233 } 234 235 int 236 main(int argc, char **argv) 237 { 238 239 parse_args(argc, argv); 240 if (flag_unix) 241 efi_to_unix(); 242 else if (flag_efi) 243 unix_to_efi(); 244 else if (flag_format) 245 format(); 246 else if (flag_parse) 247 parse(); 248 } 249