aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/efibootmgr/efibootmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/efibootmgr/efibootmgr.c')
-rw-r--r--usr.sbin/efibootmgr/efibootmgr.c85
1 files changed, 84 insertions, 1 deletions
diff --git a/usr.sbin/efibootmgr/efibootmgr.c b/usr.sbin/efibootmgr/efibootmgr.c
index e62ff6b50588..0d3e0635cb10 100644
--- a/usr.sbin/efibootmgr/efibootmgr.c
+++ b/usr.sbin/efibootmgr/efibootmgr.c
@@ -81,6 +81,8 @@ typedef struct _bmgr_opts {
bool delete_bootnext;
bool del_timeout;
bool dry_run;
+ bool device_path;
+ bool esp_device;
bool has_bootnum;
bool once;
int cp_src;
@@ -89,6 +91,7 @@ typedef struct _bmgr_opts {
bool set_inactive;
bool set_timeout;
int timeout;
+ bool unix_path;
bool verbose;
} bmgr_opts_t;
@@ -103,14 +106,17 @@ static struct option lopts[] = {
{"del-timout", no_argument, NULL, 'T'},
{"delete", no_argument, NULL, 'B'},
{"delete-bootnext", no_argument, NULL, 'N'},
+ {"device-path", no_argument, NULL, 'd'},
{"dry-run", no_argument, NULL, 'D'},
{"env", required_argument, NULL, 'e'},
+ {"esp", no_argument, NULL, 'E'},
{"help", no_argument, NULL, 'h'},
{"kernel", required_argument, NULL, 'k'},
{"label", required_argument, NULL, 'L'},
{"loader", required_argument, NULL, 'l'},
{"once", no_argument, NULL, 'O'},
{"set-timeout", required_argument, NULL, 't'},
+ {"unix-path", no_argument, NULL, 'p'},
{"verbose", no_argument, NULL, 'v'},
{ NULL, 0, NULL, 0}
};
@@ -191,7 +197,7 @@ parse_args(int argc, char *argv[])
{
int ch;
- while ((ch = getopt_long(argc, argv, "AaBb:C:cDe:hk:L:l:NnOo:Tt:v",
+ while ((ch = getopt_long(argc, argv, "AaBb:C:cdDe:Ehk:L:l:NnOo:pTt:v",
lopts, NULL)) != -1) {
switch (ch) {
case 'A':
@@ -216,10 +222,16 @@ parse_args(int argc, char *argv[])
case 'D': /* should be remove dups XXX */
opts.dry_run = true;
break;
+ case 'd':
+ opts.device_path = true;
+ break;
case 'e':
free(opts.env);
opts.env = strdup(optarg);
break;
+ case 'E':
+ opts.esp_device = true;
+ break;
case 'h':
default:
errx(1, "%s", USAGE);
@@ -250,6 +262,9 @@ parse_args(int argc, char *argv[])
free(opts.order);
opts.order = strdup(optarg);
break;
+ case 'p':
+ opts.unix_path = true;
+ break;
case 'T':
opts.del_timeout = true;
break;
@@ -906,6 +921,72 @@ handle_timeout(int to)
errx(1, "Can't set Timeout for booting.");
}
+static void
+report_esp_device(bool do_dp, bool do_unix)
+{
+ uint8_t *data;
+ size_t size, len;
+ uint32_t attrs;
+ int ret;
+ uint16_t current, fplen;
+ char *name, *dev, *relpath, *abspath;
+ uint8_t *walker, *ep;
+ efi_char *descr;
+ efidp dp, edp;
+ char buf[PATH_MAX];
+
+ if (do_dp && do_unix)
+ errx(1, "Can't report both UEFI device-path and Unix path together");
+
+ ret = efi_get_variable(EFI_GLOBAL_GUID, "BootCurrent", &data, &size,&attrs);
+ if (ret < 0)
+ err(1, "Can't get BootCurrent");
+ current = le16dec(data);
+ if (asprintf(&name, "Boot%04X", current) < 0)
+ err(1, "Can't format boot var\n");
+ if (efi_get_variable(EFI_GLOBAL_GUID, name, &data, &size, NULL) < 0)
+ err(1, "Can't retrieve EFI var %s", name);
+ // First 4 bytes are attribute flags
+ walker = data;
+ ep = walker + size;
+ walker += sizeof(uint32_t);
+ // Next two bytes are length of the file paths
+ fplen = le16dec(walker);
+ walker += sizeof(fplen);
+ // Next we have a 0 terminated UCS2 string that we know to be aligned
+ descr = (efi_char *)(intptr_t)(void *)walker;
+ len = ucs2len(descr); // XXX need to sanity check that len < (datalen - (ep - walker) / 2)
+ walker += (len + 1) * sizeof(efi_char);
+ if (walker > ep)
+ errx(1, "malformed boot variable %s", name);
+ // Now we have fplen bytes worth of file path stuff
+ dp = (efidp)walker;
+ walker += fplen;
+ edp = (efidp)walker;
+ if (walker > ep)
+ errx(1, "malformed boot variable %s", name);
+ if (do_dp) {
+ efidp_format_device_path_node(buf, sizeof(buf), dp);
+ printf("%s\n", buf);
+ exit(0);
+ }
+ if (efivar_device_path_to_unix_path(dp, &dev, &relpath, &abspath) < 0)
+ errx(1, "Can't convert to unix path");
+ if (do_unix) {
+ if (abspath == NULL)
+ errx(1, "Can't find where %s:%s is mounted",
+ dev, relpath);
+ abspath[strlen(abspath) - strlen(relpath) - 1] = '\0';
+ printf("%s\n", abspath);
+ } else {
+ printf("%s\n", dev);
+ }
+ free(dev);
+ free(relpath);
+ free(abspath);
+ exit(0);
+}
+
int
main(int argc, char *argv[])
{
@@ -938,6 +1019,8 @@ main(int argc, char *argv[])
delete_timeout();
else if (opts.set_timeout)
handle_timeout(opts.timeout);
+ else if (opts.esp_device)
+ report_esp_device(opts.device_path, opts.unix_path);
print_boot_vars(opts.verbose);
}