From owner-svn-src-all@freebsd.org Fri Apr 6 18:25:04 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9D831F9C3D6; Fri, 6 Apr 2018 18:25:04 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 51F0A6D450; Fri, 6 Apr 2018 18:25:04 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4CCD21578D; Fri, 6 Apr 2018 18:25:04 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w36IP4kX097126; Fri, 6 Apr 2018 18:25:04 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w36IP4TO097124; Fri, 6 Apr 2018 18:25:04 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201804061825.w36IP4TO097124@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Fri, 6 Apr 2018 18:25:04 +0000 (UTC) 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 X-SVN-Group: stable-11 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable/11/usr.sbin: . efibootmgr X-SVN-Commit-Revision: 332126 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Apr 2018 18:25:04 -0000 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)