12bcbcb59SWarner Losh /*-
22bcbcb59SWarner Losh * Copyright (c) 2016 Netflix, Inc.
32bcbcb59SWarner Losh *
42bcbcb59SWarner Losh * Redistribution and use in source and binary forms, with or without
52bcbcb59SWarner Losh * modification, are permitted provided that the following conditions
62bcbcb59SWarner Losh * are met:
72bcbcb59SWarner Losh * 1. Redistributions of source code must retain the above copyright
82bcbcb59SWarner Losh * notice, this list of conditions and the following disclaimer.
92bcbcb59SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
102bcbcb59SWarner Losh * notice, this list of conditions and the following disclaimer in the
112bcbcb59SWarner Losh * documentation and/or other materials provided with the distribution.
122bcbcb59SWarner Losh *
132bcbcb59SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
142bcbcb59SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
152bcbcb59SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
162bcbcb59SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
172bcbcb59SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
182bcbcb59SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
192bcbcb59SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
202bcbcb59SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
212bcbcb59SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
222bcbcb59SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
232bcbcb59SWarner Losh * SUCH DAMAGE.
242bcbcb59SWarner Losh */
252bcbcb59SWarner Losh
262bcbcb59SWarner Losh #include <sys/cdefs.h>
27c0a0f12fSWarner Losh #include <ctype.h>
282bcbcb59SWarner Losh #include <efivar.h>
292bcbcb59SWarner Losh #include <efivar-dp.h>
302bcbcb59SWarner Losh #include <err.h>
31693ba58fSWarner Losh #include <errno.h>
322bcbcb59SWarner Losh #include <getopt.h>
332bcbcb59SWarner Losh #include <stddef.h>
342bcbcb59SWarner Losh #include <stdio.h>
352bcbcb59SWarner Losh #include <stdlib.h>
362bcbcb59SWarner Losh #include <string.h>
372bcbcb59SWarner Losh #include <unistd.h>
382bcbcb59SWarner Losh
39*663b1be8SElyes Haouas #define MAXSIZE 65536 /* Everything will be smaller than this, most 1000x smaller */
4064f77f09SWarner Losh
412bcbcb59SWarner Losh /* options descriptor */
422bcbcb59SWarner Losh static struct option longopts[] = {
43693ba58fSWarner Losh { "to-unix", no_argument, NULL, 'u' },
44693ba58fSWarner Losh { "to-efi", no_argument, NULL, 'e' },
452bcbcb59SWarner Losh { "format", no_argument, NULL, 'f' },
462bcbcb59SWarner Losh { "parse", no_argument, NULL, 'p' },
472bcbcb59SWarner Losh { NULL, 0, NULL, 0 }
482bcbcb59SWarner Losh };
492bcbcb59SWarner Losh
502bcbcb59SWarner Losh
51693ba58fSWarner Losh static int flag_format, flag_parse, flag_unix, flag_efi;
522bcbcb59SWarner Losh
532bcbcb59SWarner Losh static void
usage(void)542bcbcb59SWarner Losh usage(void)
552bcbcb59SWarner Losh {
562bcbcb59SWarner Losh
57693ba58fSWarner Losh errx(1, "efidp [-efpu]");
582bcbcb59SWarner Losh }
592bcbcb59SWarner Losh
602bcbcb59SWarner Losh static ssize_t
read_file(int fd,void ** rv)612bcbcb59SWarner Losh read_file(int fd, void **rv)
622bcbcb59SWarner Losh {
632bcbcb59SWarner Losh uint8_t *retval;
642bcbcb59SWarner Losh size_t len;
652bcbcb59SWarner Losh off_t off;
662bcbcb59SWarner Losh ssize_t red;
672bcbcb59SWarner Losh
6864f77f09SWarner Losh len = MAXSIZE;
692bcbcb59SWarner Losh off = 0;
702bcbcb59SWarner Losh retval = malloc(len);
712bcbcb59SWarner Losh do {
722bcbcb59SWarner Losh red = read(fd, retval + off, len - off);
7364f77f09SWarner Losh if (red == 0)
742bcbcb59SWarner Losh break;
7564f77f09SWarner Losh off += red;
7664f77f09SWarner Losh if (off == (off_t)len)
7764f77f09SWarner Losh break;
782bcbcb59SWarner Losh } while (1);
792bcbcb59SWarner Losh *rv = retval;
802bcbcb59SWarner Losh
812bcbcb59SWarner Losh return off;
822bcbcb59SWarner Losh }
832bcbcb59SWarner Losh
842bcbcb59SWarner Losh static void
parse_args(int argc,char ** argv)852bcbcb59SWarner Losh parse_args(int argc, char **argv)
862bcbcb59SWarner Losh {
872bcbcb59SWarner Losh int ch;
882bcbcb59SWarner Losh
89693ba58fSWarner Losh while ((ch = getopt_long(argc, argv, "efpu",
902bcbcb59SWarner Losh longopts, NULL)) != -1) {
912bcbcb59SWarner Losh switch (ch) {
92693ba58fSWarner Losh case 'e':
93693ba58fSWarner Losh flag_efi++;
94693ba58fSWarner Losh break;
952bcbcb59SWarner Losh case 'f':
962bcbcb59SWarner Losh flag_format++;
972bcbcb59SWarner Losh break;
982bcbcb59SWarner Losh case 'p':
992bcbcb59SWarner Losh flag_parse++;
1002bcbcb59SWarner Losh break;
101693ba58fSWarner Losh case 'u':
102693ba58fSWarner Losh flag_unix++;
103693ba58fSWarner Losh break;
1042bcbcb59SWarner Losh default:
1052bcbcb59SWarner Losh usage();
1062bcbcb59SWarner Losh }
1072bcbcb59SWarner Losh }
1082bcbcb59SWarner Losh argc -= optind;
1092bcbcb59SWarner Losh argv += optind;
1102bcbcb59SWarner Losh
1112bcbcb59SWarner Losh if (argc >= 1)
1122bcbcb59SWarner Losh usage();
1132bcbcb59SWarner Losh
114693ba58fSWarner Losh if (flag_parse + flag_format + flag_efi + flag_unix != 1) {
1152bcbcb59SWarner Losh warnx("Can only use one of -p (--parse), "
1162bcbcb59SWarner Losh "and -f (--format)");
1172bcbcb59SWarner Losh usage();
1182bcbcb59SWarner Losh }
1192bcbcb59SWarner Losh }
1202bcbcb59SWarner Losh
12164f77f09SWarner Losh static char *
trim(char * s)12264f77f09SWarner Losh trim(char *s)
12364f77f09SWarner Losh {
12464f77f09SWarner Losh char *t;
12564f77f09SWarner Losh
12664f77f09SWarner Losh while (isspace(*s))
12764f77f09SWarner Losh s++;
12864f77f09SWarner Losh t = s + strlen(s) - 1;
12964f77f09SWarner Losh while (t > s && isspace(*t))
13064f77f09SWarner Losh *t-- = '\0';
13164f77f09SWarner Losh return s;
13264f77f09SWarner Losh }
13364f77f09SWarner Losh
134693ba58fSWarner Losh static void
unix_to_efi(void)135693ba58fSWarner Losh unix_to_efi(void)
1362bcbcb59SWarner Losh {
13764f77f09SWarner Losh char buffer[MAXSIZE];
138693ba58fSWarner Losh char efi[MAXSIZE];
139693ba58fSWarner Losh efidp dp;
140693ba58fSWarner Losh char *walker;
141693ba58fSWarner Losh int rv;
1422bcbcb59SWarner Losh
143167b7a41SWarner Losh dp = NULL;
144693ba58fSWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) {
145693ba58fSWarner Losh walker= trim(buffer);
146167b7a41SWarner Losh free(dp);
147167b7a41SWarner Losh dp = NULL;
148693ba58fSWarner Losh rv = efivar_unix_path_to_device_path(walker, &dp);
149167b7a41SWarner Losh if (rv != 0 || dp == NULL) {
150693ba58fSWarner Losh errno = rv;
151693ba58fSWarner Losh warn("Can't convert '%s' to efi", walker);
152693ba58fSWarner Losh continue;
153693ba58fSWarner Losh }
154693ba58fSWarner Losh if (efidp_format_device_path(efi, sizeof(efi),
155693ba58fSWarner Losh dp, efidp_size(dp)) < 0) {
156693ba58fSWarner Losh warnx("Can't format dp for '%s'", walker);
157693ba58fSWarner Losh continue;
158693ba58fSWarner Losh }
159693ba58fSWarner Losh printf("%s\n", efi);
160693ba58fSWarner Losh }
161167b7a41SWarner Losh free(dp);
162693ba58fSWarner Losh }
163693ba58fSWarner Losh
164693ba58fSWarner Losh static void
efi_to_unix(void)165693ba58fSWarner Losh efi_to_unix(void)
166693ba58fSWarner Losh {
167693ba58fSWarner Losh char buffer[MAXSIZE];
168693ba58fSWarner Losh char dpbuf[MAXSIZE];
169693ba58fSWarner Losh efidp dp;
170693ba58fSWarner Losh char *walker, *dev, *relpath, *abspath;
171693ba58fSWarner Losh int rv;
172693ba58fSWarner Losh
173693ba58fSWarner Losh dp = (efidp)dpbuf;
174693ba58fSWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) {
175693ba58fSWarner Losh walker= trim(buffer);
176547fb142SWarner Losh efidp_parse_device_path(walker, dp, sizeof(dpbuf));
177693ba58fSWarner Losh rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath);
178693ba58fSWarner Losh if (rv == 0)
179693ba58fSWarner Losh printf("%s:%s %s\n", dev, relpath, abspath);
180693ba58fSWarner Losh else {
181693ba58fSWarner Losh errno = rv;
182693ba58fSWarner Losh warn("Can't convert '%s' to unix", walker);
183693ba58fSWarner Losh }
184693ba58fSWarner Losh }
185693ba58fSWarner Losh }
186693ba58fSWarner Losh
187693ba58fSWarner Losh static void
format(void)188693ba58fSWarner Losh format(void)
189693ba58fSWarner Losh {
190693ba58fSWarner Losh char buffer[MAXSIZE];
19164f77f09SWarner Losh ssize_t fmtlen;
19264f77f09SWarner Losh ssize_t len;
19364f77f09SWarner Losh void *data;
19464f77f09SWarner Losh size_t dplen;
19564f77f09SWarner Losh const_efidp dp;
19664f77f09SWarner Losh
1972bcbcb59SWarner Losh len = read_file(STDIN_FILENO, &data);
1982bcbcb59SWarner Losh if (len == -1)
1992bcbcb59SWarner Losh err(1, "read");
20064f77f09SWarner Losh dp = (const_efidp)data;
20164f77f09SWarner Losh while (len > 0) {
20264f77f09SWarner Losh dplen = efidp_size(dp);
2032bcbcb59SWarner Losh fmtlen = efidp_format_device_path(buffer, sizeof(buffer),
20464f77f09SWarner Losh dp, dplen);
2052bcbcb59SWarner Losh if (fmtlen > 0)
2062bcbcb59SWarner Losh printf("%s\n", buffer);
20764f77f09SWarner Losh len -= dplen;
20864f77f09SWarner Losh dp = (const_efidp)((const char *)dp + dplen);
20964f77f09SWarner Losh }
2102bcbcb59SWarner Losh free(data);
211693ba58fSWarner Losh }
212693ba58fSWarner Losh
213693ba58fSWarner Losh static void
parse(void)214693ba58fSWarner Losh parse(void)
215693ba58fSWarner Losh {
216693ba58fSWarner Losh char buffer[MAXSIZE];
2172bcbcb59SWarner Losh efidp dp;
2182bcbcb59SWarner Losh ssize_t dplen;
21964f77f09SWarner Losh char *walker;
2202bcbcb59SWarner Losh
22164f77f09SWarner Losh dplen = MAXSIZE;
222c0a0f12fSWarner Losh dp = malloc(dplen);
22364f77f09SWarner Losh if (dp == NULL)
2242bcbcb59SWarner Losh errx(1, "Can't allocate memory.");
22564f77f09SWarner Losh while (fgets(buffer, sizeof(buffer), stdin)) {
22664f77f09SWarner Losh walker= trim(buffer);
227c0a0f12fSWarner Losh dplen = efidp_parse_device_path(walker, dp, dplen);
2282bcbcb59SWarner Losh if (dplen == -1)
229c0a0f12fSWarner Losh errx(1, "Can't parse %s", walker);
2302bcbcb59SWarner Losh write(STDOUT_FILENO, dp, dplen);
23164f77f09SWarner Losh }
232c0a0f12fSWarner Losh free(dp);
2332bcbcb59SWarner Losh }
234693ba58fSWarner Losh
235693ba58fSWarner Losh int
main(int argc,char ** argv)236693ba58fSWarner Losh main(int argc, char **argv)
237693ba58fSWarner Losh {
238693ba58fSWarner Losh
239693ba58fSWarner Losh parse_args(argc, argv);
240693ba58fSWarner Losh if (flag_unix)
241693ba58fSWarner Losh efi_to_unix();
242693ba58fSWarner Losh else if (flag_efi)
243693ba58fSWarner Losh unix_to_efi();
244693ba58fSWarner Losh else if (flag_format)
245693ba58fSWarner Losh format();
246693ba58fSWarner Losh else if (flag_parse)
247693ba58fSWarner Losh parse();
2482bcbcb59SWarner Losh }
249