From owner-svn-src-all@freebsd.org Mon Apr 29 05:02:26 2019 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 DF2771580621; Mon, 29 Apr 2019 05:02:25 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 86AF38B829; Mon, 29 Apr 2019 05:02:25 +0000 (UTC) (envelope-from imp@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 791AD1D4B9; Mon, 29 Apr 2019 05:02:25 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x3T52PiZ018248; Mon, 29 Apr 2019 05:02:25 GMT (envelope-from imp@FreeBSD.org) Received: (from imp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x3T52PFD018247; Mon, 29 Apr 2019 05:02:25 GMT (envelope-from imp@FreeBSD.org) Message-Id: <201904290502.x3T52PFD018247@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: imp set sender to imp@FreeBSD.org using -f From: Warner Losh Date: Mon, 29 Apr 2019 05:02:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r346879 - head/stand/efi/loader X-SVN-Group: head X-SVN-Commit-Author: imp X-SVN-Commit-Paths: head/stand/efi/loader X-SVN-Commit-Revision: 346879 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 86AF38B829 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.94 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.998,0]; NEURAL_HAM_SHORT(-0.95)[-0.945,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 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: Mon, 29 Apr 2019 05:02:26 -0000 Author: imp Date: Mon Apr 29 05:02:25 2019 New Revision: 346879 URL: https://svnweb.freebsd.org/changeset/base/346879 Log: Read in and parse /efi/freebsd/loader.env from the boot device's partition as if it were on the command line. Fetch FreeBSD-LoaderEnv UEFI enviornment variable. If set, read in loader environment variables from it. Otherwise read in /efi/freebsd/loader.env. Both are read relative to the device loader.efi loaded from (they aren't full UEFI device paths) Next fetch FreeBSD-NextLoaderEnv UEFI environment variable. If present, read the file it points to in as above and delete the UEFI environment variable so it only happens once. This lets one set environment variables in the bootloader. Unfortunately, we don't have all the mechanisms in place to parse the file, nor do we have the magic pattern matching in place that loader.conf has. Variables are of the form foo=bar. No quotes are supported, so spaces aren't allowed, for example. Also, variables like foo_load=yes are intercepted when we parse the loader.conf file and things are done based on that. Since those aren't done here, variables that cause an action to happen won't work. Reviewed by: bcran Differential Revision: https://reviews.freebsd.org/D20016 Modified: head/stand/efi/loader/main.c Modified: head/stand/efi/loader/main.c ============================================================================== --- head/stand/efi/loader/main.c Mon Apr 29 05:01:34 2019 (r346878) +++ head/stand/efi/loader/main.c Mon Apr 29 05:02:25 2019 (r346879) @@ -742,6 +742,80 @@ out: return (how); } +void +parse_loader_efi_config(EFI_HANDLE h, const char *env_fn) +{ + pdinfo_t *dp; + struct stat st; + int fd = -1; + char *env = NULL; + + dp = efiblk_get_pdinfo_by_handle(h); + if (dp == NULL) + return; + set_currdev_pdinfo(dp); + if (stat(env_fn, &st) != 0) + return; + fd = open(env_fn, O_RDONLY); + if (fd == -1) + return; + env = malloc(st.st_size + 1); + if (env == NULL) + goto out; + if (read(fd, env, st.st_size) != st.st_size) + goto out; + env[st.st_size] = '\0'; + boot_parse_cmdline(env); +out: + free(env); + close(fd); +} + +static void +read_loader_env(const char *name, char *def_fn, bool once) +{ + UINTN len; + char *fn, *freeme = NULL; + + len = 0; + fn = def_fn; + if (efi_freebsd_getenv(name, NULL, &len) == EFI_BUFFER_TOO_SMALL) { + freeme = fn = malloc(len + 1); + if (fn != NULL) { + if (efi_freebsd_getenv(name, fn, &len) != EFI_SUCCESS) { + free(fn); + fn = NULL; + printf( + "Can't fetch FreeBSD::%s we know is there\n", name); + } else { + /* + * if tagged as 'once' delete the env variable so we + * only use it once. + */ + if (once) + efi_freebsd_delenv(name); + /* + * We malloced 1 more than len above, then redid the call. + * so now we have room at the end of the string to NUL terminate + * it here, even if the typical idium would have '- 1' here to + * not overflow. len should be the same on return both times. + */ + fn[len] = '\0'; + } + } else { + printf( + "Can't allocate %d bytes to fetch FreeBSD::%s env var\n", + len, name); + } + } + if (fn) { + printf(" Reading loader env vars from %s\n", fn); + parse_loader_efi_config(boot_img->DeviceHandle, fn); + } +} + + + EFI_STATUS main(int argc, CHAR16 *argv[]) { @@ -812,6 +886,38 @@ main(int argc, CHAR16 *argv[]) howto |= RB_SERIAL | RB_MULTIPLE; howto &= ~RB_PROBE; uhowto = parse_uefi_con_out(); + + /* + * Scan the BLOCK IO MEDIA handles then + * march through the device switch probing for things. + */ + i = efipart_inithandles(); + if (i != 0 && i != ENOENT) { + printf("efipart_inithandles failed with ERRNO %d, expect " + "failures\n", i); + } + + for (i = 0; devsw[i] != NULL; i++) + if (devsw[i]->dv_init != NULL) + (devsw[i]->dv_init)(); + + /* + * Read additional environment variables from the boot device's + * "LoaderEnv" file. Any boot loader environment variable may be set + * there, which are subtly different than loader.conf variables. Only + * the 'simple' ones may be set so things like foo_load="YES" won't work + * for two reasons. First, the parser is simplistic and doesn't grok + * quotes. Second, because the variables that cause an action to happen + * are parsed by the lua, 4th or whatever code that's not yet + * loaded. This is relative to the root directory when loader.efi is + * loaded off the UFS root drive (when chain booted), or from the ESP + * when directly loaded by the BIOS. + * + * We also read in NextLoaderEnv if it was specified. This allows next boot + * functionality to be implemented and to override anything in LoaderEnv. + */ + read_loader_env("LoaderEnv", "/efi/freebsd/loader.env", false); + read_loader_env("NextLoaderEnv", NULL, true); /* * We now have two notions of console. howto should be viewed as