From 9df2688e8843e3fff84df8ea12bf5d70baa9e931 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Tue, 21 Mar 2017 19:57:09 +0100
Subject: [PATCH 4/5] WIP bring in efidp(8)

---
 usr.sbin/Makefile       |   1 +
 usr.sbin/efidp/Makefile |   9 +++
 usr.sbin/efidp/efidp.8  |  56 ++++++++++++++++++
 usr.sbin/efidp/efidp.c  | 148 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 214 insertions(+)
 create mode 100644 usr.sbin/efidp/Makefile
 create mode 100644 usr.sbin/efidp/efidp.8
 create mode 100644 usr.sbin/efidp/efidp.c

diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 8169e1eb0b..2e498e8fde 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -32,6 +32,7 @@ SUBDIR= 802_11 \
 	dev_mkdb \
 	dntpd \
 	edquota \
+	efidp \
 	efivar \
 	faithd \
 	fdcontrol \
diff --git a/usr.sbin/efidp/Makefile b/usr.sbin/efidp/Makefile
new file mode 100644
index 0000000000..e53c6ceeb3
--- /dev/null
+++ b/usr.sbin/efidp/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD: head/usr.sbin/efidp/Makefile 314928 2017-03-09 00:33:38Z imp $
+
+PROG=	efidp
+MAN=	efidp.8
+
+LDADD=	-lefivar
+DPADD=	${LIBEFIVAR}
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/efidp/efidp.8 b/usr.sbin/efidp/efidp.8
new file mode 100644
index 0000000000..27d0ddb62c
--- /dev/null
+++ b/usr.sbin/efidp/efidp.8
@@ -0,0 +1,56 @@
+.\" Copyright (c) 2017 Netflix, Inc
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: head/usr.sbin/efidp/efidp.8 314928 2017-03-09 00:33:38Z imp $
+.\"
+.Dd March 20, 2017
+.Dt EFIDP 8
+.Os
+.Sh NAME
+.Nm efidp
+.Nd UEFI Device Path manipulation
+.Sh SYNOPSIS
+.Nm
+.Op Fl fp
+.Op Fl -parse
+.Op Fl -format
+.Sh DESCRIPTION
+This program manages
+.Dq Unified Extensible Firmware Interface
+.Pq UEFI
+Device Paths, as defined in the UEFI standard.
+.Sh SEE ALSO
+.Xr efivar 3 ,
+.Xr efivar 8
+.Pp
+Appendix A of the UEFI specification has the format for GUIDs.
+All GUIDs
+.Pq Dq Globally Unique Identifiers
+have the format described in RFC 4122.
+.El
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 12.0 .
diff --git a/usr.sbin/efidp/efidp.c b/usr.sbin/efidp/efidp.c
new file mode 100644
index 0000000000..f383c2dba9
--- /dev/null
+++ b/usr.sbin/efidp/efidp.c
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/usr.sbin/efidp/efidp.c 314928 2017-03-09 00:33:38Z imp $");
+
+#include <efivar.h>
+#include <efivar-dp.h>
+#include <err.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* options descriptor */
+static struct option longopts[] = {
+	{ "format",		no_argument,		NULL,	'f' },
+	{ "parse",		no_argument,		NULL,	'p' },
+	{ NULL,			0,			NULL,	0 }
+};
+
+
+static int flag_format, flag_parse;
+
+static void
+usage(void)
+{
+
+	errx(1, "efidp [-fp]");
+}
+
+static ssize_t
+read_file(int fd, void **rv) 
+{
+	uint8_t *retval;
+	size_t len;
+	off_t off;
+	ssize_t red;
+
+	len = 4096;
+	off = 0;
+	retval = malloc(len);
+	do {
+		red = read(fd, retval + off, len - off);
+		off += red;
+		if (red < (ssize_t)(len - off))
+			break;
+		len *= 2;
+		retval = reallocf(retval, len);
+		if (retval == NULL)
+			return -1;
+	} while (1);
+	*rv = retval;
+
+	return off;
+}
+
+static void
+parse_args(int argc, char **argv)
+{
+	int ch;
+
+	while ((ch = getopt_long(argc, argv, "fp",
+		    longopts, NULL)) != -1) {
+		switch (ch) {
+		case 'f':
+			flag_format++;
+			break;
+		case 'p':
+			flag_parse++;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc >= 1)
+		usage();
+	
+	if (flag_parse + flag_format != 1) {
+		warnx("Can only use one of -p (--parse), "
+		    "and -f (--format)");
+		usage();
+	}
+}
+
+int
+main(int argc, char **argv)
+{
+	void *data;
+	ssize_t len;
+
+	parse_args(argc, argv);
+	len = read_file(STDIN_FILENO, &data);
+	if (len == -1)
+		err(1, "read");
+	if (flag_format) {
+		char buffer[4096];
+		ssize_t fmtlen;
+
+		fmtlen = efidp_format_device_path(buffer, sizeof(buffer),
+		    (const_efidp)data, len);
+		if (fmtlen > 0)
+			printf("%s\n", buffer);
+		free(data);
+	} else if (flag_parse) {
+		efidp dp;
+		ssize_t dplen;
+		char *str;
+
+		dp = malloc(8192);
+		str = realloc(data, len + 1);
+		if (str == NULL || dp == NULL)
+			errx(1, "Can't allocate memory.");
+		str[len] = '\0';
+		dplen = efidp_parse_device_path(str, dp, 8192);
+		if (dplen == -1)
+			errx(1, "Can't parse %s", str);
+		write(STDOUT_FILENO, dp, dplen);
+	}
+}
-- 
2.11.0

