Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 6 Apr 2018 18:25:04 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r332126 - in stable/11/usr.sbin: . efibootmgr
Message-ID:  <201804061825.w36IP4TO097124@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Fri Apr  6 18:25:03 2018
New Revision: 332126
URL: https://svnweb.freebsd.org/changeset/base/332126

Log:
  MFC efibootmgr: r326725-r326728, r326771, r326800-r326804, r326806, r327163
   r327572-r327573, r327610-r327611, r327877, r331069
  
  r326725:
  Import Netflix's efibootmgr to help manage UEFI boot variables
  
  efibootmgr manages the UEFI BootXXXX variables that implement the UEFI
  Boot Manager protocol defined in the UEFI standards. It is modeled
  after the Linux program of the same name with a mostly compatible set
  of command line options. Since there's a fair amount of OS specifioc
  code due to differeing names and methods of doing things, the
  compatibility isn't 100%.
  
  Basic functionality is implemented, though the more advanced next boot
  functionality that's been defined elsewhere is unimplemented.
  
  Submitted by: Matt Williams (with unix / efi path xlate by me)
  Sponsored by: Netflix
  
  r326726:
  Forgotten in 326725
  
  Release Notes: Yes
  
  r326727:
  Remove vestiges of -d and -p commands.
  Fix two core dumps when optional data isn't specified.
  
  Sponsored by: Netflix
  
  r326728:
  Indent multiple device path entries correctly.
  
  Sponsored by: Netflix
  
  r326771:
  Unbreak gcc build by using (void) for functions that take no args.
  
  Sponsored by: Netflix
  
  r326800:
  Check return value for set_bootvar and give a good error message.
  
  CID: 1383601
  Sponsored by: Netflix
  
  r326801:
  Don't leak new_data.
  
  CID: 1383605
  Sponsored by: Netflix
  
  r326802:
  Fix resource leak. Free converted description after printing it.
  Also minor style sort of local vars.
  
  CID: 1383606
  Sponsored by: Netflix
  
  r326803:
  Free load_opt_buf after we're done with it.
  
  CID: 1383607
  Sponsored by: Netflix
  
  r326804:
  Add sanity testing against maximum sane lengths for device paths for
  loader and kernel.
  
  CID: 1383608
  Sponsored by: Netflix
  
  r326806:
  Actually insert the free(d) call missed in r326802.
  
  Noticed by: rpokala@
  
  r327163:
  Remove write-only opt and useless optlen variables.
  
  This squashes the warning gebnerated by GCC 6.x. Since
  variables that are now removed had come documentation
  value, put relevant bits in comment, so they can be
  resurrected from there when actually needed.
  
  r327572:
  Ensure that we have a description string. When unspecified, default to "".
  
  Sponsored by: Netflix
  
  r327573:
  Free options before setting them. This will prevent us from leaking
  memory when we have multiple copies of the same option from being
  specified.
  
  Sponsored by: Netflix
  
  r327610:
  Fix usage strings. -d and -p were removed before this was committed to
  FreeBSD, but the strings weren't updated.
  
  Sponsored by: Netflix
  
  r327611:
  There's no need / benefit from deleting the variable before we set it.
  
  Sponsored by: Netflix
  
  r327877:
  Fix error in determining the next available boot slot.
  
  Sponsored by: Netflix
  
  r331069:
  Make not getting BootOrder a warning, not a fatal error when printing.
  
  Sponsored by: Netflix
  
  Relnotes:	yes

Added:
  stable/11/usr.sbin/efibootmgr/
     - copied from r326728, head/usr.sbin/efibootmgr/
Modified:
  stable/11/usr.sbin/Makefile
  stable/11/usr.sbin/efibootmgr/efibootmgr.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.sbin/Makefile
==============================================================================
--- stable/11/usr.sbin/Makefile	Fri Apr  6 18:23:42 2018	(r332125)
+++ stable/11/usr.sbin/Makefile	Fri Apr  6 18:25:03 2018	(r332126)
@@ -126,7 +126,7 @@ SUBDIR.${MK_CTM}+=	ctm
 SUBDIR.${MK_CXGBETOOL}+=	cxgbetool
 SUBDIR.${MK_MLX5TOOL}+=	mlx5tool
 SUBDIR.${MK_DIALOG}+=	bsdconfig
-SUBDIR.${MK_EFI}+=	efivar efidp
+SUBDIR.${MK_EFI}+=	efivar efidp efibootmgr
 SUBDIR.${MK_FLOPPY}+=	fdcontrol
 SUBDIR.${MK_FLOPPY}+=	fdformat
 SUBDIR.${MK_FLOPPY}+=	fdread

