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 #include <ctype.h> 28 #include <efivar.h> 29 #include <efivar-dp.h> 30 #include <err.h> 31 #include <errno.h> 32 #include <getopt.h> 33 #include <stddef.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #define MAXSIZE 65536 /* Everything will be smaller than this, most 1000x smaller */ 40 41 /* options descriptor */ 42 static struct option longopts[] = { 43 { "to-unix", no_argument, NULL, 'u' }, 44 { "to-efi", no_argument, NULL, 'e' }, 45 { "format", no_argument, NULL, 'f' }, 46 { "parse", no_argument, NULL, 'p' }, 47 { NULL, 0, NULL, 0 } 48 }; 49 50 51 static int flag_format, flag_parse, flag_unix, flag_efi; 52 53 static void 54 usage(void) 55 { 56 57 errx(1, "efidp [-efpu]"); 58 } 59 60 static ssize_t 61 read_file(int fd, void **rv) 62 { 63 uint8_t *retval; 64 size_t len; 65 off_t off; 66 ssize_t red; 67 68 len = MAXSIZE; 69 off = 0; 70 retval = malloc(len); 71 do { 72 red = read(fd, retval + off, len - off); 73 if (red == 0) 74 break; 75 off += red; 76 if (off == (off_t)len) 77 break; 78 } while (1); 79 *rv = retval; 80 81 return off; 82 } 83 84 static void 85 parse_args(int argc, char **argv) 86 { 87 int ch; 88 89 while ((ch = getopt_long(argc, argv, "efpu", 90 longopts, NULL)) != -1) { 91 switch (ch) { 92 case 'e': 93 flag_efi++; 94 break; 95 case 'f': 96 flag_format++; 97 break; 98 case 'p': 99 flag_parse++; 100 break; 101 case 'u': 102 flag_unix++; 103 break; 104 default: 105 usage(); 106 } 107 } 108 argc -= optind; 109 argv += optind; 110 111 if (argc >= 1) 112 usage(); 113 114 if (flag_parse + flag_format + flag_efi + flag_unix != 1) { 115 warnx("Can only use one of -p (--parse), " 116 "and -f (--format)"); 117 usage(); 118 } 119 } 120 121 static char * 122 trim(char *s) 123 { 124 char *t; 125 126 while (isspace(*s)) 127 s++; 128 t = s + strlen(s) - 1; 129 while (t > s && isspace(*t)) 130 *t-- = '\0'; 131 return s; 132 } 133 134 static void 135 unix_to_efi(void) 136 { 137 char buffer[MAXSIZE]; 138 char efi[MAXSIZE]; 139 efidp dp; 140 char *walker; 141 int rv; 142 143 dp = NULL; 144 while (fgets(buffer, sizeof(buffer), stdin)) { 145 walker= trim(buffer); 146 free(dp); 147 dp = NULL; 148 rv = efivar_unix_path_to_device_path(walker, &dp); 149 if (rv != 0 || dp == NULL) { 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 free(dp); 162 } 163 164 static void 165 efi_to_unix(void) 166 { 167 char buffer[MAXSIZE]; 168 char dpbuf[MAXSIZE]; 169 efidp dp; 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 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