xref: /freebsd/usr.sbin/efidp/efidp.c (revision 547fb1426cecf097a7eae023eb8a0fbde733178b)
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>
272bcbcb59SWarner Losh __FBSDID("$FreeBSD$");
282bcbcb59SWarner Losh 
29c0a0f12fSWarner Losh #include <ctype.h>
302bcbcb59SWarner Losh #include <efivar.h>
312bcbcb59SWarner Losh #include <efivar-dp.h>
322bcbcb59SWarner Losh #include <err.h>
33693ba58fSWarner Losh #include <errno.h>
342bcbcb59SWarner Losh #include <getopt.h>
352bcbcb59SWarner Losh #include <stddef.h>
362bcbcb59SWarner Losh #include <stdio.h>
372bcbcb59SWarner Losh #include <stdlib.h>
382bcbcb59SWarner Losh #include <string.h>
392bcbcb59SWarner Losh #include <unistd.h>
402bcbcb59SWarner Losh 
4164f77f09SWarner Losh #define MAXSIZE 65536	/* Everyting will be smaller than this, most 1000x smaller */
4264f77f09SWarner Losh 
432bcbcb59SWarner Losh /* options descriptor */
442bcbcb59SWarner Losh static struct option longopts[] = {
45693ba58fSWarner Losh 	{ "to-unix",		no_argument,		NULL,	'u' },
46693ba58fSWarner Losh 	{ "to-efi",		no_argument,		NULL,	'e' },
472bcbcb59SWarner Losh 	{ "format",		no_argument,		NULL,	'f' },
482bcbcb59SWarner Losh 	{ "parse",		no_argument,		NULL,	'p' },
492bcbcb59SWarner Losh 	{ NULL,			0,			NULL,	0 }
502bcbcb59SWarner Losh };
512bcbcb59SWarner Losh 
522bcbcb59SWarner Losh 
53693ba58fSWarner Losh static int flag_format, flag_parse, flag_unix, flag_efi;
542bcbcb59SWarner Losh 
552bcbcb59SWarner Losh static void
562bcbcb59SWarner Losh usage(void)
572bcbcb59SWarner Losh {
582bcbcb59SWarner Losh 
59693ba58fSWarner Losh 	errx(1, "efidp [-efpu]");
602bcbcb59SWarner Losh }
612bcbcb59SWarner Losh 
622bcbcb59SWarner Losh static ssize_t
632bcbcb59SWarner Losh read_file(int fd, void **rv)
642bcbcb59SWarner Losh {
652bcbcb59SWarner Losh 	uint8_t *retval;
662bcbcb59SWarner Losh 	size_t len;
672bcbcb59SWarner Losh 	off_t off;
682bcbcb59SWarner Losh 	ssize_t red;
692bcbcb59SWarner Losh 
7064f77f09SWarner Losh 	len = MAXSIZE;
712bcbcb59SWarner Losh 	off = 0;
722bcbcb59SWarner Losh 	retval = malloc(len);
732bcbcb59SWarner Losh 	do {
742bcbcb59SWarner Losh 		red = read(fd, retval + off, len - off);
7564f77f09SWarner Losh 		if (red == 0)
762bcbcb59SWarner Losh 			break;
7764f77f09SWarner Losh 		off += red;
7864f77f09SWarner Losh 		if (off == (off_t)len)
7964f77f09SWarner Losh 			break;
802bcbcb59SWarner Losh 	} while (1);
812bcbcb59SWarner Losh 	*rv = retval;
822bcbcb59SWarner Losh 
832bcbcb59SWarner Losh 	return off;
842bcbcb59SWarner Losh }
852bcbcb59SWarner Losh 
862bcbcb59SWarner Losh static void
872bcbcb59SWarner Losh parse_args(int argc, char **argv)
882bcbcb59SWarner Losh {
892bcbcb59SWarner Losh 	int ch;
902bcbcb59SWarner Losh 
91693ba58fSWarner Losh 	while ((ch = getopt_long(argc, argv, "efpu",
922bcbcb59SWarner Losh 		    longopts, NULL)) != -1) {
932bcbcb59SWarner Losh 		switch (ch) {
94693ba58fSWarner Losh 		case 'e':
95693ba58fSWarner Losh 			flag_efi++;
96693ba58fSWarner Losh 			break;
972bcbcb59SWarner Losh 		case 'f':
982bcbcb59SWarner Losh 			flag_format++;
992bcbcb59SWarner Losh 			break;
1002bcbcb59SWarner Losh 		case 'p':
1012bcbcb59SWarner Losh 			flag_parse++;
1022bcbcb59SWarner Losh 			break;
103693ba58fSWarner Losh 		case 'u':
104693ba58fSWarner Losh 			flag_unix++;
105693ba58fSWarner Losh 			break;
1062bcbcb59SWarner Losh 		default:
1072bcbcb59SWarner Losh 			usage();
1082bcbcb59SWarner Losh 		}
1092bcbcb59SWarner Losh 	}
1102bcbcb59SWarner Losh 	argc -= optind;
1112bcbcb59SWarner Losh 	argv += optind;
1122bcbcb59SWarner Losh 
1132bcbcb59SWarner Losh 	if (argc >= 1)
1142bcbcb59SWarner Losh 		usage();
1152bcbcb59SWarner Losh 
116693ba58fSWarner Losh 	if (flag_parse + flag_format + flag_efi + flag_unix != 1) {
1172bcbcb59SWarner Losh 		warnx("Can only use one of -p (--parse), "
1182bcbcb59SWarner Losh 		    "and -f (--format)");
1192bcbcb59SWarner Losh 		usage();
1202bcbcb59SWarner Losh 	}
1212bcbcb59SWarner Losh }
1222bcbcb59SWarner Losh 
12364f77f09SWarner Losh static char *
12464f77f09SWarner Losh trim(char *s)
12564f77f09SWarner Losh {
12664f77f09SWarner Losh 	char *t;
12764f77f09SWarner Losh 
12864f77f09SWarner Losh 	while (isspace(*s))
12964f77f09SWarner Losh 		s++;
13064f77f09SWarner Losh 	t = s + strlen(s) - 1;
13164f77f09SWarner Losh 	while (t > s && isspace(*t))
13264f77f09SWarner Losh 		*t-- = '\0';
13364f77f09SWarner Losh 	return s;
13464f77f09SWarner Losh }
13564f77f09SWarner Losh 
136693ba58fSWarner Losh static void
137693ba58fSWarner Losh unix_to_efi(void)
1382bcbcb59SWarner Losh {
13964f77f09SWarner Losh 	char buffer[MAXSIZE];
140693ba58fSWarner Losh 	char efi[MAXSIZE];
141693ba58fSWarner Losh 	efidp dp;
142693ba58fSWarner Losh 	char *walker;
143693ba58fSWarner Losh 	int rv;
1442bcbcb59SWarner Losh 
145167b7a41SWarner Losh 	dp = NULL;
146693ba58fSWarner Losh 	while (fgets(buffer, sizeof(buffer), stdin)) {
147693ba58fSWarner Losh 		walker= trim(buffer);
148167b7a41SWarner Losh 		free(dp);
149167b7a41SWarner Losh 		dp = NULL;
150693ba58fSWarner Losh 		rv = efivar_unix_path_to_device_path(walker, &dp);
151167b7a41SWarner Losh 		if (rv != 0 || dp == NULL) {
152693ba58fSWarner Losh 			errno = rv;
153693ba58fSWarner Losh 			warn("Can't convert '%s' to efi", walker);
154693ba58fSWarner Losh 			continue;
155693ba58fSWarner Losh 		}
156693ba58fSWarner Losh 		if (efidp_format_device_path(efi, sizeof(efi),
157693ba58fSWarner Losh 		    dp, efidp_size(dp)) < 0) {
158693ba58fSWarner Losh 			warnx("Can't format dp for '%s'", walker);
159693ba58fSWarner Losh 			continue;
160693ba58fSWarner Losh 		}
161693ba58fSWarner Losh 		printf("%s\n", efi);
162693ba58fSWarner Losh 	}
163167b7a41SWarner Losh 	free(dp);
164693ba58fSWarner Losh }
165693ba58fSWarner Losh 
166693ba58fSWarner Losh static void
167693ba58fSWarner Losh efi_to_unix(void)
168693ba58fSWarner Losh {
169693ba58fSWarner Losh 	char buffer[MAXSIZE];
170693ba58fSWarner Losh 	char dpbuf[MAXSIZE];
171693ba58fSWarner Losh 	efidp dp;
172693ba58fSWarner Losh 	char *walker, *dev, *relpath, *abspath;
173693ba58fSWarner Losh 	int rv;
174693ba58fSWarner Losh 
175693ba58fSWarner Losh 	dp = (efidp)dpbuf;
176693ba58fSWarner Losh 	while (fgets(buffer, sizeof(buffer), stdin)) {
177693ba58fSWarner Losh 		walker= trim(buffer);
178*547fb142SWarner Losh 		efidp_parse_device_path(walker, dp, sizeof(dpbuf));
179693ba58fSWarner Losh 		rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath);
180693ba58fSWarner Losh 		if (rv == 0)
181693ba58fSWarner Losh 			printf("%s:%s %s\n", dev, relpath, abspath);
182693ba58fSWarner Losh 		else {
183693ba58fSWarner Losh 			errno = rv;
184693ba58fSWarner Losh 			warn("Can't convert '%s' to unix", walker);
185693ba58fSWarner Losh 		}
186693ba58fSWarner Losh 	}
187693ba58fSWarner Losh }
188693ba58fSWarner Losh 
189693ba58fSWarner Losh static void
190693ba58fSWarner Losh format(void)
191693ba58fSWarner Losh {
192693ba58fSWarner Losh 	char buffer[MAXSIZE];
19364f77f09SWarner Losh 	ssize_t fmtlen;
19464f77f09SWarner Losh 	ssize_t len;
19564f77f09SWarner Losh 	void *data;
19664f77f09SWarner Losh 	size_t dplen;
19764f77f09SWarner Losh 	const_efidp dp;
19864f77f09SWarner Losh 
1992bcbcb59SWarner Losh 	len = read_file(STDIN_FILENO, &data);
2002bcbcb59SWarner Losh 	if (len == -1)
2012bcbcb59SWarner Losh 		err(1, "read");
20264f77f09SWarner Losh 	dp = (const_efidp)data;
20364f77f09SWarner Losh 	while (len > 0) {
20464f77f09SWarner Losh 		dplen = efidp_size(dp);
2052bcbcb59SWarner Losh 		fmtlen = efidp_format_device_path(buffer, sizeof(buffer),
20664f77f09SWarner Losh 		    dp, dplen);
2072bcbcb59SWarner Losh 		if (fmtlen > 0)
2082bcbcb59SWarner Losh 			printf("%s\n", buffer);
20964f77f09SWarner Losh 		len -= dplen;
21064f77f09SWarner Losh 		dp = (const_efidp)((const char *)dp + dplen);
21164f77f09SWarner Losh 	}
2122bcbcb59SWarner Losh 	free(data);
213693ba58fSWarner Losh }
214693ba58fSWarner Losh 
215693ba58fSWarner Losh static void
216693ba58fSWarner Losh parse(void)
217693ba58fSWarner Losh {
218693ba58fSWarner Losh 	char buffer[MAXSIZE];
2192bcbcb59SWarner Losh 	efidp dp;
2202bcbcb59SWarner Losh 	ssize_t dplen;
22164f77f09SWarner Losh 	char *walker;
2222bcbcb59SWarner Losh 
22364f77f09SWarner Losh 	dplen = MAXSIZE;
224c0a0f12fSWarner Losh 	dp = malloc(dplen);
22564f77f09SWarner Losh 	if (dp == NULL)
2262bcbcb59SWarner Losh 		errx(1, "Can't allocate memory.");
22764f77f09SWarner Losh 	while (fgets(buffer, sizeof(buffer), stdin)) {
22864f77f09SWarner Losh 		walker= trim(buffer);
229c0a0f12fSWarner Losh 		dplen = efidp_parse_device_path(walker, dp, dplen);
2302bcbcb59SWarner Losh 		if (dplen == -1)
231c0a0f12fSWarner Losh 			errx(1, "Can't parse %s", walker);
2322bcbcb59SWarner Losh 		write(STDOUT_FILENO, dp, dplen);
23364f77f09SWarner Losh 	}
234c0a0f12fSWarner Losh 	free(dp);
2352bcbcb59SWarner Losh }
236693ba58fSWarner Losh 
237693ba58fSWarner Losh int
238693ba58fSWarner Losh main(int argc, char **argv)
239693ba58fSWarner Losh {
240693ba58fSWarner Losh 
241693ba58fSWarner Losh 	parse_args(argc, argv);
242693ba58fSWarner Losh 	if (flag_unix)
243693ba58fSWarner Losh 		efi_to_unix();
244693ba58fSWarner Losh 	else if (flag_efi)
245693ba58fSWarner Losh 		unix_to_efi();
246693ba58fSWarner Losh 	else if (flag_format)
247693ba58fSWarner Losh 		format();
248693ba58fSWarner Losh 	else if (flag_parse)
249693ba58fSWarner Losh 		parse();
2502bcbcb59SWarner Losh }
251