Modified: stable/11/usr.sbin/efibootmgr/efibootmgr.c
==============================================================================
--- head/usr.sbin/efibootmgr/efibootmgr.c	Sat Dec  9 07:44:00 2017	(r326728)
+++ stable/11/usr.sbin/efibootmgr/efibootmgr.c	Fri Apr  6 18:25:03 2018	(r332126)
@@ -164,18 +164,17 @@ static int
 set_bootvar(const char *name, uint8_t *data, size_t size)
 {
 
-	efi_del_variable(EFI_GLOBAL_GUID, name);
 	return efi_set_variable(EFI_GLOBAL_GUID, name, data, size,
 	    COMMON_ATTRS);
 }
 
 
 #define USAGE \
-	"   [-aAnNB Bootvar] [-t timeout] [-T] [-o bootorder] [-O] [--verbose] [--help] \n \
-  [-c -d device -p partition -l loader [-L label] [--dry-run]]"
+	"   [-aAnNB Bootvar] [-t timeout] [-T] [-o bootorder] [-O] [--verbose] [--help] \n\
+  [-c -l loader [-k kernel ] [-L label] [--dry-run]]"
 
 #define CREATE_USAGE \
-	"       efibootmgr -c -d device -p partition -loader loader [-L label ] [--dry-run]"
+	"       efibootmgr -c -l loader [-k kernel] [-L label] [--dry-run]"
 #define ORDER_USAGE \
 	"       efibootmgr -o bootvarnum1,bootvarnum2,..."
 #define TIMEOUT_USAGE \
@@ -217,6 +216,7 @@ parse_args(int argc, char *argv[])
 			opts.dry_run = true;
 			break;
 		case 'e':
+			free(opts.env);
 			opts.env = strdup(optarg);
 			break;
 		case 'h':
@@ -224,12 +224,15 @@ parse_args(int argc, char *argv[])
 			errx(1, "%s", USAGE);
 			break;
 		case 'k':
+			free(opts.kernel);
 			opts.kernel = strdup(optarg);
 			break;
 		case 'L':
+			free(opts.label);
 			opts.label = strdup(optarg);
 			break;
 		case 'l':
+			free(opts.loader);
 			opts.loader = strdup(optarg);
 			opts.loader = mangle_loader(opts.loader);
 			break;
@@ -244,6 +247,7 @@ parse_args(int argc, char *argv[])
 			opts.once = true;
 			break;
 		case 'o':
+			free(opts.order);
 			opts.order = strdup(optarg);
 			break;
 		case 'T':
@@ -275,14 +279,16 @@ parse_args(int argc, char *argv[])
 
 
 static void
-print_order()
+print_order(void)
 {
 	uint32_t attrs;
 	uint8_t *data;
 	size_t size, i;
 
-	if (efi_get_variable(EFI_GLOBAL_GUID, "BootOrder", &data, &size, &attrs) < 0)
-		errx(1, "Couldn't get value for BootOrder\n");
+	if (efi_get_variable(EFI_GLOBAL_GUID, "BootOrder", &data, &size, &attrs) < 0) {
+		printf("BootOrder : Couldn't get value for BootOrder\n");
+		return;
+	}
 
 	if (size % 2 == 1)
 		errx(1, "Bad BootOrder variable: odd length");
@@ -361,6 +367,7 @@ set_boot_order(char *order)
 	free(cp);
 	if (set_bootvar("BootOrder", (uint8_t*)new_data, size) < 0)
 		err(1, "Unabke to set BootOrder to %s", order);
+	free(new_data);
 }
 
 static void
@@ -531,7 +538,7 @@ compare(const void *a, const void *b)
 }
 
 static char *
