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
usage(void)54 usage(void)
55 {
56
57 errx(1, "efidp [-efpu]");
58 }
59
60 static ssize_t
read_file(int fd,void ** rv)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
parse_args(int argc,char ** argv)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 *
trim(char * s)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
unix_to_efi(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
efi_to_unix(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
format(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
parse(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
main(int argc,char ** argv)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