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