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