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);

Reply via email to