changeset 19591:0a306c8a3b2d

9540 libefi: add efienv functions Reviewed by: Jason King <jason.brian.king@gmail.com> Reviewed by: Igor Kozhukhov <igor@dilos.org> Approved by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
author Toomas Soome <tsoome@me.com>
date Wed, 14 Mar 2018 07:49:04 +0200
parents 2b8355c8681c
children a905b8c9e72f 133c34d5848c
files usr/src/boot/sys/boot/efi/include/efi.h usr/src/boot/sys/boot/efi/include/efilib.h usr/src/boot/sys/boot/efi/libefi/Makefile usr/src/boot/sys/boot/efi/libefi/efienv.c usr/src/boot/sys/boot/efi/libefi/env.c
diffstat 5 files changed, 142 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/boot/sys/boot/efi/include/efi.h	Sat Jun 02 10:18:58 2018 +0000
+++ b/usr/src/boot/sys/boot/efi/include/efi.h	Wed Mar 14 07:49:04 2018 +0200
@@ -61,4 +61,9 @@
 #include "efipoint.h"
 #include "efiuga.h"
 
+/*
+ * illumos UUID
+ */
+#define	ILLUMOS_BOOT_VAR_GUID \
+	{ 0x8B54B311, 0x7163, 0x40d3, {0xA6, 0x7B, 0xE7, 0xB2, 0x95, 0x1B, 0x3D, 0x56} }
 #endif
--- a/usr/src/boot/sys/boot/efi/include/efilib.h	Sat Jun 02 10:18:58 2018 +0000
+++ b/usr/src/boot/sys/boot/efi/include/efilib.h	Wed Mar 14 07:49:04 2018 +0200
@@ -1,4 +1,4 @@
-/*-
+/*
  * Copyright (c) 2000 Doug Rabson
  * Copyright (c) 2006 Marcel Moolenaar
  * All rights reserved.
@@ -106,6 +106,17 @@
 void cpy8to16(const char *, CHAR16 *, size_t);
 void cpy16to8(const CHAR16 *, char *, size_t);
 
+/*
+ * Routines for interacting with EFI's env vars in a more unix-like
+ * way than the standard APIs. In addition, convenience routines for
+ * the loader setting / getting illumos specific variables.
+ */
+
+EFI_STATUS efi_illumos_getenv(const char *v, void *data, size_t *len);
+EFI_STATUS efi_getenv(EFI_GUID *g, const char *v, void *data, size_t *len);
+EFI_STATUS efi_global_getenv(const char *v, void *data, size_t *len);
+EFI_STATUS efi_setenv_illumos_wcs(const char *varname, CHAR16 *valstr);
+
 /* guids and names */
 bool efi_guid_to_str(const EFI_GUID *, char **);
 bool efi_str_to_guid(const char *, EFI_GUID *);
--- a/usr/src/boot/sys/boot/efi/libefi/Makefile	Sat Jun 02 10:18:58 2018 +0000
+++ b/usr/src/boot/sys/boot/efi/libefi/Makefile	Wed Mar 14 07:49:04 2018 +0200
@@ -30,6 +30,7 @@
 	efi_console.c \
 	efi_driver_utils.c \
 	efichar.c \
+	efienv.c \
 	efinet.c \
 	efipart.c \
 	efizfs.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/boot/sys/boot/efi/libefi/efienv.c	Wed Mar 14 07:49:04 2018 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018 Netflix, Inc.
+ * 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
+
+#include <stand.h>
+#include <efi.h>
+#include <efichar.h>
+#include <efilib.h>
+
+static EFI_GUID illumosBootVarGUID = ILLUMOS_BOOT_VAR_GUID;
+static EFI_GUID GlobalBootVarGUID = EFI_GLOBAL_VARIABLE;
+
+EFI_STATUS
+efi_getenv(EFI_GUID *g, const char *v, void *data, size_t *len)
+{
+	size_t ul;
+	CHAR16 *uv;
+	UINT32 attr;
+	UINTN dl;
+	EFI_STATUS rv;
+
+	uv = NULL;
+	if (utf8_to_ucs2(v, &uv, &ul) != 0)
+		return (EFI_OUT_OF_RESOURCES);
+	dl = *len;
+	rv = RS->GetVariable(uv, g, &attr, &dl, data);
+	if (rv == EFI_SUCCESS)
+		*len = dl;
+	free(uv);
+	return (rv);
+}
+
+EFI_STATUS
+efi_global_getenv(const char *v, void *data, size_t *len)
+{
+
+	return (efi_getenv(&GlobalBootVarGUID, v, data, len));
+}
+
+EFI_STATUS
+efi_illumos_getenv(const char *v, void *data, size_t *len)
+{
+
+	return (efi_getenv(&illumosBootVarGUID, v, data, len));
+}
+
+EFI_STATUS
+efi_setenv_illumos_wcs(const char *varname, CHAR16 *valstr)
+{
+	CHAR16 *var = NULL;
+	size_t len;
+	EFI_STATUS rv;
+
+	if (utf8_to_ucs2(varname, &var, &len) != 0)
+		return (EFI_OUT_OF_RESOURCES);
+	rv = RS->SetVariable(var, &illumosBootVarGUID,
+	    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+	    (ucs2len(valstr) + 1) * sizeof (CHAR16), valstr);
+	free(var);
+	return (rv);
+}
--- a/usr/src/boot/sys/boot/efi/libefi/env.c	Sat Jun 02 10:18:58 2018 +0000
+++ b/usr/src/boot/sys/boot/efi/libefi/env.c	Wed Mar 14 07:49:04 2018 +0200
@@ -28,6 +28,7 @@
 #include <stand.h>
 #include <string.h>
 #include <efi.h>
