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 <getopt.h> 35 #include <stddef.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 /* options descriptor */ 42 static struct option longopts[] = { 43 { "format", no_argument, NULL, 'f' }, 44 { "parse", no_argument, NULL, 'p' }, 45 { NULL, 0, NULL, 0 } 46 }; 47 48 49 static int flag_format, flag_parse; 50 51 static void 52 usage(void) 53 { 54 55 errx(1, "efidp [-fp]"); 56 } 57 58 static ssize_t 59 read_file(int fd, void **rv) 60 { 61 uint8_t *retval; 62 size_t len; 63 off_t off; 64 ssize_t red; 65 66 len = 4096; 67 off = 0; 68 retval = malloc(len); 69 do { 70 red = read(fd, retval + off, len - off); 71 off += red; 72 if (red < (ssize_t)(len - off)) 73 break; 74 len *= 2; 75 retval = reallocf(retval, len); 76 if (retval == NULL) 77 return -1; 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, "fp", 90 longopts, NULL)) != -1) { 91 switch (ch) { 92 case 'f': 93 flag_format++; 94 break; 95 case 'p': 96 flag_parse++; 97 break; 98 default: 99 usage(); 100 } 101 } 102 argc -= optind; 103 argv += optind; 104 105 if (argc >= 1) 106 usage(); 107 108 if (flag_parse + flag_format != 1) { 109 warnx("Can only use one of -p (--parse), " 110 "and -f (--format)"); 111 usage(); 112 } 113 } 114 115 int 116 main(int argc, char **argv) 117 { 118 void *data; 119 ssize_t len; 120 121 parse_args(argc, argv); 122 len = read_file(STDIN_FILENO, &data); 123 if (len == -1) 124 err(1, "read"); 125 if (flag_format) { 126 char buffer[4096]; 127 ssize_t fmtlen; 128 129 fmtlen = efidp_format_device_path(buffer, sizeof(buffer), 130 (const_efidp)data, len); 131 if (fmtlen > 0) 132 printf("%s\n", buffer); 133 free(data); 134 } else if (flag_parse) { 135 efidp dp; 136 ssize_t dplen; 137 char *str, *walker; 138 139 dplen = 8192; 140 dp = malloc(dplen); 141 str = realloc(data, len + 1); 142 if (str == NULL || dp == NULL) 143 errx(1, "Can't allocate memory."); 144 str[len] = '\0'; 145 walker = str; 146 while (isspace(*walker)) 147 walker++; 148 dplen = efidp_parse_device_path(walker, dp, dplen); 149 if (dplen == -1) 150 errx(1, "Can't parse %s", walker); 151 write(STDOUT_FILENO, dp, dplen); 152 free(dp); 153 free(str); 154 } 155 } 156