xref: /freebsd/usr.sbin/efidp/efidp.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
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