+#include <efichar.h>
 #include <efilib.h>
 #include <efigpt.h>	/* Partition GUIDS */
 #include <Guid/MemoryTypeInformation.h>
@@ -46,6 +47,7 @@
 	EFI_GUID efi_guid;
 } efi_uuid_mapping[] = {
 	{ .efi_guid_name = "global", .efi_guid = EFI_GLOBAL_VARIABLE },
+	{ .efi_guid_name = "illumos", .efi_guid = ILLUMOS_BOOT_VAR_GUID },
 	/* EFI Systab entry names. */
 	{ .efi_guid_name = "MPS Table", .efi_guid = MPS_TABLE_GUID },
 	{ .efi_guid_name = "ACPI Table", .efi_guid = ACPI_TABLE_GUID },
@@ -102,12 +104,12 @@
 	{ .efi_guid_name = "loaded image device path",
 	    .efi_guid = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID },
 	{ .efi_guid_name = "ISA io", .efi_guid = EFI_ISA_IO_PROTOCOL_GUID },
-        { .efi_guid_name = "IDE controller init",
+	{ .efi_guid_name = "IDE controller init",
 	    .efi_guid = EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID },
-        { .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID },
-        { .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID },
-        { .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID },
-        { .efi_guid_name = "PCI enumeration",
+	{ .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID },
+	{ .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID },
+	{ .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID },
+	{ .efi_guid_name = "PCI enumeration",
 	    .efi_guid = EFI_PCI_ENUMERATION_COMPLETE_GUID },
         { .efi_guid_name = "Driver diagnostics",
 	    .efi_guid = EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID },
@@ -443,24 +445,43 @@
 	return (CMD_OK);
 }
 
+/*
+ * Print illumos variables.
+ * We have LoaderPath and LoaderDev as CHAR16 strings.
+ */
+static int
+efi_print_illumos(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
+{
+	int rv = -1;
+	char *var = NULL;
+
+	if (ucs2_to_utf8(varnamearg, &var) != 0)
+		return (CMD_ERROR);
+
+	if (strcmp("LoaderPath", var) == 0 ||
+	    strcmp("LoaderDev", var) == 0) {
+		printf(" = ");
+		printf("%S", (CHAR16 *)data);
+
+		if (pager_output("\n"))
+			rv = CMD_WARN;
+		else
+			rv = CMD_OK;
+	}
+
+	free(var);
+	return (rv);
+}
+
 /* Print global variables. */
 static int
 efi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
 {
-	int len;
 	int rv = -1;
-	char *var;
-
-	for (len = 0; varnamearg[len] != 0; len++)
-		;
+	char *var = NULL;
 
-	if (len == 0)
-		return (CMD_OK);
-	len++;
-
-	if ((var = malloc(len)) == NULL)
+	if (ucs2_to_utf8(varnamearg, &var) != 0)
 		return (CMD_ERROR);
-	cpy16to8(varnamearg, var, len);
 
 	if (strcmp("AuditMode", var) == 0) {
 		printf(" = ");
@@ -667,6 +688,8 @@
 	if (lflag == 0) {
 		if (strcmp(str, "global") == 0)
 			rv = efi_print_global(varnamearg, data, datasz);
+		else if (strcmp(str, "illumos") == 0)
+			rv = efi_print_illumos(varnamearg, data, datasz);
 		else if (strcmp(str,
 		    EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0)
 			rv = efi_print_mem_type(varnamearg, data, datasz);