-make_next_boot_var_name()
+make_next_boot_var_name(void)
 {
 	struct entry *v;
 	uint16_t *vals, next_free = 0;
@@ -558,7 +565,7 @@ make_next_boot_var_name()
 	} else {
 		/* now just run the list looking for the first hole */
 		for (i = 0; i < cnt - 1 && next_free == 0; i++)
-			if (vals[i] != vals[i + 1] + 1)
+			if (vals[i] + 1 != vals[i + 1])
 				next_free = vals[i] + 1;
 		if (next_free == 0)
 			next_free = vals[cnt - 1] + 1;
@@ -590,12 +597,7 @@ create_loadopt(uint8_t *buf, size_t bufmax, uint32_t a
 	/*
 	 * Compute the length to make sure the passed in buffer is long enough.
 	 */
-	if (description)
-		utf8_to_ucs2(description, &bbuf, &desc_len);
-	else {
-		desc_len = 0;
-		bbuf = NULL;
-	}
+	utf8_to_ucs2(description, &bbuf, &desc_len);
 	len = sizeof(uint32_t) + sizeof(uint16_t) + desc_len + dp_size + optional_data_size;
 	if (len > bufmax) {
 		free(bbuf);
@@ -635,6 +637,8 @@ make_boot_var(const char *label, const char *loader, c
 	char *bootvar = NULL;
 	int ret;
 
+	assert(label != NULL);
+
 	bootvar = make_next_boot_var_name();
 	if (bootvar == NULL)
 		err(1, "bootvar creation");
@@ -649,8 +653,14 @@ make_boot_var(const char *label, const char *loader, c
 		kerneldp = NULL;
 	}
 	llen = efidp_size(loaderdp);
+	if (llen > MAX_DP_LEN)
+		errx(1, "Loader path too long.");
 	klen = efidp_size(kerneldp);
+	if (klen > MAX_DP_LEN)
+		errx(1, "Kernel path too long.");
 	dp = malloc(llen + klen);
+	if (dp == NULL)
+		errx(1, "Can't allocate memory for new device paths");
 	memcpy(dp, loaderdp, llen);
 	if (kerneldp != NULL)
 		memcpy((char *)dp + llen, kerneldp, klen);
@@ -683,8 +693,9 @@ make_boot_var(const char *label, const char *loader, c
 	new_ent->name = bootvar;
 	new_ent->guid = EFI_GLOBAL_GUID;
 	LIST_INSERT_HEAD(&efivars, new_ent, entries);
-
+	free(load_opt_buf);
 	free(dp);
+
 	return 0;
 }
 
@@ -699,10 +710,8 @@ print_loadopt_str(uint8_t *data, size_t datalen)
 	uint8_t *ep = data + datalen;
 	uint8_t *walker = data;
 	efidp dp, edp;
-	void *opt;
 	char buf[1024];
 	int len;
-	int optlen;
 	int rv;
 	int indent;
 
@@ -726,10 +735,11 @@ print_loadopt_str(uint8_t *data, size_t datalen)
 	if (walker > ep)
 		return;
 	edp = (efidp)walker;
-	// Everything left is the binary option args
-	opt = walker;
-	optlen = ep - walker;
-
+	/*
+	 * Everything left is the binary option args
+	 * opt = walker;
+	 * optlen = ep - walker;
+	 */
 	indent = 1;
 	while (dp < edp) {
 		efidp_format_device_path(buf, sizeof(buf), dp,
@@ -745,12 +755,10 @@ print_loadopt_str(uint8_t *data, size_t datalen)
 		}
 		dp = (efidp)((char *)dp + efidp_size(dp));
 	}
-	if (optlen == 0)
-		return;
 }
 
 static char *
-get_descr(uint8_t* data)
+get_descr(uint8_t *data)
 {
 	uint8_t *pos = data;
 	efi_char *desc;
@@ -782,9 +790,10 @@ print_boot_vars(bool verbose)
 	 * as a command epilogue
 	 */
 	struct entry *v;
-	uint32_t attrs, load_attrs;
 	uint8_t *data;
+	char *d;
 	size_t size;
+	uint32_t attrs, load_attrs;
 	int ret;
 
 	ret = efi_get_variable(EFI_GLOBAL_GUID, "BootNext", &data, &size, &attrs);
@@ -811,9 +820,10 @@ print_boot_vars(bool verbose)
 		if (ret < 0)
 			continue; /* we must have deleted it */
 		load_attrs = le32dec(data);
+		d = get_descr(data);
 		printf("%s%c %s", v->name,
-		    ((load_attrs & LOAD_OPTION_ACTIVE) ? '*': ' '),
-		    get_descr(data));
+		    ((load_attrs & LOAD_OPTION_ACTIVE) ? '*': ' '), d);
+		free(d);
 		if (verbose)
 			print_loadopt_str(data, size);
 		else
@@ -823,7 +833,7 @@ print_boot_vars(bool verbose)
 }
 
 static void
-delete_timeout()
+delete_timeout(void)
 {
 
 	efi_del_variable(EFI_GLOBAL_GUID,"Timeout");
@@ -835,7 +845,8 @@ handle_timeout(int to)
 	uint16_t timeout;
 
 	le16enc(&timeout, to);
-	set_bootvar("Timeout", (uint8_t *)&timeout, sizeof(timeout));
+	if (set_bootvar("Timeout", (uint8_t *)&timeout, sizeof(timeout)) < 0)
+		errx(1, "Can't set Timeout for booting.");
 }
 
 int
@@ -853,8 +864,8 @@ main(int argc, char *argv[])
 		/*
 		 * side effect, adds to boot order, but not yet active.
 		 */
-		make_boot_var(opts.label, opts.loader, opts.kernel, opts.env,
-		    opts.dry_run);
+		make_boot_var(opts.label ? opts.label : "",
+		    opts.loader, opts.kernel, opts.env, opts.dry_run);
 	else if (opts.set_active || opts.set_inactive )
 		handle_activity(opts.bootnum, opts.set_active);
 	else if (opts.order != NULL)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804061825.w36IP4TO097124>