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