Index: head/usr.sbin/efidp/Makefile =================================================================== --- head/usr.sbin/efidp/Makefile (revision 326458) +++ head/usr.sbin/efidp/Makefile (revision 326459) @@ -1,8 +1,8 @@ # $FreeBSD$ PROG= efidp MAN= efidp.8 -LIBADD= efivar +LIBADD= efivar geom .include Index: head/usr.sbin/efidp/efidp.8 =================================================================== --- head/usr.sbin/efidp/efidp.8 (revision 326458) +++ head/usr.sbin/efidp/efidp.8 (revision 326459) @@ -1,72 +1,81 @@ .\" 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$ .\" -.Dd November 21, 2017 +.Dd December 1, 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 converts .Dq Unified Extensible Firmware Interface .Pq UEFI Device Paths, as defined in the UEFI standard, to and from binary form. Binary and textual forms are defined in Chapter 9 of the UEFI Specification. .Pp .Bl -tag -width 20m .It Fl f Fl -format Formats a binary UEFI Device Path into its canonical UTF-8 textual form. -A binary Device Path can be no longer than 8192 bytes. -The textual form must fit into 4096 bytes. +A binary Device Path can be no longer than 65536 bytes. +The textual form must fit into 65536 bytes. +Multiple binary device paths may be specified. .It Fl p Fl -parse Parses a UEFI Device Path UTF-8 specification and outputs the binary Device Path form. Only one device path is parsed, even if there are multiple present in the input. Leading white space is ignored. -The resulting binary Device Path can be no longer than 8192 bytes. +The resulting binary Device Path can be no longer than 65536 bytes. +Multiple lines may be specified. +Each one will be translated. +.It Fl e Fl --to-efi +Translate a Unix file path to an EFI Device Path. +The output is the textual representation of the EFI Device Path. +.It Fl u Fl --to-unix +Translate an EFI device path to a Unix file path. +The input is the textual representation of the EFI Device Path. .El .Sh SEE ALSO Appendix A of the UEFI specification has the format for GUIDs. All GUIDs .Dq Globally Unique Identifiers have the format described in RFC 4122. .Pp The Unified Extensible Firmware Interface Specification is available from .Pa www.uefi.org . .Sh HISTORY The .Nm utility first appeared in .Fx 11.1 . Index: head/usr.sbin/efidp/efidp.c =================================================================== --- head/usr.sbin/efidp/efidp.c (revision 326458) +++ head/usr.sbin/efidp/efidp.c (revision 326459) @@ -1,173 +1,248 @@ /*- * 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 __FBSDID("$FreeBSD$"); #include #include #include #include +#include #include #include #include #include #include #include #define MAXSIZE 65536 /* Everyting will be smaller than this, most 1000x smaller */ /* options descriptor */ static struct option longopts[] = { + { "to-unix", no_argument, NULL, 'u' }, + { "to-efi", no_argument, NULL, 'e' }, { "format", no_argument, NULL, 'f' }, { "parse", no_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; -static int flag_format, flag_parse; +static int flag_format, flag_parse, flag_unix, flag_efi; static void usage(void) { - errx(1, "efidp [-fp]"); + errx(1, "efidp [-efpu]"); } static ssize_t read_file(int fd, void **rv) { uint8_t *retval; size_t len; off_t off; ssize_t red; len = MAXSIZE; off = 0; retval = malloc(len); do { red = read(fd, retval + off, len - off); if (red == 0) break; off += red; if (off == (off_t)len) break; } while (1); *rv = retval; return off; } static void parse_args(int argc, char **argv) { int ch; - while ((ch = getopt_long(argc, argv, "fp", + while ((ch = getopt_long(argc, argv, "efpu", longopts, NULL)) != -1) { switch (ch) { + case 'e': + flag_efi++; + break; case 'f': flag_format++; break; case 'p': flag_parse++; break; + case 'u': + flag_unix++; + break; default: usage(); } } argc -= optind; argv += optind; if (argc >= 1) usage(); - if (flag_parse + flag_format != 1) { + if (flag_parse + flag_format + flag_efi + flag_unix != 1) { warnx("Can only use one of -p (--parse), " "and -f (--format)"); usage(); } } static char * trim(char *s) { char *t; while (isspace(*s)) s++; t = s + strlen(s) - 1; while (t > s && isspace(*t)) *t-- = '\0'; return s; } -int -main(int argc, char **argv) +static void +unix_to_efi(void) { char buffer[MAXSIZE]; + char efi[MAXSIZE]; + efidp dp; + char *walker; + int rv; - parse_args(argc, argv); - if (flag_format) { - ssize_t fmtlen; - ssize_t len; - void *data; - size_t dplen; - const_efidp dp; - - len = read_file(STDIN_FILENO, &data); - if (len == -1) - err(1, "read"); - dp = (const_efidp)data; - while (len > 0) { - dplen = efidp_size(dp); - fmtlen = efidp_format_device_path(buffer, sizeof(buffer), - dp, dplen); - if (fmtlen > 0) - printf("%s\n", buffer); - len -= dplen; - dp = (const_efidp)((const char *)dp + dplen); + while (fgets(buffer, sizeof(buffer), stdin)) { + walker= trim(buffer); + rv = efivar_unix_path_to_device_path(walker, &dp); + if (rv != 0) { + errno = rv; + warn("Can't convert '%s' to efi", walker); + continue; } - free(data); - } else if (flag_parse) { - efidp dp; - ssize_t dplen; - char *walker; + if (efidp_format_device_path(efi, sizeof(efi), + dp, efidp_size(dp)) < 0) { + warnx("Can't format dp for '%s'", walker); + continue; + } + printf("%s\n", efi); + } +} - dplen = MAXSIZE; - dp = malloc(dplen); - if (dp == NULL) - errx(1, "Can't allocate memory."); - while (fgets(buffer, sizeof(buffer), stdin)) { - walker= trim(buffer); - dplen = efidp_parse_device_path(walker, dp, dplen); - if (dplen == -1) - errx(1, "Can't parse %s", walker); - write(STDOUT_FILENO, dp, dplen); +static void +efi_to_unix(void) +{ + char buffer[MAXSIZE]; + char dpbuf[MAXSIZE]; + efidp dp; + size_t dplen; + char *walker, *dev, *relpath, *abspath; + int rv; + + dp = (efidp)dpbuf; + while (fgets(buffer, sizeof(buffer), stdin)) { + walker= trim(buffer); + dplen = efidp_parse_device_path(walker, dp, sizeof(dpbuf)); + rv = efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath); + if (rv == 0) + printf("%s:%s %s\n", dev, relpath, abspath); + else { + errno = rv; + warn("Can't convert '%s' to unix", walker); } - free(dp); } +} + +static void +format(void) +{ + char buffer[MAXSIZE]; + ssize_t fmtlen; + ssize_t len; + void *data; + size_t dplen; + const_efidp dp; + + len = read_file(STDIN_FILENO, &data); + if (len == -1) + err(1, "read"); + dp = (const_efidp)data; + while (len > 0) { + dplen = efidp_size(dp); + fmtlen = efidp_format_device_path(buffer, sizeof(buffer), + dp, dplen); + if (fmtlen > 0) + printf("%s\n", buffer); + len -= dplen; + dp = (const_efidp)((const char *)dp + dplen); + } + free(data); +} + +static void +parse(void) +{ + char buffer[MAXSIZE]; + efidp dp; + ssize_t dplen; + char *walker; + + dplen = MAXSIZE; + dp = malloc(dplen); + if (dp == NULL) + errx(1, "Can't allocate memory."); + while (fgets(buffer, sizeof(buffer), stdin)) { + walker= trim(buffer); + dplen = efidp_parse_device_path(walker, dp, dplen); + if (dplen == -1) + errx(1, "Can't parse %s", walker); + write(STDOUT_FILENO, dp, dplen); + } + free(dp); +} + +int +main(int argc, char **argv) +{ + + parse_args(argc, argv); + if (flag_unix) + efi_to_unix(); + else if (flag_efi) + unix_to_efi(); + else if (flag_format) + format(); + else if (flag_parse) + parse(); }