Module Name: src Committed By: jmcneill Date: Sun Sep 9 17:55:22 UTC 2018
Modified Files: src/sys/stand/efiboot: Makefile.efiboot boot.c version Added Files: src/sys/stand/efiboot: efienv.c efienv.h Log Message: Add support for setting environment variables. Currently the following env vars are supported: "fdtfile", "initrd", and "rootdev". To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/stand/efiboot/Makefile.efiboot cvs rdiff -u -r1.7 -r1.8 src/sys/stand/efiboot/boot.c cvs rdiff -u -r0 -r1.1 src/sys/stand/efiboot/efienv.c \ src/sys/stand/efiboot/efienv.h cvs rdiff -u -r1.2 -r1.3 src/sys/stand/efiboot/version Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/stand/efiboot/Makefile.efiboot diff -u src/sys/stand/efiboot/Makefile.efiboot:1.3 src/sys/stand/efiboot/Makefile.efiboot:1.4 --- src/sys/stand/efiboot/Makefile.efiboot:1.3 Mon Sep 3 00:04:02 2018 +++ src/sys/stand/efiboot/Makefile.efiboot Sun Sep 9 17:55:22 2018 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.efiboot,v 1.3 2018/09/03 00:04:02 jmcneill Exp $ +# $NetBSD: Makefile.efiboot,v 1.4 2018/09/09 17:55:22 jmcneill Exp $ S= ${.CURDIR}/../../.. @@ -22,7 +22,7 @@ AFLAGS.start.S= ${${ACTIVE_CC} == "clang .PATH: ${EFIDIR}/gnuefi SOURCES= crt0-efi-${GNUEFIARCH}.S reloc_${GNUEFIARCH}.c SOURCES+= boot.c conf.c console.c dev_net.c devopen.c exec.c panic.c prompt.c -SOURCES+= efiboot.c efichar.c efidev.c efigetsecs.c efifdt.c efifile.c efiblock.c efinet.c efipxe.c +SOURCES+= efiboot.c efichar.c efidev.c efienv.c efigetsecs.c efifdt.c efifile.c efiblock.c efinet.c efipxe.c .PATH: ${S}/external/bsd/libfdt/dist CPPFLAGS+= -I${S}/external/bsd/libfdt/dist Index: src/sys/stand/efiboot/boot.c diff -u src/sys/stand/efiboot/boot.c:1.7 src/sys/stand/efiboot/boot.c:1.8 --- src/sys/stand/efiboot/boot.c:1.7 Sun Sep 9 13:37:54 2018 +++ src/sys/stand/efiboot/boot.c Sun Sep 9 17:55:22 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: boot.c,v 1.7 2018/09/09 13:37:54 jmcneill Exp $ */ +/* $NetBSD: boot.c,v 1.8 2018/09/09 17:55:22 jmcneill Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -30,6 +30,7 @@ #include "efiboot.h" #include "efiblock.h" #include "efifdt.h" +#include "efienv.h" #include <sys/bootblock.h> #include <sys/boot_flag.h> @@ -61,6 +62,10 @@ void command_dev(char *); void command_dtb(char *); void command_initrd(char *); void command_ls(char *); +void command_printenv(char *); +void command_setenv(char *); +void command_clearenv(char *); +void command_resetenv(char *); void command_reset(char *); void command_version(char *); void command_quit(char *); @@ -71,6 +76,10 @@ const struct boot_command commands[] = { { "dtb", command_dtb, "dtb [dev:][filename]" }, { "initrd", command_initrd, "initrd [dev:][filename]" }, { "ls", command_ls, "ls [hdNn:/path]" }, + { "printenv", command_printenv, "printenv [key]" }, + { "setenv", command_setenv, "setenv <key> <value>" }, + { "clearenv", command_clearenv, "clearenv <key>" }, + { "resetenv", command_resetenv, "resetenv" }, { "version", command_version, "version" }, { "help", command_help, "help|?" }, { "?", command_help, NULL }, @@ -135,6 +144,53 @@ command_ls(char *arg) } void +command_printenv(char *arg) +{ + char *val; + + if (arg && *arg) { + val = efi_env_get(arg); + if (val) { + printf("\"%s\" = \"%s\"\n", arg, val); + FreePool(val); + } + } else { + efi_env_print(); + } +} + +void +command_setenv(char *arg) +{ + char *spc; + + spc = strchr(arg, ' '); + if (spc == NULL || spc[1] == '\0') { + command_help(""); + return; + } + + *spc = '\0'; + efi_env_set(arg, spc + 1); +} + +void +command_clearenv(char *arg) +{ + if (*arg == '\0') { + command_help(""); + return; + } + efi_env_clear(arg); +} + +void +command_resetenv(char *arg) +{ + efi_env_reset(); +} + +void command_version(char *arg) { char *ufirmware; @@ -213,11 +269,46 @@ print_banner(void) bootprog_name, bootprog_rev, bootprog_kernrev); } +static void +read_env(void) +{ + char *s; + + s = efi_env_get("fdtfile"); + if (s) { +#ifdef EFIBOOT_DEBUG + printf(">> Setting DTB path to '%s' from environment\n", s); +#endif + set_dtb_path(s); + FreePool(s); + } + + s = efi_env_get("initrd"); + if (s) { +#ifdef EFIBOOT_DEBUG + printf(">> Setting initrd path to '%s' from environment\n", s); +#endif + set_initrd_path(s); + FreePool(s); + } + + s = efi_env_get("rootdev"); + if (s) { +#ifdef EFIBOOT_DEBUG + printf(">> Setting default device to '%s' from environment\n", s); +#endif + set_default_device(s); + FreePool(s); + } +} + void boot(void) { int currname, c; + read_env(); + print_banner(); printf("Press return to boot now, any other key for boot prompt\n"); Index: src/sys/stand/efiboot/version diff -u src/sys/stand/efiboot/version:1.2 src/sys/stand/efiboot/version:1.3 --- src/sys/stand/efiboot/version:1.2 Mon Sep 3 00:04:02 2018 +++ src/sys/stand/efiboot/version Sun Sep 9 17:55:22 2018 @@ -1,4 +1,4 @@ -$NetBSD: version,v 1.2 2018/09/03 00:04:02 jmcneill Exp $ +$NetBSD: version,v 1.3 2018/09/09 17:55:22 jmcneill Exp $ NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this file is important - make sure the entries are appended on end, last item @@ -6,3 +6,4 @@ is taken as the current. 1.0: Initial version. 1.1: Add PXE booting support. +1.2: Add environment variable support. Added files: Index: src/sys/stand/efiboot/efienv.c diff -u /dev/null src/sys/stand/efiboot/efienv.c:1.1 --- /dev/null Sun Sep 9 17:55:22 2018 +++ src/sys/stand/efiboot/efienv.c Sun Sep 9 17:55:22 2018 @@ -0,0 +1,134 @@ +/* $NetBSD: efienv.c,v 1.1 2018/09/09 17:55:22 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> + * 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 REGENTS 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 REGENTS 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 "efiboot.h" +#include "efienv.h" + +#define EFIBOOT_VENDOR_GUID \ + { 0x97cde9bd, 0xac88, 0x4cf9, { 0x84, 0x86, 0x01, 0x33, 0x0f, 0xe1, 0x95, 0xd4 } } + +static EFI_GUID EfibootVendorGuid = EFIBOOT_VENDOR_GUID; + +void +efi_env_set(const char *key, char *val) +{ + EFI_STATUS status; + CHAR16 *ukey; + char *data; + size_t len; + + data = AllocatePool(strlen(val) + 1); + strcpy(data, val); + + utf8_to_ucs2(key, &ukey, &len); + status = LibSetNVVariable(ukey, &EfibootVendorGuid, strlen(data) + 1, data); + FreePool(ukey); + FreePool(data); + + if (EFI_ERROR(status)) + printf("env: failed to set variable '%s': %#lx\n", key, status); +} + +char * +efi_env_get(const char *key) +{ + CHAR16 *ukey; + size_t len; + char *ret; + + utf8_to_ucs2(key, &ukey, &len); + ret = LibGetVariable(ukey, &EfibootVendorGuid); + FreePool(ukey); + + return ret; +} + +void +efi_env_clear(const char *key) +{ + CHAR16 *ukey; + size_t len; + + utf8_to_ucs2(key, &ukey, &len); + LibDeleteVariable(ukey, &EfibootVendorGuid); + FreePool(ukey); +} + +void +efi_env_reset(void) +{ + EFI_STATUS status; + CHAR16 ukey[256]; + EFI_GUID vendor; + UINTN size; + +retry: + ukey[0] = '\0'; + vendor = NullGuid; + + for (;;) { + size = sizeof(ukey); + status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, ukey, &vendor); + if (status != EFI_SUCCESS) + break; + + if (CompareGuid(&vendor, &EfibootVendorGuid) == 0) { + LibDeleteVariable(ukey, &vendor); + goto retry; + } + } +} + +void +efi_env_print(void) +{ + EFI_STATUS status; + CHAR16 ukey[256]; + EFI_GUID vendor; + UINTN size; + char *val; + + ukey[0] = '\0'; + vendor = NullGuid; + + for (;;) { + size = sizeof(ukey); + status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, ukey, &vendor); + if (status != EFI_SUCCESS) + break; + + if (CompareGuid(&vendor, &EfibootVendorGuid) != 0) + continue; + + Print(L"\"%s\" = ", ukey); + + val = LibGetVariable(ukey, &vendor); + printf("\"%s\"\n", val); + FreePool(val); + } +} Index: src/sys/stand/efiboot/efienv.h diff -u /dev/null src/sys/stand/efiboot/efienv.h:1.1 --- /dev/null Sun Sep 9 17:55:22 2018 +++ src/sys/stand/efiboot/efienv.h Sun Sep 9 17:55:22 2018 @@ -0,0 +1,33 @@ +/* $NetBSD: efienv.h,v 1.1 2018/09/09 17:55:22 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> + * 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 REGENTS 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 REGENTS 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. + */ + +void efi_env_set(const char *, char *); +char *efi_env_get(const char *); +void efi_env_clear(const char *); +void efi_env_reset(void); +void efi_env_print(void);