xref: /illumos-gate/usr/src/boot/sys/boot/efi/libefi/env.c (revision 8eef2ab6)
1eee59048SToomas Soome /*
2eee59048SToomas Soome  * Copyright (c) 2015 Netflix, Inc. All Rights Reserved.
3eee59048SToomas Soome  *
4eee59048SToomas Soome  * Redistribution and use in source and binary forms, with or without
5eee59048SToomas Soome  * modification, are permitted provided that the following conditions
6eee59048SToomas Soome  * are met:
7eee59048SToomas Soome  * 1. Redistributions of source code must retain the above copyright
8eee59048SToomas Soome  *    notice, this list of conditions and the following disclaimer.
9eee59048SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
10eee59048SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
11eee59048SToomas Soome  *    documentation and/or other materials provided with the distribution.
12eee59048SToomas Soome  *
13eee59048SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14eee59048SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15eee59048SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16eee59048SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17eee59048SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18eee59048SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19eee59048SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20eee59048SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21eee59048SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22eee59048SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23eee59048SToomas Soome  * SUCH DAMAGE.
24eee59048SToomas Soome  */
25eee59048SToomas Soome 
26eee59048SToomas Soome #include <sys/cdefs.h>
27eee59048SToomas Soome 
28eee59048SToomas Soome #include <stand.h>
29eee59048SToomas Soome #include <string.h>
30eee59048SToomas Soome #include <efi.h>
318dff7262SToomas Soome #include <efichar.h>
32eee59048SToomas Soome #include <efilib.h>
33eee59048SToomas Soome #include <efigpt.h>	/* Partition GUIDS */
34eee59048SToomas Soome #include <Guid/MemoryTypeInformation.h>
35eee59048SToomas Soome #include <Guid/MtcVendor.h>
36eee59048SToomas Soome #include <Guid/ZeroGuid.h>
37eee59048SToomas Soome #include <Protocol/EdidActive.h>
38eee59048SToomas Soome #include <Protocol/EdidDiscovered.h>
39eee59048SToomas Soome #include <uuid.h>
40eee59048SToomas Soome #include <stdbool.h>
41eee59048SToomas Soome #include <sys/param.h>
42eee59048SToomas Soome #include "bootstrap.h"
43eee59048SToomas Soome #include "ficl.h"
44eee59048SToomas Soome 
452b811402SToomas Soome /*
462b811402SToomas Soome  * About ENABLE_UPDATES
472b811402SToomas Soome  *
482b811402SToomas Soome  * The UEFI variables are identified only by GUID and name, there is no
492b811402SToomas Soome  * way to (auto)detect the type for the value, so we need to process the
502b811402SToomas Soome  * variables case by case, as we do learn about them.
512b811402SToomas Soome  *
522b811402SToomas Soome  * While showing the variable name and the value is safe, we must not store
532b811402SToomas Soome  * random values nor allow removing (random) variables.
542b811402SToomas Soome  *
552b811402SToomas Soome  * Since we do have stub code to set/unset the variables, I do want to keep
562b811402SToomas Soome  * it to make the future development a bit easier, but the updates are disabled
572b811402SToomas Soome  * by default till:
582b811402SToomas Soome  *	a) the validation and data translation to values is properly implemented
592b811402SToomas Soome  *	b) We have established which variables we do allow to be updated.
602b811402SToomas Soome  * Therefore the set/unset code is included only for developers aid.
612b811402SToomas Soome  */
622b811402SToomas Soome 
63eee59048SToomas Soome static struct efi_uuid_mapping {
64eee59048SToomas Soome 	const char *efi_guid_name;
65eee59048SToomas Soome 	EFI_GUID efi_guid;
66eee59048SToomas Soome } efi_uuid_mapping[] = {
67eee59048SToomas Soome 	{ .efi_guid_name = "global", .efi_guid = EFI_GLOBAL_VARIABLE },
688dff7262SToomas Soome 	{ .efi_guid_name = "illumos", .efi_guid = ILLUMOS_BOOT_VAR_GUID },
69eee59048SToomas Soome 	/* EFI Systab entry names. */
70eee59048SToomas Soome 	{ .efi_guid_name = "MPS Table", .efi_guid = MPS_TABLE_GUID },
71eee59048SToomas Soome 	{ .efi_guid_name = "ACPI Table", .efi_guid = ACPI_TABLE_GUID },
72eee59048SToomas Soome 	{ .efi_guid_name = "ACPI 2.0 Table", .efi_guid = ACPI_20_TABLE_GUID },
73eee59048SToomas Soome 	{ .efi_guid_name = "SMBIOS Table", .efi_guid = SMBIOS_TABLE_GUID },
74eee59048SToomas Soome 	{ .efi_guid_name = "SMBIOS3 Table", .efi_guid = SMBIOS3_TABLE_GUID },
75eee59048SToomas Soome 	{ .efi_guid_name = "DXE Table", .efi_guid = DXE_SERVICES_TABLE_GUID },
76eee59048SToomas Soome 	{ .efi_guid_name = "HOB List Table", .efi_guid = HOB_LIST_TABLE_GUID },
77eee59048SToomas Soome 	{ .efi_guid_name = EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
78eee59048SToomas Soome 	    .efi_guid = EFI_MEMORY_TYPE_INFORMATION_GUID },
79eee59048SToomas Soome 	{ .efi_guid_name = "Debug Image Info Table",
80eee59048SToomas Soome 	    .efi_guid = DEBUG_IMAGE_INFO_TABLE_GUID },
81eee59048SToomas Soome 	{ .efi_guid_name = "FDT Table", .efi_guid = FDT_TABLE_GUID },
82eee59048SToomas Soome 	/*
83eee59048SToomas Soome 	 * Protocol names for debug purposes.
84eee59048SToomas Soome 	 * Can be removed along with lsefi command.
85eee59048SToomas Soome 	 */
86eee59048SToomas Soome 	{ .efi_guid_name = "device path", .efi_guid = DEVICE_PATH_PROTOCOL },
87eee59048SToomas Soome 	{ .efi_guid_name = "block io", .efi_guid = BLOCK_IO_PROTOCOL },
88eee59048SToomas Soome 	{ .efi_guid_name = "disk io", .efi_guid = DISK_IO_PROTOCOL },
89eee59048SToomas Soome 	{ .efi_guid_name = "disk info", .efi_guid =
90eee59048SToomas Soome 	    EFI_DISK_INFO_PROTOCOL_GUID },
91eee59048SToomas Soome 	{ .efi_guid_name = "simple fs",
92eee59048SToomas Soome 	    .efi_guid = SIMPLE_FILE_SYSTEM_PROTOCOL },
93eee59048SToomas Soome 	{ .efi_guid_name = "load file", .efi_guid = LOAD_FILE_PROTOCOL },
94eee59048SToomas Soome 	{ .efi_guid_name = "device io", .efi_guid = DEVICE_IO_PROTOCOL },
95eee59048SToomas Soome 	{ .efi_guid_name = "unicode collation",
96eee59048SToomas Soome 	    .efi_guid = UNICODE_COLLATION_PROTOCOL },
97eee59048SToomas Soome 	{ .efi_guid_name = "unicode collation2",
98eee59048SToomas Soome 	    .efi_guid = EFI_UNICODE_COLLATION2_PROTOCOL_GUID },
99eee59048SToomas Soome 	{ .efi_guid_name = "simple network",
100eee59048SToomas Soome 	    .efi_guid = EFI_SIMPLE_NETWORK_PROTOCOL },
101eee59048SToomas Soome 	{ .efi_guid_name = "simple text output",
102eee59048SToomas Soome 	    .efi_guid = SIMPLE_TEXT_OUTPUT_PROTOCOL },
103eee59048SToomas Soome 	{ .efi_guid_name = "simple text input",
104eee59048SToomas Soome 	    .efi_guid = SIMPLE_TEXT_INPUT_PROTOCOL },
105eee59048SToomas Soome 	{ .efi_guid_name = "simple text ex input",
106eee59048SToomas Soome 	    .efi_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID },
107eee59048SToomas Soome 	{ .efi_guid_name = "console control",
108eee59048SToomas Soome 	    .efi_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID },
109eee59048SToomas Soome 	{ .efi_guid_name = "stdin", .efi_guid = EFI_CONSOLE_IN_DEVICE_GUID },
110eee59048SToomas Soome 	{ .efi_guid_name = "stdout", .efi_guid = EFI_CONSOLE_OUT_DEVICE_GUID },
111eee59048SToomas Soome 	{ .efi_guid_name = "stderr",
112eee59048SToomas Soome 	    .efi_guid = EFI_STANDARD_ERROR_DEVICE_GUID },
113eee59048SToomas Soome 	{ .efi_guid_name = "GOP",
114eee59048SToomas Soome 	    .efi_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID },
115eee59048SToomas Soome 	{ .efi_guid_name = "UGA draw", .efi_guid = EFI_UGA_DRAW_PROTOCOL_GUID },
116eee59048SToomas Soome 	{ .efi_guid_name = "PXE base code",
117eee59048SToomas Soome 	    .efi_guid = EFI_PXE_BASE_CODE_PROTOCOL },
118eee59048SToomas Soome 	{ .efi_guid_name = "PXE base code callback",
119eee59048SToomas Soome 	    .efi_guid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL },
120eee59048SToomas Soome 	{ .efi_guid_name = "serial io", .efi_guid = SERIAL_IO_PROTOCOL },
121eee59048SToomas Soome 	{ .efi_guid_name = "loaded image", .efi_guid = LOADED_IMAGE_PROTOCOL },
122eee59048SToomas Soome 	{ .efi_guid_name = "loaded image device path",
123eee59048SToomas Soome 	    .efi_guid = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID },
124eee59048SToomas Soome 	{ .efi_guid_name = "ISA io", .efi_guid = EFI_ISA_IO_PROTOCOL_GUID },
1258dff7262SToomas Soome 	{ .efi_guid_name = "IDE controller init",
126eee59048SToomas Soome 	    .efi_guid = EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID },
1278dff7262SToomas Soome 	{ .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID },
1288dff7262SToomas Soome 	{ .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID },
1298dff7262SToomas Soome 	{ .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID },
1308dff7262SToomas Soome 	{ .efi_guid_name = "PCI enumeration",
131eee59048SToomas Soome 	    .efi_guid = EFI_PCI_ENUMERATION_COMPLETE_GUID },
132eee59048SToomas Soome         { .efi_guid_name = "Driver diagnostics",
133eee59048SToomas Soome 	    .efi_guid = EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID },
134eee59048SToomas Soome         { .efi_guid_name = "Driver diagnostics2",
135eee59048SToomas Soome 	    .efi_guid = EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID },
136eee59048SToomas Soome         { .efi_guid_name = "simple pointer",
137eee59048SToomas Soome 	    .efi_guid = EFI_SIMPLE_POINTER_PROTOCOL_GUID },
138eee59048SToomas Soome         { .efi_guid_name = "absolute pointer",
139eee59048SToomas Soome 	    .efi_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID },
140eee59048SToomas Soome         { .efi_guid_name = "VLAN config",
141eee59048SToomas Soome 	    .efi_guid = EFI_VLAN_CONFIG_PROTOCOL_GUID },
142eee59048SToomas Soome         { .efi_guid_name = "ARP service binding",
143eee59048SToomas Soome 	    .efi_guid = EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID },
144eee59048SToomas Soome         { .efi_guid_name = "ARP", .efi_guid = EFI_ARP_PROTOCOL_GUID },
145eee59048SToomas Soome         { .efi_guid_name = "IPv4 service binding",
146eee59048SToomas Soome 	    .efi_guid = EFI_IP4_SERVICE_BINDING_PROTOCOL },
147eee59048SToomas Soome         { .efi_guid_name = "IPv4", .efi_guid = EFI_IP4_PROTOCOL },
148eee59048SToomas Soome         { .efi_guid_name = "IPv4 config",
149eee59048SToomas Soome 	    .efi_guid = EFI_IP4_CONFIG_PROTOCOL_GUID },
150eee59048SToomas Soome         { .efi_guid_name = "IPv6 service binding",
151eee59048SToomas Soome 	    .efi_guid = EFI_IP6_SERVICE_BINDING_PROTOCOL },
152eee59048SToomas Soome         { .efi_guid_name = "IPv6", .efi_guid = EFI_IP6_PROTOCOL },
153eee59048SToomas Soome         { .efi_guid_name = "IPv6 config",
154eee59048SToomas Soome 	    .efi_guid = EFI_IP6_CONFIG_PROTOCOL_GUID },
155eee59048SToomas Soome         { .efi_guid_name = "UDPv4", .efi_guid = EFI_UDP4_PROTOCOL },
156eee59048SToomas Soome         { .efi_guid_name = "UDPv4 service binding",
157eee59048SToomas Soome 	    .efi_guid = EFI_UDP4_SERVICE_BINDING_PROTOCOL },
158eee59048SToomas Soome         { .efi_guid_name = "UDPv6", .efi_guid = EFI_UDP6_PROTOCOL },
159eee59048SToomas Soome         { .efi_guid_name = "UDPv6 service binding",
160eee59048SToomas Soome 	    .efi_guid = EFI_UDP6_SERVICE_BINDING_PROTOCOL },
161eee59048SToomas Soome         { .efi_guid_name = "TCPv4", .efi_guid = EFI_TCP4_PROTOCOL },
162eee59048SToomas Soome         { .efi_guid_name = "TCPv4 service binding",
163eee59048SToomas Soome 	    .efi_guid = EFI_TCP4_SERVICE_BINDING_PROTOCOL },
164eee59048SToomas Soome         { .efi_guid_name = "TCPv6", .efi_guid = EFI_TCP6_PROTOCOL },
165eee59048SToomas Soome         { .efi_guid_name = "TCPv6 service binding",
166eee59048SToomas Soome 	    .efi_guid = EFI_TCP6_SERVICE_BINDING_PROTOCOL },
167eee59048SToomas Soome         { .efi_guid_name = "EFI System partition",
168eee59048SToomas Soome 	    .efi_guid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID },
169eee59048SToomas Soome         { .efi_guid_name = "MBR legacy",
170eee59048SToomas Soome 	    .efi_guid = EFI_PART_TYPE_LEGACY_MBR_GUID },
171eee59048SToomas Soome         { .efi_guid_name = "device tree", .efi_guid = EFI_DEVICE_TREE_GUID },
172eee59048SToomas Soome         { .efi_guid_name = "USB io", .efi_guid = EFI_USB_IO_PROTOCOL_GUID },
173eee59048SToomas Soome         { .efi_guid_name = "USB2 HC", .efi_guid = EFI_USB2_HC_PROTOCOL_GUID },
174eee59048SToomas Soome         { .efi_guid_name = "component name",
175eee59048SToomas Soome 	    .efi_guid = EFI_COMPONENT_NAME_PROTOCOL_GUID },
176eee59048SToomas Soome         { .efi_guid_name = "component name2",
177eee59048SToomas Soome 	    .efi_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID },
178eee59048SToomas Soome         { .efi_guid_name = "driver binding",
179eee59048SToomas Soome 	    .efi_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID },
180eee59048SToomas Soome         { .efi_guid_name = "driver configuration",
181eee59048SToomas Soome 	    .efi_guid = EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID },
182eee59048SToomas Soome         { .efi_guid_name = "driver configuration2",
183eee59048SToomas Soome 	    .efi_guid = EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID },
184eee59048SToomas Soome         { .efi_guid_name = "decompress",
185eee59048SToomas Soome 	    .efi_guid = EFI_DECOMPRESS_PROTOCOL_GUID },
186eee59048SToomas Soome         { .efi_guid_name = "ebc interpreter",
187eee59048SToomas Soome 	    .efi_guid = EFI_EBC_INTERPRETER_PROTOCOL_GUID },
188eee59048SToomas Soome         { .efi_guid_name = "network interface identifier",
189eee59048SToomas Soome 	    .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL },
190eee59048SToomas Soome         { .efi_guid_name = "network interface identifier_31",
191eee59048SToomas Soome 	    .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31 },
192eee59048SToomas Soome         { .efi_guid_name = "managed network service binding",
193eee59048SToomas Soome 	    .efi_guid = EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID },
194eee59048SToomas Soome         { .efi_guid_name = "managed network",
195eee59048SToomas Soome 	    .efi_guid = EFI_MANAGED_NETWORK_PROTOCOL_GUID },
196eee59048SToomas Soome         { .efi_guid_name = "form browser",
197eee59048SToomas Soome 	    .efi_guid = EFI_FORM_BROWSER2_PROTOCOL_GUID },
198eee59048SToomas Soome         { .efi_guid_name = "HII config routing",
199eee59048SToomas Soome 	    .efi_guid = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID },
200eee59048SToomas Soome         { .efi_guid_name = "HII database",
201eee59048SToomas Soome 	    .efi_guid = EFI_HII_DATABASE_PROTOCOL_GUID },
202eee59048SToomas Soome         { .efi_guid_name = "HII string",
203eee59048SToomas Soome 	    .efi_guid = EFI_HII_STRING_PROTOCOL_GUID },
204eee59048SToomas Soome         { .efi_guid_name = "HII image",
205eee59048SToomas Soome 	    .efi_guid = EFI_HII_IMAGE_PROTOCOL_GUID },
206eee59048SToomas Soome         { .efi_guid_name = "HII font", .efi_guid = EFI_HII_FONT_PROTOCOL_GUID },
207eee59048SToomas Soome         { .efi_guid_name = "HII config",
208eee59048SToomas Soome 	    .efi_guid = EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID },
209eee59048SToomas Soome         { .efi_guid_name = "MTFTP4 service binding",
210eee59048SToomas Soome 	    .efi_guid = EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID },
211eee59048SToomas Soome         { .efi_guid_name = "MTFTP4", .efi_guid = EFI_MTFTP4_PROTOCOL_GUID },
212eee59048SToomas Soome         { .efi_guid_name = "MTFTP6 service binding",
213eee59048SToomas Soome 	    .efi_guid = EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID },
214eee59048SToomas Soome         { .efi_guid_name = "MTFTP6", .efi_guid = EFI_MTFTP6_PROTOCOL_GUID },
215eee59048SToomas Soome         { .efi_guid_name = "DHCP4 service binding",
216eee59048SToomas Soome 	    .efi_guid = EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID },
217eee59048SToomas Soome         { .efi_guid_name = "DHCP4", .efi_guid = EFI_DHCP4_PROTOCOL_GUID },
218eee59048SToomas Soome         { .efi_guid_name = "DHCP6 service binding",
219eee59048SToomas Soome 	    .efi_guid = EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID },
220eee59048SToomas Soome         { .efi_guid_name = "DHCP6", .efi_guid = EFI_DHCP6_PROTOCOL_GUID },
221eee59048SToomas Soome         { .efi_guid_name = "SCSI io", .efi_guid = EFI_SCSI_IO_PROTOCOL_GUID },
222eee59048SToomas Soome         { .efi_guid_name = "SCSI pass thru",
223eee59048SToomas Soome 	    .efi_guid = EFI_SCSI_PASS_THRU_PROTOCOL_GUID },
224eee59048SToomas Soome         { .efi_guid_name = "SCSI pass thru ext",
225eee59048SToomas Soome 	    .efi_guid = EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID },
226eee59048SToomas Soome         { .efi_guid_name = "Capsule arch",
227eee59048SToomas Soome 	    .efi_guid = EFI_CAPSULE_ARCH_PROTOCOL_GUID },
228eee59048SToomas Soome         { .efi_guid_name = "monotonic counter arch",
229eee59048SToomas Soome 	    .efi_guid = EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID },
230eee59048SToomas Soome         { .efi_guid_name = "realtime clock arch",
231eee59048SToomas Soome 	    .efi_guid = EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID },
232eee59048SToomas Soome         { .efi_guid_name = "variable arch",
233eee59048SToomas Soome 	    .efi_guid = EFI_VARIABLE_ARCH_PROTOCOL_GUID },
234eee59048SToomas Soome         { .efi_guid_name = "variable write arch",
235eee59048SToomas Soome 	    .efi_guid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID },
236eee59048SToomas Soome         { .efi_guid_name = "watchdog timer arch",
237eee59048SToomas Soome 	    .efi_guid = EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID },
238eee59048SToomas Soome         { .efi_guid_name = "ACPI support",
239eee59048SToomas Soome 	    .efi_guid = EFI_ACPI_SUPPORT_PROTOCOL_GUID },
240eee59048SToomas Soome         { .efi_guid_name = "BDS arch", .efi_guid = EFI_BDS_ARCH_PROTOCOL_GUID },
241eee59048SToomas Soome         { .efi_guid_name = "metronome arch",
242eee59048SToomas Soome 	    .efi_guid = EFI_METRONOME_ARCH_PROTOCOL_GUID },
243eee59048SToomas Soome         { .efi_guid_name = "timer arch",
244eee59048SToomas Soome 	    .efi_guid = EFI_TIMER_ARCH_PROTOCOL_GUID },
245eee59048SToomas Soome         { .efi_guid_name = "DPC", .efi_guid = EFI_DPC_PROTOCOL_GUID },
246eee59048SToomas Soome         { .efi_guid_name = "print2", .efi_guid = EFI_PRINT2_PROTOCOL_GUID },
247eee59048SToomas Soome         { .efi_guid_name = "device path to text",
248eee59048SToomas Soome 	    .efi_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID },
249eee59048SToomas Soome         { .efi_guid_name = "reset arch",
250eee59048SToomas Soome 	    .efi_guid = EFI_RESET_ARCH_PROTOCOL_GUID },
251eee59048SToomas Soome         { .efi_guid_name = "CPU arch", .efi_guid = EFI_CPU_ARCH_PROTOCOL_GUID },
252eee59048SToomas Soome         { .efi_guid_name = "CPU IO2", .efi_guid = EFI_CPU_IO2_PROTOCOL_GUID },
253eee59048SToomas Soome         { .efi_guid_name = "Legacy 8259",
254eee59048SToomas Soome 	    .efi_guid = EFI_LEGACY_8259_PROTOCOL_GUID },
255eee59048SToomas Soome         { .efi_guid_name = "Security arch",
256eee59048SToomas Soome 	    .efi_guid = EFI_SECURITY_ARCH_PROTOCOL_GUID },
257eee59048SToomas Soome         { .efi_guid_name = "Security2 arch",
258eee59048SToomas Soome 	    .efi_guid = EFI_SECURITY2_ARCH_PROTOCOL_GUID },
259eee59048SToomas Soome         { .efi_guid_name = "Runtime arch",
260eee59048SToomas Soome 	    .efi_guid = EFI_RUNTIME_ARCH_PROTOCOL_GUID },
261eee59048SToomas Soome         { .efi_guid_name = "status code runtime",
262eee59048SToomas Soome 	    .efi_guid = EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID },
263eee59048SToomas Soome         { .efi_guid_name = "data hub", .efi_guid = EFI_DATA_HUB_PROTOCOL_GUID },
264eee59048SToomas Soome         { .efi_guid_name = "PCD", .efi_guid = PCD_PROTOCOL_GUID },
265eee59048SToomas Soome         { .efi_guid_name = "EFI PCD", .efi_guid = EFI_PCD_PROTOCOL_GUID },
266eee59048SToomas Soome         { .efi_guid_name = "firmware volume block",
267eee59048SToomas Soome 	    .efi_guid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID },
268eee59048SToomas Soome         { .efi_guid_name = "firmware volume2",
269eee59048SToomas Soome 	    .efi_guid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID },
270eee59048SToomas Soome         { .efi_guid_name = "firmware volume dispatch",
271eee59048SToomas Soome 	    .efi_guid = EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID },
272eee59048SToomas Soome         { .efi_guid_name = "lzma compress", .efi_guid = LZMA_COMPRESS_GUID },
273eee59048SToomas Soome         { .efi_guid_name = "MP services",
274eee59048SToomas Soome 	    .efi_guid = EFI_MP_SERVICES_PROTOCOL_GUID },
275eee59048SToomas Soome         { .efi_guid_name = MTC_VARIABLE_NAME, .efi_guid = MTC_VENDOR_GUID },
276eee59048SToomas Soome         { .efi_guid_name = "RTC", .efi_guid = { 0x378D7B65, 0x8DA9, 0x4773,
277eee59048SToomas Soome 	    { 0xB6, 0xE4, 0xA4, 0x78, 0x26, 0xA8, 0x33, 0xE1} } },
278eee59048SToomas Soome         { .efi_guid_name = "Active EDID",
279eee59048SToomas Soome 	    .efi_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID },
280eee59048SToomas Soome         { .efi_guid_name = "Discovered EDID",
281eee59048SToomas Soome 	    .efi_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID }
282eee59048SToomas Soome };
283eee59048SToomas Soome 
284eee59048SToomas Soome bool
efi_guid_to_str(const EFI_GUID * guid,char ** sp)285eee59048SToomas Soome efi_guid_to_str(const EFI_GUID *guid, char **sp)
286eee59048SToomas Soome {
287eee59048SToomas Soome 	uint32_t status;
288eee59048SToomas Soome 
289eee59048SToomas Soome 	uuid_to_string((const uuid_t *)guid, sp, &status);
290eee59048SToomas Soome 	return (status == uuid_s_ok ? true : false);
291eee59048SToomas Soome }
292eee59048SToomas Soome 
293eee59048SToomas Soome bool
efi_str_to_guid(const char * s,EFI_GUID * guid)294eee59048SToomas Soome efi_str_to_guid(const char *s, EFI_GUID *guid)
295eee59048SToomas Soome {
296eee59048SToomas Soome 	uint32_t status;
297eee59048SToomas Soome 
298eee59048SToomas Soome 	uuid_from_string(s, (uuid_t *)guid, &status);
299eee59048SToomas Soome 	return (status == uuid_s_ok ? true : false);
300eee59048SToomas Soome }
301eee59048SToomas Soome 
302eee59048SToomas Soome bool
efi_name_to_guid(const char * name,EFI_GUID * guid)303eee59048SToomas Soome efi_name_to_guid(const char *name, EFI_GUID *guid)
304eee59048SToomas Soome {
305eee59048SToomas Soome 	uint32_t i;
306eee59048SToomas Soome 
307eee59048SToomas Soome 	for (i = 0; i < nitems(efi_uuid_mapping); i++) {
308eee59048SToomas Soome 		if (strcasecmp(name, efi_uuid_mapping[i].efi_guid_name) == 0) {
309eee59048SToomas Soome 			*guid = efi_uuid_mapping[i].efi_guid;
310eee59048SToomas Soome 			return (true);
311eee59048SToomas Soome 		}
312eee59048SToomas Soome 	}
313eee59048SToomas Soome 	return (efi_str_to_guid(name, guid));
314eee59048SToomas Soome }
315eee59048SToomas Soome 
316eee59048SToomas Soome bool
efi_guid_to_name(EFI_GUID * guid,char ** name)317eee59048SToomas Soome efi_guid_to_name(EFI_GUID *guid, char **name)
318eee59048SToomas Soome {
319eee59048SToomas Soome 	uint32_t i;
320eee59048SToomas Soome 	int rv;
321eee59048SToomas Soome 
322eee59048SToomas Soome 	for (i = 0; i < nitems(efi_uuid_mapping); i++) {
323eee59048SToomas Soome 		rv = uuid_equal((uuid_t *)guid,
324eee59048SToomas Soome 		    (uuid_t *)&efi_uuid_mapping[i].efi_guid, NULL);
325eee59048SToomas Soome 		if (rv != 0) {
326eee59048SToomas Soome 			*name = strdup(efi_uuid_mapping[i].efi_guid_name);
327eee59048SToomas Soome 			if (*name == NULL)
328eee59048SToomas Soome 				return (false);
329eee59048SToomas Soome 			return (true);
330eee59048SToomas Soome 		}
331eee59048SToomas Soome 	}
332eee59048SToomas Soome 	return (efi_guid_to_str(guid, name));
333eee59048SToomas Soome }
334eee59048SToomas Soome 
335eee59048SToomas Soome void
efi_init_environment(void)336eee59048SToomas Soome efi_init_environment(void)
337eee59048SToomas Soome {
338eee59048SToomas Soome 	char var[128];
339eee59048SToomas Soome 
340eee59048SToomas Soome 	snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
341eee59048SToomas Soome 	    ST->Hdr.Revision & 0xffff);
342eee59048SToomas Soome 	env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
343eee59048SToomas Soome }
344eee59048SToomas Soome 
345eee59048SToomas Soome COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
346eee59048SToomas Soome 
347eee59048SToomas Soome static int
efi_print_other_value(uint8_t * data,UINTN datasz)348eee59048SToomas Soome efi_print_other_value(uint8_t *data, UINTN datasz)
349eee59048SToomas Soome {
350eee59048SToomas Soome 	UINTN i;
351eee59048SToomas Soome 	bool is_ascii = true;
352eee59048SToomas Soome 
353eee59048SToomas Soome 	printf(" = ");
354eee59048SToomas Soome 	for (i = 0; i < datasz - 1; i++) {
355eee59048SToomas Soome 		/*
356eee59048SToomas Soome 		 * Quick hack to see if this ascii-ish string is printable
357eee59048SToomas Soome 		 * range plus tab, cr and lf.
358eee59048SToomas Soome 		 */
359eee59048SToomas Soome 		if ((data[i] < 32 || data[i] > 126)
360eee59048SToomas Soome 		    && data[i] != 9 && data[i] != 10 && data[i] != 13) {
361eee59048SToomas Soome 			is_ascii = false;
362eee59048SToomas Soome 			break;
363eee59048SToomas Soome 		}
364eee59048SToomas Soome 	}
365eee59048SToomas Soome 	if (data[datasz - 1] != '\0')
366eee59048SToomas Soome 		is_ascii = false;
367eee59048SToomas Soome 	if (is_ascii == true) {
368eee59048SToomas Soome 		printf("%s", data);
369eee59048SToomas Soome 		if (pager_output("\n"))
370eee59048SToomas Soome 			return (CMD_WARN);
371eee59048SToomas Soome 	} else {
372eee59048SToomas Soome 		if (pager_output("\n"))
373eee59048SToomas Soome 			return (CMD_WARN);
374eee59048SToomas Soome 		/*
375eee59048SToomas Soome 		 * Dump hex bytes grouped by 4.
376eee59048SToomas Soome 		 */
377eee59048SToomas Soome 		for (i = 0; i < datasz; i++) {
378eee59048SToomas Soome 			printf("%02x ", data[i]);
379eee59048SToomas Soome 			if ((i + 1) % 4 == 0)
380eee59048SToomas Soome 				printf(" ");
381eee59048SToomas Soome 			if ((i + 1) % 20 == 0) {
382eee59048SToomas Soome 				if (pager_output("\n"))
383eee59048SToomas Soome 					return (CMD_WARN);
384eee59048SToomas Soome 			}
385eee59048SToomas Soome 		}
386eee59048SToomas Soome 		if (pager_output("\n"))
387eee59048SToomas Soome 			return (CMD_WARN);
388eee59048SToomas Soome 	}
389eee59048SToomas Soome 
390eee59048SToomas Soome 	return (CMD_OK);
391eee59048SToomas Soome }
392eee59048SToomas Soome 
393eee59048SToomas Soome /* This appears to be some sort of UEFI shell alias table. */
394eee59048SToomas Soome static int
efi_print_shell_str(const CHAR16 * varnamearg __unused,uint8_t * data,UINTN datasz __unused)395*8eef2ab6SToomas Soome efi_print_shell_str(const CHAR16 *varnamearg __unused, uint8_t *data,
396*8eef2ab6SToomas Soome     UINTN datasz __unused)
397eee59048SToomas Soome {
398eee59048SToomas Soome 	printf(" = %S", (CHAR16 *)data);
399eee59048SToomas Soome 	if (pager_output("\n"))
400eee59048SToomas Soome 		return (CMD_WARN);
401eee59048SToomas Soome 	return (CMD_OK);
402eee59048SToomas Soome }
403eee59048SToomas Soome 
404eee59048SToomas Soome const char *
efi_memory_type(EFI_MEMORY_TYPE type)405eee59048SToomas Soome efi_memory_type(EFI_MEMORY_TYPE type)
406eee59048SToomas Soome {
407eee59048SToomas Soome 	const char *types[] = {
408eee59048SToomas Soome 	    "Reserved",
409eee59048SToomas Soome 	    "LoaderCode",
410eee59048SToomas Soome 	    "LoaderData",
411eee59048SToomas Soome 	    "BootServicesCode",
412eee59048SToomas Soome 	    "BootServicesData",
413eee59048SToomas Soome 	    "RuntimeServicesCode",
414eee59048SToomas Soome 	    "RuntimeServicesData",
415eee59048SToomas Soome 	    "ConventionalMemory",
416eee59048SToomas Soome 	    "UnusableMemory",
417eee59048SToomas Soome 	    "ACPIReclaimMemory",
418eee59048SToomas Soome 	    "ACPIMemoryNVS",
419eee59048SToomas Soome 	    "MemoryMappedIO",
420eee59048SToomas Soome 	    "MemoryMappedIOPortSpace",
421eee59048SToomas Soome 	    "PalCode",
422eee59048SToomas Soome 	    "PersistentMemory"
423eee59048SToomas Soome 	};
4240e8ce6eeSToomas Soome 
425eee59048SToomas Soome 	switch (type) {
426eee59048SToomas Soome 	case EfiReservedMemoryType:
427eee59048SToomas Soome 	case EfiLoaderCode:
428eee59048SToomas Soome 	case EfiLoaderData:
429eee59048SToomas Soome 	case EfiBootServicesCode:
430eee59048SToomas Soome 	case EfiBootServicesData:
431eee59048SToomas Soome 	case EfiRuntimeServicesCode:
432eee59048SToomas Soome 	case EfiRuntimeServicesData:
433eee59048SToomas Soome 	case EfiConventionalMemory:
434eee59048SToomas Soome 	case EfiUnusableMemory:
435eee59048SToomas Soome 	case EfiACPIReclaimMemory:
436eee59048SToomas Soome 	case EfiACPIMemoryNVS:
437eee59048SToomas Soome 	case EfiMemoryMappedIO:
438eee59048SToomas Soome 	case EfiMemoryMappedIOPortSpace:
439eee59048SToomas Soome 	case EfiPalCode:
440eee59048SToomas Soome 	case EfiPersistentMemory:
441eee59048SToomas Soome 		return (types[type]);
4420e8ce6eeSToomas Soome 	default:
4430e8ce6eeSToomas Soome 		return ("Unknown");
444eee59048SToomas Soome 	}
445eee59048SToomas Soome }
446eee59048SToomas Soome 
447eee59048SToomas Soome /* Print memory type table. */
448eee59048SToomas Soome static int
efi_print_mem_type(const CHAR16 * varnamearg __unused,uint8_t * data,UINTN datasz)449*8eef2ab6SToomas Soome efi_print_mem_type(const CHAR16 *varnamearg __unused, uint8_t *data,
450*8eef2ab6SToomas Soome     UINTN datasz)
451eee59048SToomas Soome {
452eee59048SToomas Soome 	int i, n;
453eee59048SToomas Soome 	EFI_MEMORY_TYPE_INFORMATION *ti;
454eee59048SToomas Soome 
455eee59048SToomas Soome 	ti = (EFI_MEMORY_TYPE_INFORMATION *)data;
456eee59048SToomas Soome 	if (pager_output(" = \n"))
457eee59048SToomas Soome 		return (CMD_WARN);
458eee59048SToomas Soome 
459eee59048SToomas Soome 	n = datasz / sizeof (EFI_MEMORY_TYPE_INFORMATION);
460eee59048SToomas Soome 	for (i = 0; i < n && ti[i].NumberOfPages != 0; i++) {
461eee59048SToomas Soome 		printf("\t%23s pages: %u", efi_memory_type(ti[i].Type),
462eee59048SToomas Soome 		    ti[i].NumberOfPages);
463eee59048SToomas Soome 		if (pager_output("\n"))
464eee59048SToomas Soome 			return (CMD_WARN);
465eee59048SToomas Soome 	}
466eee59048SToomas Soome 
467eee59048SToomas Soome 	return (CMD_OK);
468eee59048SToomas Soome }
469eee59048SToomas Soome 
4708dff7262SToomas Soome /*
4718dff7262SToomas Soome  * Print illumos variables.
4728dff7262SToomas Soome  * We have LoaderPath and LoaderDev as CHAR16 strings.
4738dff7262SToomas Soome  */
474eee59048SToomas Soome static int
efi_print_illumos(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz __unused)475*8eef2ab6SToomas Soome efi_print_illumos(const CHAR16 *varnamearg, uint8_t *data,
476*8eef2ab6SToomas Soome     UINTN datasz __unused)
477eee59048SToomas Soome {
478eee59048SToomas Soome 	int rv = -1;
4798dff7262SToomas Soome 	char *var = NULL;
4808dff7262SToomas Soome 
4818dff7262SToomas Soome 	if (ucs2_to_utf8(varnamearg, &var) != 0)
4828dff7262SToomas Soome 		return (CMD_ERROR);
4838dff7262SToomas Soome 
4848dff7262SToomas Soome 	if (strcmp("LoaderPath", var) == 0 ||
4858dff7262SToomas Soome 	    strcmp("LoaderDev", var) == 0) {
4868dff7262SToomas Soome 		printf(" = ");
4878dff7262SToomas Soome 		printf("%S", (CHAR16 *)data);
4888dff7262SToomas Soome 
4898dff7262SToomas Soome 		if (pager_output("\n"))
4908dff7262SToomas Soome 			rv = CMD_WARN;
4918dff7262SToomas Soome 		else
4928dff7262SToomas Soome 			rv = CMD_OK;
4938dff7262SToomas Soome 	}
494eee59048SToomas Soome 
4958dff7262SToomas Soome 	free(var);
4968dff7262SToomas Soome 	return (rv);
4978dff7262SToomas Soome }
498eee59048SToomas Soome 
4998dff7262SToomas Soome /* Print global variables. */
5008dff7262SToomas Soome static int
efi_print_global(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz)5018dff7262SToomas Soome efi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
5028dff7262SToomas Soome {
5038dff7262SToomas Soome 	int rv = -1;
5048dff7262SToomas Soome 	char *var = NULL;
505eee59048SToomas Soome 
5068dff7262SToomas Soome 	if (ucs2_to_utf8(varnamearg, &var) != 0)
507eee59048SToomas Soome 		return (CMD_ERROR);
508eee59048SToomas Soome 
509eee59048SToomas Soome 	if (strcmp("AuditMode", var) == 0) {
510eee59048SToomas Soome 		printf(" = ");
511eee59048SToomas Soome 		printf("0x%x", *data);	/* 8-bit int */
512eee59048SToomas Soome 		goto done;
513eee59048SToomas Soome 	}
514eee59048SToomas Soome 
515eee59048SToomas Soome 	if (strcmp("BootOptionSupport", var) == 0) {
516eee59048SToomas Soome 		printf(" = ");
517eee59048SToomas Soome 		printf("0x%x", *((uint32_t *)data));	/* UINT32 */
518eee59048SToomas Soome 		goto done;
519eee59048SToomas Soome 	}
520eee59048SToomas Soome 
521eee59048SToomas Soome 	if (strcmp("BootCurrent", var) == 0 ||
522eee59048SToomas Soome 	    strcmp("BootNext", var) == 0 ||
523eee59048SToomas Soome 	    strcmp("Timeout", var) == 0) {
524eee59048SToomas Soome 		printf(" = ");
525eee59048SToomas Soome 		printf("%u", *((uint16_t *)data));	/* UINT16 */
526eee59048SToomas Soome 		goto done;
527eee59048SToomas Soome 	}
528eee59048SToomas Soome 
529eee59048SToomas Soome 	if (strcmp("BootOrder", var) == 0 ||
530eee59048SToomas Soome 	    strcmp("DriverOrder", var) == 0) {
531eee59048SToomas Soome 		int i;
532eee59048SToomas Soome 		UINT16 *u16 = (UINT16 *)data;
533eee59048SToomas Soome 
534eee59048SToomas Soome 		printf(" =");
535eee59048SToomas Soome 		for (i = 0; i < datasz / sizeof (UINT16); i++)
536eee59048SToomas Soome 			printf(" %u", u16[i]);
537eee59048SToomas Soome 		goto done;
538eee59048SToomas Soome 	}
539eee59048SToomas Soome 	if (strncmp("Boot", var, 4) == 0 ||
540eee59048SToomas Soome 	    strncmp("Driver", var, 5) == 0 ||
541eee59048SToomas Soome 	    strncmp("SysPrep", var, 7) == 0 ||
542eee59048SToomas Soome 	    strncmp("OsRecovery", var, 10) == 0) {
543eee59048SToomas Soome 		UINT16 filepathlistlen;
544eee59048SToomas Soome 		CHAR16 *text;
545eee59048SToomas Soome 		int desclen;
546eee59048SToomas Soome 		EFI_DEVICE_PATH *dp;
547eee59048SToomas Soome 
548eee59048SToomas Soome 		data += sizeof(UINT32);
549eee59048SToomas Soome 		filepathlistlen = *(uint16_t *)data;
550eee59048SToomas Soome 		data += sizeof (UINT16);
551eee59048SToomas Soome 		text = (CHAR16 *)data;
552eee59048SToomas Soome 
553eee59048SToomas Soome 		for (desclen = 0; text[desclen] != 0; desclen++)
554eee59048SToomas Soome 			;
555eee59048SToomas Soome 		if (desclen != 0) {
556eee59048SToomas Soome 			/* Add terminating zero and we have CHAR16. */
557eee59048SToomas Soome 			desclen = (desclen + 1) * 2;
558eee59048SToomas Soome 		}
559eee59048SToomas Soome 
560eee59048SToomas Soome 		printf(" = ");
561eee59048SToomas Soome 		printf("%S", text);
562eee59048SToomas Soome 		if (filepathlistlen != 0) {
563eee59048SToomas Soome 			/* Output pathname from new line. */
564eee59048SToomas Soome 			if (pager_output("\n")) {
565eee59048SToomas Soome 				rv = CMD_WARN;
566eee59048SToomas Soome 				goto done;
567eee59048SToomas Soome 			}
568eee59048SToomas Soome 			dp = malloc(filepathlistlen);
569eee59048SToomas Soome 			if (dp == NULL)
570eee59048SToomas Soome 				goto done;
571eee59048SToomas Soome 
572eee59048SToomas Soome 			memcpy(dp, data + desclen, filepathlistlen);
573eee59048SToomas Soome 			text = efi_devpath_name(dp);
574eee59048SToomas Soome 			if (text != NULL) {
575eee59048SToomas Soome 				printf("\t%S", text);
576eee59048SToomas Soome 				efi_free_devpath_name(text);
577eee59048SToomas Soome 			}
578eee59048SToomas Soome 			free(dp);
579eee59048SToomas Soome 		}
580eee59048SToomas Soome 		goto done;
581eee59048SToomas Soome 	}
582eee59048SToomas Soome 
583eee59048SToomas Soome 	if (strcmp("ConIn", var) == 0 ||
584eee59048SToomas Soome 	    strcmp("ConInDev", var) == 0 ||
585eee59048SToomas Soome 	    strcmp("ConOut", var) == 0 ||
586eee59048SToomas Soome 	    strcmp("ConOutDev", var) == 0 ||
587eee59048SToomas Soome 	    strcmp("ErrOut", var) == 0 ||
588eee59048SToomas Soome 	    strcmp("ErrOutDev", var) == 0) {
589eee59048SToomas Soome 		CHAR16 *text;
590eee59048SToomas Soome 
591eee59048SToomas Soome 		printf(" = ");
592eee59048SToomas Soome 		text = efi_devpath_name((EFI_DEVICE_PATH *)data);
593eee59048SToomas Soome 		if (text != NULL) {
594eee59048SToomas Soome 			printf("%S", text);
595eee59048SToomas Soome 			efi_free_devpath_name(text);
596eee59048SToomas Soome 		}
597eee59048SToomas Soome 		goto done;
598eee59048SToomas Soome 	}
599eee59048SToomas Soome 
600eee59048SToomas Soome 	if (strcmp("PlatformLang", var) == 0 ||
601eee59048SToomas Soome 	    strcmp("PlatformLangCodes", var) == 0 ||
602eee59048SToomas Soome 	    strcmp("LangCodes", var) == 0 ||
603eee59048SToomas Soome 	    strcmp("Lang", var) == 0) {
604eee59048SToomas Soome 		printf(" = ");
605eee59048SToomas Soome 		printf("%s", data);	/* ASCII string */
606eee59048SToomas Soome 		goto done;
607eee59048SToomas Soome 	}
608eee59048SToomas Soome 
609eee59048SToomas Soome 	/*
610eee59048SToomas Soome 	 * Feature bitmap from firmware to OS.
611eee59048SToomas Soome 	 * Older UEFI provides UINT32, newer UINT64.
612eee59048SToomas Soome 	 */
613eee59048SToomas Soome 	if (strcmp("OsIndicationsSupported", var) == 0) {
614eee59048SToomas Soome 		printf(" = ");
615eee59048SToomas Soome 		if (datasz == 4)
616eee59048SToomas Soome 			printf("0x%x", *((uint32_t *)data));
617eee59048SToomas Soome 		else
618eee59048SToomas Soome 			printf("0x%jx", *((uint64_t *)data));
619eee59048SToomas Soome 		goto done;
620eee59048SToomas Soome 	}
621eee59048SToomas Soome 
622eee59048SToomas Soome 	/* Fallback for anything else. */
623eee59048SToomas Soome 	rv = efi_print_other_value(data, datasz);
624eee59048SToomas Soome done:
625eee59048SToomas Soome 	if (rv == -1) {
626eee59048SToomas Soome 		if (pager_output("\n"))
627eee59048SToomas Soome 			rv = CMD_WARN;
628eee59048SToomas Soome 		else
629eee59048SToomas Soome 			rv = CMD_OK;
630eee59048SToomas Soome 	}
631eee59048SToomas Soome 	free(var);
632eee59048SToomas Soome 	return (rv);
633eee59048SToomas Soome }
634eee59048SToomas Soome 
635eee59048SToomas Soome static void
efi_print_var_attr(UINT32 attr)636eee59048SToomas Soome efi_print_var_attr(UINT32 attr)
637eee59048SToomas Soome {
638eee59048SToomas Soome 	bool comma = false;
639eee59048SToomas Soome 
640eee59048SToomas Soome 	if (attr & EFI_VARIABLE_NON_VOLATILE) {
641eee59048SToomas Soome 		printf("NV");
642eee59048SToomas Soome 		comma = true;
643eee59048SToomas Soome 	}
644eee59048SToomas Soome 	if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS) {
645eee59048SToomas Soome 		if (comma == true)
646eee59048SToomas Soome 			printf(",");
647eee59048SToomas Soome 		printf("BS");
648eee59048SToomas Soome 		comma = true;
649eee59048SToomas Soome 	}
650eee59048SToomas Soome 	if (attr & EFI_VARIABLE_RUNTIME_ACCESS) {
651eee59048SToomas Soome 		if (comma == true)
652eee59048SToomas Soome 			printf(",");
653eee59048SToomas Soome 		printf("RS");
654eee59048SToomas Soome 		comma = true;
655eee59048SToomas Soome 	}
656eee59048SToomas Soome 	if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
657eee59048SToomas Soome 		if (comma == true)
658eee59048SToomas Soome 			printf(",");
659eee59048SToomas Soome 		printf("HR");
660eee59048SToomas Soome 		comma = true;
661eee59048SToomas Soome 	}
662eee59048SToomas Soome 	if (attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
663eee59048SToomas Soome 		if (comma == true)
664eee59048SToomas Soome 			printf(",");
665eee59048SToomas Soome 		printf("AT");
666eee59048SToomas Soome 		comma = true;
667eee59048SToomas Soome 	}
668eee59048SToomas Soome }
669eee59048SToomas Soome 
670eee59048SToomas Soome static int
efi_print_var(CHAR16 * varnamearg,EFI_GUID * matchguid,int lflag)671eee59048SToomas Soome efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
672eee59048SToomas Soome {
673eee59048SToomas Soome 	UINTN		datasz;
674eee59048SToomas Soome 	EFI_STATUS	status;
675eee59048SToomas Soome 	UINT32		attr;
67614634113SToomas Soome 	char		*str;
67714634113SToomas Soome 	uint8_t		*data;
678eee59048SToomas Soome 	int		rv = CMD_OK;
679eee59048SToomas Soome 
680eee59048SToomas Soome 	str = NULL;
681eee59048SToomas Soome 	datasz = 0;
682911abd25SToomas Soome 	status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, NULL);
683eee59048SToomas Soome 	if (status != EFI_BUFFER_TOO_SMALL) {
684eee59048SToomas Soome 		printf("Can't get the variable: error %#lx\n",
685eee59048SToomas Soome 		    EFI_ERROR_CODE(status));
686eee59048SToomas Soome 		return (CMD_ERROR);
687eee59048SToomas Soome 	}
688eee59048SToomas Soome 	data = malloc(datasz);
689eee59048SToomas Soome 	if (data == NULL) {
690eee59048SToomas Soome 		printf("Out of memory\n");
691eee59048SToomas Soome 		return (CMD_ERROR);
692eee59048SToomas Soome 	}
693eee59048SToomas Soome 
694911abd25SToomas Soome 	status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, data);
695eee59048SToomas Soome 	if (status != EFI_SUCCESS) {
696eee59048SToomas Soome 		printf("Can't get the variable: error %#lx\n",
697eee59048SToomas Soome 		    EFI_ERROR_CODE(status));
698eee59048SToomas Soome 		free(data);
699eee59048SToomas Soome 		return (CMD_ERROR);
700eee59048SToomas Soome 	}
701eee59048SToomas Soome 
702eee59048SToomas Soome 	if (efi_guid_to_name(matchguid, &str) == false) {
703eee59048SToomas Soome 		rv = CMD_ERROR;
704eee59048SToomas Soome 		goto done;
705eee59048SToomas Soome 	}
706eee59048SToomas Soome 	printf("%s ", str);
707eee59048SToomas Soome 	efi_print_var_attr(attr);
708eee59048SToomas Soome 	printf(" %S", varnamearg);
709eee59048SToomas Soome 
710eee59048SToomas Soome 	if (lflag == 0) {
711eee59048SToomas Soome 		if (strcmp(str, "global") == 0)
712eee59048SToomas Soome 			rv = efi_print_global(varnamearg, data, datasz);
7138dff7262SToomas Soome 		else if (strcmp(str, "illumos") == 0)
7148dff7262SToomas Soome 			rv = efi_print_illumos(varnamearg, data, datasz);
715eee59048SToomas Soome 		else if (strcmp(str,
716eee59048SToomas Soome 		    EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0)
717eee59048SToomas Soome 			rv = efi_print_mem_type(varnamearg, data, datasz);
718eee59048SToomas Soome 		else if (strcmp(str,
719eee59048SToomas Soome 		    "47c7b227-c42a-11d2-8e57-00a0c969723b") == 0)
720eee59048SToomas Soome 			rv = efi_print_shell_str(varnamearg, data, datasz);
721eee59048SToomas Soome 		else if (strcmp(str, MTC_VARIABLE_NAME) == 0) {
722eee59048SToomas Soome 			printf(" = ");
723eee59048SToomas Soome 			printf("%u", *((uint32_t *)data));	/* UINT32 */
724eee59048SToomas Soome 			rv = CMD_OK;
725eee59048SToomas Soome 			if (pager_output("\n"))
726eee59048SToomas Soome 				rv = CMD_WARN;
727eee59048SToomas Soome 		} else
728eee59048SToomas Soome 			rv = efi_print_other_value(data, datasz);
729eee59048SToomas Soome 	} else if (pager_output("\n"))
730eee59048SToomas Soome 		rv =  CMD_WARN;
731eee59048SToomas Soome 
732eee59048SToomas Soome done:
733eee59048SToomas Soome 	free(str);
734eee59048SToomas Soome 	free(data);
735eee59048SToomas Soome 	return (rv);
736eee59048SToomas Soome }
737eee59048SToomas Soome 
738eee59048SToomas Soome static int
command_efi_show(int argc,char * argv[])739eee59048SToomas Soome command_efi_show(int argc, char *argv[])
740eee59048SToomas Soome {
741eee59048SToomas Soome 	/*
742eee59048SToomas Soome 	 * efi-show [-a]
743eee59048SToomas Soome 	 *	print all the env
744eee59048SToomas Soome 	 * efi-show -g UUID
745eee59048SToomas Soome 	 *	print all the env vars tagged with UUID
746eee59048SToomas Soome 	 * efi-show -v var
747eee59048SToomas Soome 	 *	search all the env vars and print the ones matching var
7485882b622SToomas Soome 	 * efi-show -g UUID -v var
7495882b622SToomas Soome 	 * efi-show UUID var
750eee59048SToomas Soome 	 *	print all the env vars that match UUID and var
751eee59048SToomas Soome 	 */
752eee59048SToomas Soome 	/* NB: We assume EFI_GUID is the same as uuid_t */
753eee59048SToomas Soome 	int		aflag = 0, gflag = 0, lflag = 0, vflag = 0;
754eee59048SToomas Soome 	int		ch, rv;
755eee59048SToomas Soome 	unsigned	i;
756eee59048SToomas Soome 	EFI_STATUS	status;
757eee59048SToomas Soome 	EFI_GUID	varguid = ZERO_GUID;
758eee59048SToomas Soome 	EFI_GUID	matchguid = ZERO_GUID;
759eee59048SToomas Soome 	CHAR16		*varname;
760eee59048SToomas Soome 	CHAR16		*newnm;
761eee59048SToomas Soome 	CHAR16		varnamearg[128];
762eee59048SToomas Soome 	UINTN		varalloc;
763eee59048SToomas Soome 	UINTN		varsz;
764eee59048SToomas Soome 
765eee59048SToomas Soome 	optind = 1;
766eee59048SToomas Soome 	optreset = 1;
767eee59048SToomas Soome 	opterr = 1;
768eee59048SToomas Soome 
769eee59048SToomas Soome 	while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
770eee59048SToomas Soome 		switch (ch) {
771eee59048SToomas Soome 		case 'a':
772eee59048SToomas Soome 			aflag = 1;
773eee59048SToomas Soome 			break;
774eee59048SToomas Soome 		case 'g':
775eee59048SToomas Soome 			gflag = 1;
776eee59048SToomas Soome 			if (efi_name_to_guid(optarg, &matchguid) == false) {
777eee59048SToomas Soome 				printf("uuid %s could not be parsed\n", optarg);
778eee59048SToomas Soome 				return (CMD_ERROR);
779eee59048SToomas Soome 			}
780eee59048SToomas Soome 			break;
781eee59048SToomas Soome 		case 'l':
782eee59048SToomas Soome 			lflag = 1;
783eee59048SToomas Soome 			break;
784eee59048SToomas Soome 		case 'v':
785eee59048SToomas Soome 			vflag = 1;
786eee59048SToomas Soome 			if (strlen(optarg) >= nitems(varnamearg)) {
7872b811402SToomas Soome 				printf("Variable %s is longer than %zu "
788eee59048SToomas Soome 				    "characters\n", optarg, nitems(varnamearg));
789eee59048SToomas Soome 				return (CMD_ERROR);
790eee59048SToomas Soome 			}
791eee59048SToomas Soome 			cpy8to16(optarg, varnamearg, nitems(varnamearg));
792eee59048SToomas Soome 			break;
793eee59048SToomas Soome 		default:
794eee59048SToomas Soome 			return (CMD_ERROR);
795eee59048SToomas Soome 		}
796eee59048SToomas Soome 	}
797eee59048SToomas Soome 
798eee59048SToomas Soome 	if (argc == 1)		/* default is -a */
799eee59048SToomas Soome 		aflag = 1;
800eee59048SToomas Soome 
801eee59048SToomas Soome 	if (aflag && (gflag || vflag)) {
802eee59048SToomas Soome 		printf("-a isn't compatible with -g or -v\n");
803eee59048SToomas Soome 		return (CMD_ERROR);
804eee59048SToomas Soome 	}
805eee59048SToomas Soome 
806eee59048SToomas Soome 	if (aflag && optind < argc) {
807eee59048SToomas Soome 		printf("-a doesn't take any args\n");
808eee59048SToomas Soome 		return (CMD_ERROR);
809eee59048SToomas Soome 	}
810eee59048SToomas Soome 
811eee59048SToomas Soome 	argc -= optind;
812eee59048SToomas Soome 	argv += optind;
813eee59048SToomas Soome 
814eee59048SToomas Soome 	pager_open();
815eee59048SToomas Soome 	if (vflag && gflag) {
816eee59048SToomas Soome 		rv = efi_print_var(varnamearg, &matchguid, lflag);
817eee59048SToomas Soome 		if (rv == CMD_WARN)
818eee59048SToomas Soome 			rv = CMD_OK;
819eee59048SToomas Soome 		pager_close();
820eee59048SToomas Soome 		return (rv);
821eee59048SToomas Soome 	}
822eee59048SToomas Soome 
823eee59048SToomas Soome 	if (argc == 2) {
824eee59048SToomas Soome 		optarg = argv[0];
825eee59048SToomas Soome 		if (strlen(optarg) >= nitems(varnamearg)) {
8262b811402SToomas Soome 			printf("Variable %s is longer than %zu characters\n",
827eee59048SToomas Soome 			    optarg, nitems(varnamearg));
828eee59048SToomas Soome 			pager_close();
829eee59048SToomas Soome 			return (CMD_ERROR);
830eee59048SToomas Soome 		}
831eee59048SToomas Soome 		for (i = 0; i < strlen(optarg); i++)
832eee59048SToomas Soome 			varnamearg[i] = optarg[i];
833eee59048SToomas Soome 		varnamearg[i] = 0;
834eee59048SToomas Soome 		optarg = argv[1];
835eee59048SToomas Soome 		if (efi_name_to_guid(optarg, &matchguid) == false) {
836eee59048SToomas Soome 			printf("uuid %s could not be parsed\n", optarg);
837eee59048SToomas Soome 			pager_close();
838eee59048SToomas Soome 			return (CMD_ERROR);
839eee59048SToomas Soome 		}
840eee59048SToomas Soome 		rv = efi_print_var(varnamearg, &matchguid, lflag);
841eee59048SToomas Soome 		if (rv == CMD_WARN)
842eee59048SToomas Soome 			rv = CMD_OK;
843eee59048SToomas Soome 		pager_close();
844eee59048SToomas Soome 		return (rv);
845eee59048SToomas Soome 	}
846eee59048SToomas Soome 
847eee59048SToomas Soome 	if (argc > 0) {
848eee59048SToomas Soome 		printf("Too many args: %d\n", argc);
849eee59048SToomas Soome 		pager_close();
850eee59048SToomas Soome 		return (CMD_ERROR);
851eee59048SToomas Soome 	}
852eee59048SToomas Soome 
853eee59048SToomas Soome 	/*
854eee59048SToomas Soome 	 * Initiate the search -- note the standard takes pain
855eee59048SToomas Soome 	 * to specify the initial call must be a poiner to a NULL
856eee59048SToomas Soome 	 * character.
857eee59048SToomas Soome 	 */
858eee59048SToomas Soome 	varalloc = 1024;
859eee59048SToomas Soome 	varname = malloc(varalloc);
860eee59048SToomas Soome 	if (varname == NULL) {
861eee59048SToomas Soome 		printf("Can't allocate memory to get variables\n");
862eee59048SToomas Soome 		pager_close();
863eee59048SToomas Soome 		return (CMD_ERROR);
864eee59048SToomas Soome 	}
865eee59048SToomas Soome 	varname[0] = 0;
866eee59048SToomas Soome 	while (1) {
867eee59048SToomas Soome 		varsz = varalloc;
868911abd25SToomas Soome 		status = RS->GetNextVariableName(&varsz, varname, &varguid);
869eee59048SToomas Soome 		if (status == EFI_BUFFER_TOO_SMALL) {
870eee59048SToomas Soome 			varalloc = varsz;
871eee59048SToomas Soome 			newnm = realloc(varname, varalloc);
872eee59048SToomas Soome 			if (newnm == NULL) {
873eee59048SToomas Soome 				printf("Can't allocate memory to get "
874eee59048SToomas Soome 				    "variables\n");
875eee59048SToomas Soome 				rv = CMD_ERROR;
876eee59048SToomas Soome 				break;
877eee59048SToomas Soome 			}
878eee59048SToomas Soome 			varname = newnm;
879eee59048SToomas Soome 			continue; /* Try again with bigger buffer */
880eee59048SToomas Soome 		}
881eee59048SToomas Soome 		if (status == EFI_NOT_FOUND) {
882eee59048SToomas Soome 			rv = CMD_OK;
883eee59048SToomas Soome 			break;
884eee59048SToomas Soome 		}
885eee59048SToomas Soome 		if (status != EFI_SUCCESS) {
886eee59048SToomas Soome 			rv = CMD_ERROR;
887eee59048SToomas Soome 			break;
888eee59048SToomas Soome 		}
889eee59048SToomas Soome 
890eee59048SToomas Soome 		if (aflag) {
891eee59048SToomas Soome 			rv = efi_print_var(varname, &varguid, lflag);
892eee59048SToomas Soome 			if (rv != CMD_OK) {
893eee59048SToomas Soome 				if (rv == CMD_WARN)
894