1ca987d46SWarner Losh /*
252467047SWarner Losh * Copyright (c) 2015 Netflix, Inc.
3ca987d46SWarner Losh *
4ca987d46SWarner Losh * Redistribution and use in source and binary forms, with or without
5ca987d46SWarner Losh * modification, are permitted provided that the following conditions
6ca987d46SWarner Losh * are met:
7ca987d46SWarner Losh * 1. Redistributions of source code must retain the above copyright
8ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer.
9ca987d46SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
10ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer in the
11ca987d46SWarner Losh * documentation and/or other materials provided with the distribution.
12ca987d46SWarner Losh *
13ca987d46SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14ca987d46SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15ca987d46SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16ca987d46SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17ca987d46SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18ca987d46SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19ca987d46SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20ca987d46SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21ca987d46SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22ca987d46SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23ca987d46SWarner Losh * SUCH DAMAGE.
24ca987d46SWarner Losh */
25ca987d46SWarner Losh
26ca987d46SWarner Losh #include <stand.h>
27ca987d46SWarner Losh #include <string.h>
28ca987d46SWarner Losh #include <efi.h>
2965641822SToomas Soome #include <efichar.h>
30ca987d46SWarner Losh #include <efilib.h>
3165641822SToomas Soome #include <efigpt.h> /* Partition GUIDS */
3265641822SToomas Soome #include <Guid/MemoryTypeInformation.h>
3365641822SToomas Soome #include <Guid/MtcVendor.h>
3465641822SToomas Soome #include <Guid/ZeroGuid.h>
3565641822SToomas Soome #include <Protocol/EdidActive.h>
3665641822SToomas Soome #include <Protocol/EdidDiscovered.h>
37ca987d46SWarner Losh #include <uuid.h>
38ca987d46SWarner Losh #include <stdbool.h>
3965641822SToomas Soome #include <sys/param.h>
40ca987d46SWarner Losh #include "bootstrap.h"
41ca987d46SWarner Losh
4265641822SToomas Soome /*
4365641822SToomas Soome * About ENABLE_UPDATES
4465641822SToomas Soome *
4565641822SToomas Soome * The UEFI variables are identified only by GUID and name, there is no
4665641822SToomas Soome * way to (auto)detect the type for the value, so we need to process the
4765641822SToomas Soome * variables case by case, as we do learn about them.
4865641822SToomas Soome *
4965641822SToomas Soome * While showing the variable name and the value is safe, we must not store
5065641822SToomas Soome * random values nor allow removing (random) variables.
5165641822SToomas Soome *
5265641822SToomas Soome * Since we do have stub code to set/unset the variables, I do want to keep
5365641822SToomas Soome * it to make the future development a bit easier, but the updates are disabled
5465641822SToomas Soome * by default till:
5565641822SToomas Soome * a) the validation and data translation to values is properly implemented
5665641822SToomas Soome * b) We have established which variables we do allow to be updated.
5765641822SToomas Soome * Therefore the set/unset code is included only for developers aid.
5865641822SToomas Soome */
5965641822SToomas Soome
6065641822SToomas Soome static struct efi_uuid_mapping {
6165641822SToomas Soome const char *efi_guid_name;
6265641822SToomas Soome EFI_GUID efi_guid;
6365641822SToomas Soome } efi_uuid_mapping[] = {
6465641822SToomas Soome { .efi_guid_name = "global", .efi_guid = EFI_GLOBAL_VARIABLE },
6565641822SToomas Soome { .efi_guid_name = "freebsd", .efi_guid = FREEBSD_BOOT_VAR_GUID },
6665641822SToomas Soome /* EFI Systab entry names. */
6765641822SToomas Soome { .efi_guid_name = "MPS Table", .efi_guid = MPS_TABLE_GUID },
6865641822SToomas Soome { .efi_guid_name = "ACPI Table", .efi_guid = ACPI_TABLE_GUID },
6965641822SToomas Soome { .efi_guid_name = "ACPI 2.0 Table", .efi_guid = ACPI_20_TABLE_GUID },
7065641822SToomas Soome { .efi_guid_name = "SMBIOS Table", .efi_guid = SMBIOS_TABLE_GUID },
7165641822SToomas Soome { .efi_guid_name = "SMBIOS3 Table", .efi_guid = SMBIOS3_TABLE_GUID },
7265641822SToomas Soome { .efi_guid_name = "DXE Table", .efi_guid = DXE_SERVICES_TABLE_GUID },
7365641822SToomas Soome { .efi_guid_name = "HOB List Table", .efi_guid = HOB_LIST_TABLE_GUID },
7465641822SToomas Soome { .efi_guid_name = EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
7565641822SToomas Soome .efi_guid = EFI_MEMORY_TYPE_INFORMATION_GUID },
7665641822SToomas Soome { .efi_guid_name = "Debug Image Info Table",
7765641822SToomas Soome .efi_guid = DEBUG_IMAGE_INFO_TABLE_GUID },
7865641822SToomas Soome { .efi_guid_name = "FDT Table", .efi_guid = FDT_TABLE_GUID },
7965641822SToomas Soome /*
8065641822SToomas Soome * Protocol names for debug purposes.
8165641822SToomas Soome * Can be removed along with lsefi command.
8265641822SToomas Soome */
8365641822SToomas Soome { .efi_guid_name = "device path", .efi_guid = DEVICE_PATH_PROTOCOL },
8465641822SToomas Soome { .efi_guid_name = "block io", .efi_guid = BLOCK_IO_PROTOCOL },
8565641822SToomas Soome { .efi_guid_name = "disk io", .efi_guid = DISK_IO_PROTOCOL },
8665641822SToomas Soome { .efi_guid_name = "disk info", .efi_guid =
8765641822SToomas Soome EFI_DISK_INFO_PROTOCOL_GUID },
8865641822SToomas Soome { .efi_guid_name = "simple fs",
8965641822SToomas Soome .efi_guid = SIMPLE_FILE_SYSTEM_PROTOCOL },
9065641822SToomas Soome { .efi_guid_name = "load file", .efi_guid = LOAD_FILE_PROTOCOL },
9165641822SToomas Soome { .efi_guid_name = "device io", .efi_guid = DEVICE_IO_PROTOCOL },
9265641822SToomas Soome { .efi_guid_name = "unicode collation",
9365641822SToomas Soome .efi_guid = UNICODE_COLLATION_PROTOCOL },
9465641822SToomas Soome { .efi_guid_name = "unicode collation2",
9565641822SToomas Soome .efi_guid = EFI_UNICODE_COLLATION2_PROTOCOL_GUID },
9665641822SToomas Soome { .efi_guid_name = "simple network",
9765641822SToomas Soome .efi_guid = EFI_SIMPLE_NETWORK_PROTOCOL },
9865641822SToomas Soome { .efi_guid_name = "simple text output",
9965641822SToomas Soome .efi_guid = SIMPLE_TEXT_OUTPUT_PROTOCOL },
10065641822SToomas Soome { .efi_guid_name = "simple text input",
10165641822SToomas Soome .efi_guid = SIMPLE_TEXT_INPUT_PROTOCOL },
10265641822SToomas Soome { .efi_guid_name = "simple text ex input",
10365641822SToomas Soome .efi_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID },
10465641822SToomas Soome { .efi_guid_name = "console control",
10565641822SToomas Soome .efi_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID },
10665641822SToomas Soome { .efi_guid_name = "stdin", .efi_guid = EFI_CONSOLE_IN_DEVICE_GUID },
10765641822SToomas Soome { .efi_guid_name = "stdout", .efi_guid = EFI_CONSOLE_OUT_DEVICE_GUID },
10865641822SToomas Soome { .efi_guid_name = "stderr",
10965641822SToomas Soome .efi_guid = EFI_STANDARD_ERROR_DEVICE_GUID },
11065641822SToomas Soome { .efi_guid_name = "GOP",
11165641822SToomas Soome .efi_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID },
11265641822SToomas Soome { .efi_guid_name = "UGA draw", .efi_guid = EFI_UGA_DRAW_PROTOCOL_GUID },
11365641822SToomas Soome { .efi_guid_name = "PXE base code",
11465641822SToomas Soome .efi_guid = EFI_PXE_BASE_CODE_PROTOCOL },
11565641822SToomas Soome { .efi_guid_name = "PXE base code callback",
11665641822SToomas Soome .efi_guid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL },
11765641822SToomas Soome { .efi_guid_name = "serial io", .efi_guid = SERIAL_IO_PROTOCOL },
11865641822SToomas Soome { .efi_guid_name = "loaded image", .efi_guid = LOADED_IMAGE_PROTOCOL },
11965641822SToomas Soome { .efi_guid_name = "loaded image device path",
12065641822SToomas Soome .efi_guid = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID },
12165641822SToomas Soome { .efi_guid_name = "ISA io", .efi_guid = EFI_ISA_IO_PROTOCOL_GUID },
12265641822SToomas Soome { .efi_guid_name = "IDE controller init",
12365641822SToomas Soome .efi_guid = EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID },
12465641822SToomas Soome { .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID },
12565641822SToomas Soome { .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID },
12665641822SToomas Soome { .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID },
12765641822SToomas Soome { .efi_guid_name = "PCI enumeration",
12865641822SToomas Soome .efi_guid = EFI_PCI_ENUMERATION_COMPLETE_GUID },
12965641822SToomas Soome { .efi_guid_name = "Driver diagnostics",
13065641822SToomas Soome .efi_guid = EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID },
13165641822SToomas Soome { .efi_guid_name = "Driver diagnostics2",
13265641822SToomas Soome .efi_guid = EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID },
13365641822SToomas Soome { .efi_guid_name = "simple pointer",
13465641822SToomas Soome .efi_guid = EFI_SIMPLE_POINTER_PROTOCOL_GUID },
13565641822SToomas Soome { .efi_guid_name = "absolute pointer",
13665641822SToomas Soome .efi_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID },
13765641822SToomas Soome { .efi_guid_name = "VLAN config",
13865641822SToomas Soome .efi_guid = EFI_VLAN_CONFIG_PROTOCOL_GUID },
13965641822SToomas Soome { .efi_guid_name = "ARP service binding",
14065641822SToomas Soome .efi_guid = EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID },
14165641822SToomas Soome { .efi_guid_name = "ARP", .efi_guid = EFI_ARP_PROTOCOL_GUID },
14265641822SToomas Soome { .efi_guid_name = "IPv4 service binding",
14365641822SToomas Soome .efi_guid = EFI_IP4_SERVICE_BINDING_PROTOCOL },
14465641822SToomas Soome { .efi_guid_name = "IPv4", .efi_guid = EFI_IP4_PROTOCOL },
14565641822SToomas Soome { .efi_guid_name = "IPv4 config",
14665641822SToomas Soome .efi_guid = EFI_IP4_CONFIG_PROTOCOL_GUID },
14765641822SToomas Soome { .efi_guid_name = "IPv6 service binding",
14865641822SToomas Soome .efi_guid = EFI_IP6_SERVICE_BINDING_PROTOCOL },
14965641822SToomas Soome { .efi_guid_name = "IPv6", .efi_guid = EFI_IP6_PROTOCOL },
15065641822SToomas Soome { .efi_guid_name = "IPv6 config",
15165641822SToomas Soome .efi_guid = EFI_IP6_CONFIG_PROTOCOL_GUID },
15265641822SToomas Soome { .efi_guid_name = "UDPv4", .efi_guid = EFI_UDP4_PROTOCOL },
15365641822SToomas Soome { .efi_guid_name = "UDPv4 service binding",
15465641822SToomas Soome .efi_guid = EFI_UDP4_SERVICE_BINDING_PROTOCOL },
15565641822SToomas Soome { .efi_guid_name = "UDPv6", .efi_guid = EFI_UDP6_PROTOCOL },
15665641822SToomas Soome { .efi_guid_name = "UDPv6 service binding",
15765641822SToomas Soome .efi_guid = EFI_UDP6_SERVICE_BINDING_PROTOCOL },
15865641822SToomas Soome { .efi_guid_name = "TCPv4", .efi_guid = EFI_TCP4_PROTOCOL },
15965641822SToomas Soome { .efi_guid_name = "TCPv4 service binding",
16065641822SToomas Soome .efi_guid = EFI_TCP4_SERVICE_BINDING_PROTOCOL },
16165641822SToomas Soome { .efi_guid_name = "TCPv6", .efi_guid = EFI_TCP6_PROTOCOL },
16265641822SToomas Soome { .efi_guid_name = "TCPv6 service binding",
16365641822SToomas Soome .efi_guid = EFI_TCP6_SERVICE_BINDING_PROTOCOL },
16465641822SToomas Soome { .efi_guid_name = "EFI System partition",
16565641822SToomas Soome .efi_guid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID },
16665641822SToomas Soome { .efi_guid_name = "MBR legacy",
16765641822SToomas Soome .efi_guid = EFI_PART_TYPE_LEGACY_MBR_GUID },
16865641822SToomas Soome { .efi_guid_name = "device tree", .efi_guid = EFI_DEVICE_TREE_GUID },
16965641822SToomas Soome { .efi_guid_name = "USB io", .efi_guid = EFI_USB_IO_PROTOCOL_GUID },
17065641822SToomas Soome { .efi_guid_name = "USB2 HC", .efi_guid = EFI_USB2_HC_PROTOCOL_GUID },
17165641822SToomas Soome { .efi_guid_name = "component name",
17265641822SToomas Soome .efi_guid = EFI_COMPONENT_NAME_PROTOCOL_GUID },
17365641822SToomas Soome { .efi_guid_name = "component name2",
17465641822SToomas Soome .efi_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID },
17565641822SToomas Soome { .efi_guid_name = "driver binding",
17665641822SToomas Soome .efi_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID },
17765641822SToomas Soome { .efi_guid_name = "driver configuration",
17865641822SToomas Soome .efi_guid = EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID },
17965641822SToomas Soome { .efi_guid_name = "driver configuration2",
18065641822SToomas Soome .efi_guid = EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID },
18165641822SToomas Soome { .efi_guid_name = "decompress",
18265641822SToomas Soome .efi_guid = EFI_DECOMPRESS_PROTOCOL_GUID },
18365641822SToomas Soome { .efi_guid_name = "ebc interpreter",
18465641822SToomas Soome .efi_guid = EFI_EBC_INTERPRETER_PROTOCOL_GUID },
18565641822SToomas Soome { .efi_guid_name = "network interface identifier",
18665641822SToomas Soome .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL },
18765641822SToomas Soome { .efi_guid_name = "network interface identifier_31",
18865641822SToomas Soome .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31 },
18965641822SToomas Soome { .efi_guid_name = "managed network service binding",
19065641822SToomas Soome .efi_guid = EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID },
19165641822SToomas Soome { .efi_guid_name = "managed network",
19265641822SToomas Soome .efi_guid = EFI_MANAGED_NETWORK_PROTOCOL_GUID },
19365641822SToomas Soome { .efi_guid_name = "form browser",
19465641822SToomas Soome .efi_guid = EFI_FORM_BROWSER2_PROTOCOL_GUID },
19565641822SToomas Soome { .efi_guid_name = "HII config routing",
19665641822SToomas Soome .efi_guid = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID },
19765641822SToomas Soome { .efi_guid_name = "HII database",
19865641822SToomas Soome .efi_guid = EFI_HII_DATABASE_PROTOCOL_GUID },
19965641822SToomas Soome { .efi_guid_name = "HII string",
20065641822SToomas Soome .efi_guid = EFI_HII_STRING_PROTOCOL_GUID },
20165641822SToomas Soome { .efi_guid_name = "HII image",
20265641822SToomas Soome .efi_guid = EFI_HII_IMAGE_PROTOCOL_GUID },
20365641822SToomas Soome { .efi_guid_name = "HII font", .efi_guid = EFI_HII_FONT_PROTOCOL_GUID },
20465641822SToomas Soome { .efi_guid_name = "HII config",
20565641822SToomas Soome .efi_guid = EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID },
20665641822SToomas Soome { .efi_guid_name = "MTFTP4 service binding",
20765641822SToomas Soome .efi_guid = EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID },
20865641822SToomas Soome { .efi_guid_name = "MTFTP4", .efi_guid = EFI_MTFTP4_PROTOCOL_GUID },
20965641822SToomas Soome { .efi_guid_name = "MTFTP6 service binding",
21065641822SToomas Soome .efi_guid = EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID },
21165641822SToomas Soome { .efi_guid_name = "MTFTP6", .efi_guid = EFI_MTFTP6_PROTOCOL_GUID },
21265641822SToomas Soome { .efi_guid_name = "DHCP4 service binding",
21365641822SToomas Soome .efi_guid = EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID },
21465641822SToomas Soome { .efi_guid_name = "DHCP4", .efi_guid = EFI_DHCP4_PROTOCOL_GUID },
21565641822SToomas Soome { .efi_guid_name = "DHCP6 service binding",
21665641822SToomas Soome .efi_guid = EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID },
21765641822SToomas Soome { .efi_guid_name = "DHCP6", .efi_guid = EFI_DHCP6_PROTOCOL_GUID },
21865641822SToomas Soome { .efi_guid_name = "SCSI io", .efi_guid = EFI_SCSI_IO_PROTOCOL_GUID },
21965641822SToomas Soome { .efi_guid_name = "SCSI pass thru",
22065641822SToomas Soome .efi_guid = EFI_SCSI_PASS_THRU_PROTOCOL_GUID },
22165641822SToomas Soome { .efi_guid_name = "SCSI pass thru ext",
22265641822SToomas Soome .efi_guid = EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID },
22365641822SToomas Soome { .efi_guid_name = "Capsule arch",
22465641822SToomas Soome .efi_guid = EFI_CAPSULE_ARCH_PROTOCOL_GUID },
22565641822SToomas Soome { .efi_guid_name = "monotonic counter arch",
22665641822SToomas Soome .efi_guid = EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID },
22765641822SToomas Soome { .efi_guid_name = "realtime clock arch",
22865641822SToomas Soome .efi_guid = EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID },
22965641822SToomas Soome { .efi_guid_name = "variable arch",
23065641822SToomas Soome .efi_guid = EFI_VARIABLE_ARCH_PROTOCOL_GUID },
23165641822SToomas Soome { .efi_guid_name = "variable write arch",
23265641822SToomas Soome .efi_guid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID },
23365641822SToomas Soome { .efi_guid_name = "watchdog timer arch",
23465641822SToomas Soome .efi_guid = EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID },
23565641822SToomas Soome { .efi_guid_name = "ACPI support",
23665641822SToomas Soome .efi_guid = EFI_ACPI_SUPPORT_PROTOCOL_GUID },
23765641822SToomas Soome { .efi_guid_name = "BDS arch", .efi_guid = EFI_BDS_ARCH_PROTOCOL_GUID },
23865641822SToomas Soome { .efi_guid_name = "metronome arch",
23965641822SToomas Soome .efi_guid = EFI_METRONOME_ARCH_PROTOCOL_GUID },
24065641822SToomas Soome { .efi_guid_name = "timer arch",
24165641822SToomas Soome .efi_guid = EFI_TIMER_ARCH_PROTOCOL_GUID },
24265641822SToomas Soome { .efi_guid_name = "DPC", .efi_guid = EFI_DPC_PROTOCOL_GUID },
24365641822SToomas Soome { .efi_guid_name = "print2", .efi_guid = EFI_PRINT2_PROTOCOL_GUID },
24465641822SToomas Soome { .efi_guid_name = "device path to text",
24565641822SToomas Soome .efi_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID },
24665641822SToomas Soome { .efi_guid_name = "reset arch",
24765641822SToomas Soome .efi_guid = EFI_RESET_ARCH_PROTOCOL_GUID },
24865641822SToomas Soome { .efi_guid_name = "CPU arch", .efi_guid = EFI_CPU_ARCH_PROTOCOL_GUID },
24965641822SToomas Soome { .efi_guid_name = "CPU IO2", .efi_guid = EFI_CPU_IO2_PROTOCOL_GUID },
25065641822SToomas Soome { .efi_guid_name = "Legacy 8259",
25165641822SToomas Soome .efi_guid = EFI_LEGACY_8259_PROTOCOL_GUID },
25265641822SToomas Soome { .efi_guid_name = "Security arch",
25365641822SToomas Soome .efi_guid = EFI_SECURITY_ARCH_PROTOCOL_GUID },
25465641822SToomas Soome { .efi_guid_name = "Security2 arch",
25565641822SToomas Soome .efi_guid = EFI_SECURITY2_ARCH_PROTOCOL_GUID },
25665641822SToomas Soome { .efi_guid_name = "Runtime arch",
25765641822SToomas Soome .efi_guid = EFI_RUNTIME_ARCH_PROTOCOL_GUID },
25865641822SToomas Soome { .efi_guid_name = "status code runtime",
25965641822SToomas Soome .efi_guid = EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID },
26065641822SToomas Soome { .efi_guid_name = "data hub", .efi_guid = EFI_DATA_HUB_PROTOCOL_GUID },
26165641822SToomas Soome { .efi_guid_name = "PCD", .efi_guid = PCD_PROTOCOL_GUID },
26265641822SToomas Soome { .efi_guid_name = "EFI PCD", .efi_guid = EFI_PCD_PROTOCOL_GUID },
26365641822SToomas Soome { .efi_guid_name = "firmware volume block",
26465641822SToomas Soome .efi_guid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID },
26565641822SToomas Soome { .efi_guid_name = "firmware volume2",
26665641822SToomas Soome .efi_guid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID },
26765641822SToomas Soome { .efi_guid_name = "firmware volume dispatch",
26865641822SToomas Soome .efi_guid = EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID },
26965641822SToomas Soome { .efi_guid_name = "lzma compress", .efi_guid = LZMA_COMPRESS_GUID },
27065641822SToomas Soome { .efi_guid_name = "MP services",
27165641822SToomas Soome .efi_guid = EFI_MP_SERVICES_PROTOCOL_GUID },
27265641822SToomas Soome { .efi_guid_name = MTC_VARIABLE_NAME, .efi_guid = MTC_VENDOR_GUID },
27365641822SToomas Soome { .efi_guid_name = "RTC", .efi_guid = { 0x378D7B65, 0x8DA9, 0x4773,
27465641822SToomas Soome { 0xB6, 0xE4, 0xA4, 0x78, 0x26, 0xA8, 0x33, 0xE1} } },
27565641822SToomas Soome { .efi_guid_name = "Active EDID",
27665641822SToomas Soome .efi_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID },
27765641822SToomas Soome { .efi_guid_name = "Discovered EDID",
27865641822SToomas Soome .efi_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID }
27965641822SToomas Soome };
28065641822SToomas Soome
28165641822SToomas Soome bool
efi_guid_to_str(const EFI_GUID * guid,char ** sp)28265641822SToomas Soome efi_guid_to_str(const EFI_GUID *guid, char **sp)
28365641822SToomas Soome {
28465641822SToomas Soome uint32_t status;
28565641822SToomas Soome
28665641822SToomas Soome uuid_to_string((const uuid_t *)guid, sp, &status);
28765641822SToomas Soome return (status == uuid_s_ok ? true : false);
28865641822SToomas Soome }
28965641822SToomas Soome
29065641822SToomas Soome bool
efi_str_to_guid(const char * s,EFI_GUID * guid)29165641822SToomas Soome efi_str_to_guid(const char *s, EFI_GUID *guid)
29265641822SToomas Soome {
29365641822SToomas Soome uint32_t status;
29465641822SToomas Soome
29565641822SToomas Soome uuid_from_string(s, (uuid_t *)guid, &status);
29665641822SToomas Soome return (status == uuid_s_ok ? true : false);
29765641822SToomas Soome }
29865641822SToomas Soome
29965641822SToomas Soome bool
efi_name_to_guid(const char * name,EFI_GUID * guid)30065641822SToomas Soome efi_name_to_guid(const char *name, EFI_GUID *guid)
30165641822SToomas Soome {
30265641822SToomas Soome uint32_t i;
30365641822SToomas Soome
30465641822SToomas Soome for (i = 0; i < nitems(efi_uuid_mapping); i++) {
30565641822SToomas Soome if (strcasecmp(name, efi_uuid_mapping[i].efi_guid_name) == 0) {
30665641822SToomas Soome *guid = efi_uuid_mapping[i].efi_guid;
30765641822SToomas Soome return (true);
30865641822SToomas Soome }
30965641822SToomas Soome }
31065641822SToomas Soome return (efi_str_to_guid(name, guid));
31165641822SToomas Soome }
31265641822SToomas Soome
31365641822SToomas Soome bool
efi_guid_to_name(EFI_GUID * guid,char ** name)31465641822SToomas Soome efi_guid_to_name(EFI_GUID *guid, char **name)
31565641822SToomas Soome {
31665641822SToomas Soome uint32_t i;
31765641822SToomas Soome int rv;
31865641822SToomas Soome
31965641822SToomas Soome for (i = 0; i < nitems(efi_uuid_mapping); i++) {
32065641822SToomas Soome rv = uuid_equal((uuid_t *)guid,
32165641822SToomas Soome (uuid_t *)&efi_uuid_mapping[i].efi_guid, NULL);
32265641822SToomas Soome if (rv != 0) {
32365641822SToomas Soome *name = strdup(efi_uuid_mapping[i].efi_guid_name);
32465641822SToomas Soome if (*name == NULL)
32565641822SToomas Soome return (false);
32665641822SToomas Soome return (true);
32765641822SToomas Soome }
32865641822SToomas Soome }
32965641822SToomas Soome return (efi_guid_to_str(guid, name));
33065641822SToomas Soome }
33165641822SToomas Soome
332ca987d46SWarner Losh void
efi_init_environment(void)333ca987d46SWarner Losh efi_init_environment(void)
334ca987d46SWarner Losh {
335ca987d46SWarner Losh char var[128];
336ca987d46SWarner Losh
337ca987d46SWarner Losh snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
338ca987d46SWarner Losh ST->Hdr.Revision & 0xffff);
339ca987d46SWarner Losh env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
340ca987d46SWarner Losh }
341ca987d46SWarner Losh
342ca987d46SWarner Losh COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
343ca987d46SWarner Losh
34465641822SToomas Soome static int
efi_print_other_value(uint8_t * data,UINTN datasz)34565641822SToomas Soome efi_print_other_value(uint8_t *data, UINTN datasz)
34665641822SToomas Soome {
34765641822SToomas Soome UINTN i;
34865641822SToomas Soome bool is_ascii = true;
34965641822SToomas Soome
35065641822SToomas Soome printf(" = ");
35165641822SToomas Soome for (i = 0; i < datasz - 1; i++) {
35265641822SToomas Soome /*
35365641822SToomas Soome * Quick hack to see if this ascii-ish string is printable
35465641822SToomas Soome * range plus tab, cr and lf.
35565641822SToomas Soome */
35665641822SToomas Soome if ((data[i] < 32 || data[i] > 126)
35765641822SToomas Soome && data[i] != 9 && data[i] != 10 && data[i] != 13) {
35865641822SToomas Soome is_ascii = false;
35965641822SToomas Soome break;
36065641822SToomas Soome }
36165641822SToomas Soome }
36265641822SToomas Soome if (data[datasz - 1] != '\0')
36365641822SToomas Soome is_ascii = false;
36465641822SToomas Soome if (is_ascii == true) {
36565641822SToomas Soome printf("%s", data);
36665641822SToomas Soome if (pager_output("\n"))
36765641822SToomas Soome return (CMD_WARN);
36865641822SToomas Soome } else {
36965641822SToomas Soome if (pager_output("\n"))
37065641822SToomas Soome return (CMD_WARN);
37165641822SToomas Soome /*
37265641822SToomas Soome * Dump hex bytes grouped by 4.
37365641822SToomas Soome */
37465641822SToomas Soome for (i = 0; i < datasz; i++) {
37565641822SToomas Soome printf("%02x ", data[i]);
37665641822SToomas Soome if ((i + 1) % 4 == 0)
37765641822SToomas Soome printf(" ");
37865641822SToomas Soome if ((i + 1) % 20 == 0) {
37965641822SToomas Soome if (pager_output("\n"))
38065641822SToomas Soome return (CMD_WARN);
38165641822SToomas Soome }
38265641822SToomas Soome }
38365641822SToomas Soome if (pager_output("\n"))
38465641822SToomas Soome return (CMD_WARN);
38565641822SToomas Soome }
38665641822SToomas Soome
38765641822SToomas Soome return (CMD_OK);
38865641822SToomas Soome }
38965641822SToomas Soome
39065641822SToomas Soome /* This appears to be some sort of UEFI shell alias table. */
39165641822SToomas Soome static int
efi_print_shell_str(const CHAR16 * varnamearg __unused,uint8_t * data,UINTN datasz __unused)39265641822SToomas Soome efi_print_shell_str(const CHAR16 *varnamearg __unused, uint8_t *data,
39365641822SToomas Soome UINTN datasz __unused)
39465641822SToomas Soome {
39565641822SToomas Soome printf(" = %S", (CHAR16 *)data);
39665641822SToomas Soome if (pager_output("\n"))
39765641822SToomas Soome return (CMD_WARN);
39865641822SToomas Soome return (CMD_OK);
39965641822SToomas Soome }
40065641822SToomas Soome
40134ada209SToomas Soome const char *
efi_memory_type(EFI_MEMORY_TYPE type)40234ada209SToomas Soome efi_memory_type(EFI_MEMORY_TYPE type)
40334ada209SToomas Soome {
40434ada209SToomas Soome const char *types[] = {
40534ada209SToomas Soome "Reserved",
40634ada209SToomas Soome "LoaderCode",
40734ada209SToomas Soome "LoaderData",
40834ada209SToomas Soome "BootServicesCode",
40934ada209SToomas Soome "BootServicesData",
41034ada209SToomas Soome "RuntimeServicesCode",
41134ada209SToomas Soome "RuntimeServicesData",
41234ada209SToomas Soome "ConventionalMemory",
41334ada209SToomas Soome "UnusableMemory",
41434ada209SToomas Soome "ACPIReclaimMemory",
41534ada209SToomas Soome "ACPIMemoryNVS",
41634ada209SToomas Soome "MemoryMappedIO",
41734ada209SToomas Soome "MemoryMappedIOPortSpace",
41834ada209SToomas Soome "PalCode",
41934ada209SToomas Soome "PersistentMemory"
42034ada209SToomas Soome };
42134ada209SToomas Soome
42234ada209SToomas Soome switch (type) {
42334ada209SToomas Soome case EfiReservedMemoryType:
42434ada209SToomas Soome case EfiLoaderCode:
42534ada209SToomas Soome case EfiLoaderData:
42634ada209SToomas Soome case EfiBootServicesCode:
42734ada209SToomas Soome case EfiBootServicesData:
42834ada209SToomas Soome case EfiRuntimeServicesCode:
42934ada209SToomas Soome case EfiRuntimeServicesData:
43034ada209SToomas Soome case EfiConventionalMemory:
43134ada209SToomas Soome case EfiUnusableMemory:
43234ada209SToomas Soome case EfiACPIReclaimMemory:
43334ada209SToomas Soome case EfiACPIMemoryNVS:
43434ada209SToomas Soome case EfiMemoryMappedIO:
43534ada209SToomas Soome case EfiMemoryMappedIOPortSpace:
43634ada209SToomas Soome case EfiPalCode:
43734ada209SToomas Soome case EfiPersistentMemory:
43834ada209SToomas Soome return (types[type]);
43934ada209SToomas Soome default:
44034ada209SToomas Soome return ("Unknown");
44134ada209SToomas Soome }
44234ada209SToomas Soome }
44334ada209SToomas Soome
44465641822SToomas Soome /* Print memory type table. */
44565641822SToomas Soome static int
efi_print_mem_type(const CHAR16 * varnamearg __unused,uint8_t * data,UINTN datasz)44665641822SToomas Soome efi_print_mem_type(const CHAR16 *varnamearg __unused, uint8_t *data,
44765641822SToomas Soome UINTN datasz)
44865641822SToomas Soome {
44965641822SToomas Soome int i, n;
45065641822SToomas Soome EFI_MEMORY_TYPE_INFORMATION *ti;
45165641822SToomas Soome
45265641822SToomas Soome ti = (EFI_MEMORY_TYPE_INFORMATION *)data;
45365641822SToomas Soome if (pager_output(" = \n"))
45465641822SToomas Soome return (CMD_WARN);
45565641822SToomas Soome
45665641822SToomas Soome n = datasz / sizeof (EFI_MEMORY_TYPE_INFORMATION);
45765641822SToomas Soome for (i = 0; i < n && ti[i].NumberOfPages != 0; i++) {
45865641822SToomas Soome printf("\t%23s pages: %u", efi_memory_type(ti[i].Type),
45965641822SToomas Soome ti[i].NumberOfPages);
46065641822SToomas Soome if (pager_output("\n"))
46165641822SToomas Soome return (CMD_WARN);
46265641822SToomas Soome }
46365641822SToomas Soome
46465641822SToomas Soome return (CMD_OK);
46565641822SToomas Soome }
46665641822SToomas Soome
46765641822SToomas Soome /*
46865641822SToomas Soome * Print FreeBSD variables.
46965641822SToomas Soome * We have LoaderPath and LoaderDev as CHAR16 strings.
47065641822SToomas Soome */
47165641822SToomas Soome static int
efi_print_freebsd(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz __unused)47265641822SToomas Soome efi_print_freebsd(const CHAR16 *varnamearg, uint8_t *data,
47365641822SToomas Soome UINTN datasz __unused)
47465641822SToomas Soome {
47565641822SToomas Soome int rv = -1;
47665641822SToomas Soome char *var = NULL;
47765641822SToomas Soome
47865641822SToomas Soome if (ucs2_to_utf8(varnamearg, &var) != 0)
47965641822SToomas Soome return (CMD_ERROR);
48065641822SToomas Soome
48165641822SToomas Soome if (strcmp("LoaderPath", var) == 0 ||
48265641822SToomas Soome strcmp("LoaderDev", var) == 0) {
48365641822SToomas Soome printf(" = ");
48465641822SToomas Soome printf("%S", (CHAR16 *)data);
48565641822SToomas Soome
48665641822SToomas Soome if (pager_output("\n"))
48765641822SToomas Soome rv = CMD_WARN;
48865641822SToomas Soome else
48965641822SToomas Soome rv = CMD_OK;
49065641822SToomas Soome }
49165641822SToomas Soome
49265641822SToomas Soome free(var);
49365641822SToomas Soome return (rv);
49465641822SToomas Soome }
49565641822SToomas Soome
49665641822SToomas Soome /* Print global variables. */
49765641822SToomas Soome static int
efi_print_global(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz)49865641822SToomas Soome efi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
49965641822SToomas Soome {
50065641822SToomas Soome int rv = -1;
50165641822SToomas Soome char *var = NULL;
50265641822SToomas Soome
50365641822SToomas Soome if (ucs2_to_utf8(varnamearg, &var) != 0)
50465641822SToomas Soome return (CMD_ERROR);
50565641822SToomas Soome
50665641822SToomas Soome if (strcmp("AuditMode", var) == 0) {
50765641822SToomas Soome printf(" = ");
50865641822SToomas Soome printf("0x%x", *data); /* 8-bit int */
50965641822SToomas Soome goto done;
51065641822SToomas Soome }
51165641822SToomas Soome
51265641822SToomas Soome if (strcmp("BootOptionSupport", var) == 0) {
51365641822SToomas Soome printf(" = ");
51465641822SToomas Soome printf("0x%x", *((uint32_t *)data)); /* UINT32 */
51565641822SToomas Soome goto done;
51665641822SToomas Soome }
51765641822SToomas Soome
51865641822SToomas Soome if (strcmp("BootCurrent", var) == 0 ||
51965641822SToomas Soome strcmp("BootNext", var) == 0 ||
52065641822SToomas Soome strcmp("Timeout", var) == 0) {
52165641822SToomas Soome printf(" = ");
52265641822SToomas Soome printf("%u", *((uint16_t *)data)); /* UINT16 */
52365641822SToomas Soome goto done;
52465641822SToomas Soome }
52565641822SToomas Soome
52665641822SToomas Soome if (strcmp("BootOrder", var) == 0 ||
52765641822SToomas Soome strcmp("DriverOrder", var) == 0) {
52865641822SToomas Soome UINTN i;
52965641822SToomas Soome UINT16 *u16 = (UINT16 *)data;
53065641822SToomas Soome
53165641822SToomas Soome printf(" =");
53265641822SToomas Soome for (i = 0; i < datasz / sizeof (UINT16); i++)
53365641822SToomas Soome printf(" %u", u16[i]);
53465641822SToomas Soome goto done;
53565641822SToomas Soome }
53665641822SToomas Soome if (strncmp("Boot", var, 4) == 0 ||
537*39ae24e3SAlfonso Gregory strncmp("Driver", var, 6) == 0 ||
53865641822SToomas Soome strncmp("SysPrep", var, 7) == 0 ||
53965641822SToomas Soome strncmp("OsRecovery", var, 10) == 0) {
54065641822SToomas Soome UINT16 filepathlistlen;
54165641822SToomas Soome CHAR16 *text;
54265641822SToomas Soome int desclen;
54365641822SToomas Soome EFI_DEVICE_PATH *dp;
54465641822SToomas Soome
54565641822SToomas Soome data += sizeof(UINT32);
54665641822SToomas Soome filepathlistlen = *(uint16_t *)data;
54765641822SToomas Soome data += sizeof (UINT16);
54865641822SToomas Soome text = (CHAR16 *)data;
54965641822SToomas Soome
55065641822SToomas Soome for (desclen = 0; text[desclen] != 0; desclen++)
55165641822SToomas Soome ;
55265641822SToomas Soome if (desclen != 0) {
55365641822SToomas Soome /* Add terminating zero and we have CHAR16. */
55465641822SToomas Soome desclen = (desclen + 1) * 2;
55565641822SToomas Soome }
55665641822SToomas Soome
55765641822SToomas Soome printf(" = ");
55865641822SToomas Soome printf("%S", text);
55965641822SToomas Soome if (filepathlistlen != 0) {
56065641822SToomas Soome /* Output pathname from new line. */
56165641822SToomas Soome if (pager_output("\n")) {
56265641822SToomas Soome rv = CMD_WARN;
56365641822SToomas Soome goto done;
56465641822SToomas Soome }
56565641822SToomas Soome dp = malloc(filepathlistlen);
56665641822SToomas Soome if (dp == NULL)
56765641822SToomas Soome goto done;
56865641822SToomas Soome
56965641822SToomas Soome memcpy(dp, data + desclen, filepathlistlen);
57065641822SToomas Soome text = efi_devpath_name(dp);
57165641822SToomas Soome if (text != NULL) {
57265641822SToomas Soome printf("\t%S", text);
57365641822SToomas Soome efi_free_devpath_name(text);
57465641822SToomas Soome }
57565641822SToomas Soome free(dp);
57665641822SToomas Soome }
57765641822SToomas Soome goto done;
57865641822SToomas Soome }
57965641822SToomas Soome
58065641822SToomas Soome if (strcmp("ConIn", var) == 0 ||
58165641822SToomas Soome strcmp("ConInDev", var) == 0 ||
58265641822SToomas Soome strcmp("ConOut", var) == 0 ||
58365641822SToomas Soome strcmp("ConOutDev", var) == 0 ||
58465641822SToomas Soome strcmp("ErrOut", var) == 0 ||
58565641822SToomas Soome strcmp("ErrOutDev", var) == 0) {
58665641822SToomas Soome CHAR16 *text;
58765641822SToomas Soome
58865641822SToomas Soome printf(" = ");
58965641822SToomas Soome text = efi_devpath_name((EFI_DEVICE_PATH *)data);
59065641822SToomas Soome if (text != NULL) {
59165641822SToomas Soome printf("%S", text);
59265641822SToomas Soome efi_free_devpath_name(text);
59365641822SToomas Soome }
59465641822SToomas Soome goto done;
59565641822SToomas Soome }
59665641822SToomas Soome
59765641822SToomas Soome if (strcmp("PlatformLang", var) == 0 ||
59865641822SToomas Soome strcmp("PlatformLangCodes", var) == 0 ||
59965641822SToomas Soome strcmp("LangCodes", var) == 0 ||
60065641822SToomas Soome strcmp("Lang", var) == 0) {
60165641822SToomas Soome printf(" = ");
60265641822SToomas Soome printf("%s", data); /* ASCII string */
60365641822SToomas Soome goto done;
60465641822SToomas Soome }
60565641822SToomas Soome
60665641822SToomas Soome /*
60765641822SToomas Soome * Feature bitmap from firmware to OS.
60865641822SToomas Soome * Older UEFI provides UINT32, newer UINT64.
60965641822SToomas Soome */
61065641822SToomas Soome if (strcmp("OsIndicationsSupported", var) == 0) {
61165641822SToomas Soome printf(" = ");
61265641822SToomas Soome if (datasz == 4)
61365641822SToomas Soome printf("0x%x", *((uint32_t *)data));
61465641822SToomas Soome else
61565641822SToomas Soome printf("0x%jx", *((uint64_t *)data));
61665641822SToomas Soome goto done;
61765641822SToomas Soome }
61865641822SToomas Soome
61965641822SToomas Soome /* Fallback for anything else. */
62065641822SToomas Soome rv = efi_print_other_value(data, datasz);
62165641822SToomas Soome done:
62265641822SToomas Soome if (rv == -1) {
62365641822SToomas Soome if (pager_output("\n"))
62465641822SToomas Soome rv = CMD_WARN;
62565641822SToomas Soome else
62665641822SToomas Soome rv = CMD_OK;
62765641822SToomas Soome }
62865641822SToomas Soome free(var);
62965641822SToomas Soome return (rv);
63065641822SToomas Soome }
63165641822SToomas Soome
63265641822SToomas Soome static void
efi_print_var_attr(UINT32 attr)63365641822SToomas Soome efi_print_var_attr(UINT32 attr)
63465641822SToomas Soome {
63565641822SToomas Soome bool comma = false;
63665641822SToomas Soome
63765641822SToomas Soome if (attr & EFI_VARIABLE_NON_VOLATILE) {
63865641822SToomas Soome printf("NV");
63965641822SToomas Soome comma = true;
64065641822SToomas Soome }
64165641822SToomas Soome if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS) {
64265641822SToomas Soome if (comma == true)
64365641822SToomas Soome printf(",");
64465641822SToomas Soome printf("BS");
64565641822SToomas Soome comma = true;
64665641822SToomas Soome }
64765641822SToomas Soome if (attr & EFI_VARIABLE_RUNTIME_ACCESS) {
64865641822SToomas Soome if (comma == true)
64965641822SToomas Soome printf(",");
65065641822SToomas Soome printf("RS");
65165641822SToomas Soome comma = true;
65265641822SToomas Soome }
65365641822SToomas Soome if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
65465641822SToomas Soome if (comma == true)
65565641822SToomas Soome printf(",");
65665641822SToomas Soome printf("HR");
65765641822SToomas Soome comma = true;
65865641822SToomas Soome }
65965641822SToomas Soome if (attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
66065641822SToomas Soome if (comma == true)
66165641822SToomas Soome printf(",");
66265641822SToomas Soome printf("AT");
66365641822SToomas Soome comma = true;
66465641822SToomas Soome }
66565641822SToomas Soome }
66665641822SToomas Soome
667ca987d46SWarner Losh static int
efi_print_var(CHAR16 * varnamearg,EFI_GUID * matchguid,int lflag)668ca987d46SWarner Losh efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
669ca987d46SWarner Losh {
67065641822SToomas Soome UINTN datasz;
671ca987d46SWarner Losh EFI_STATUS status;
672ca987d46SWarner Losh UINT32 attr;
673ca987d46SWarner Losh char *str;
67465641822SToomas Soome uint8_t *data;
67565641822SToomas Soome int rv = CMD_OK;
676ca987d46SWarner Losh
67765641822SToomas Soome str = NULL;
678ca987d46SWarner Losh datasz = 0;
67965641822SToomas Soome status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, NULL);
680ca987d46SWarner Losh if (status != EFI_BUFFER_TOO_SMALL) {
681ca987d46SWarner Losh printf("Can't get the variable: error %#lx\n",
682ca987d46SWarner Losh EFI_ERROR_CODE(status));
683ca987d46SWarner Losh return (CMD_ERROR);
684ca987d46SWarner Losh }
685ca987d46SWarner Losh data = malloc(datasz);
68665641822SToomas Soome if (data == NULL) {
68765641822SToomas Soome printf("Out of memory\n");
68865641822SToomas Soome return (CMD_ERROR);
68965641822SToomas Soome }
69065641822SToomas Soome
69165641822SToomas Soome status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, data);
692ca987d46SWarner Losh if (status != EFI_SUCCESS) {
693ca987d46SWarner Losh printf("Can't get the variable: error %#lx\n",
694ca987d46SWarner Losh EFI_ERROR_CODE(status));
69565641822SToomas Soome free(data);
696ca987d46SWarner Losh return (CMD_ERROR);
697ca987d46SWarner Losh }
69865641822SToomas Soome
69965641822SToomas Soome if (efi_guid_to_name(matchguid, &str) == false) {
70065641822SToomas Soome rv = CMD_ERROR;
70165641822SToomas Soome goto done;
702ca987d46SWarner Losh }
703ca987d46SWarner Losh printf("%s ", str);
70465641822SToomas Soome efi_print_var_attr(attr);
70565641822SToomas Soome printf(" %S", varnamearg);
70665641822SToomas Soome
70765641822SToomas Soome if (lflag == 0) {
70865641822SToomas Soome if (strcmp(str, "global") == 0)
70965641822SToomas Soome rv = efi_print_global(varnamearg, data, datasz);
71065641822SToomas Soome else if (strcmp(str, "freebsd") == 0)
71165641822SToomas Soome rv = efi_print_freebsd(varnamearg, data, datasz);
71265641822SToomas Soome else if (strcmp(str,
71365641822SToomas Soome EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0)
71465641822SToomas Soome rv = efi_print_mem_type(varnamearg, data, datasz);
71565641822SToomas Soome else if (strcmp(str,
71665641822SToomas Soome "47c7b227-c42a-11d2-8e57-00a0c969723b") == 0)
71765641822SToomas Soome rv = efi_print_shell_str(varnamearg, data, datasz);
71865641822SToomas Soome else if (strcmp(str, MTC_VARIABLE_NAME) == 0) {
71965641822SToomas Soome printf(" = ");
72065641822SToomas Soome printf("%u", *((uint32_t *)data)); /* UINT32 */
72165641822SToomas Soome rv = CMD_OK;
722ca987d46SWarner Losh if (pager_output("\n"))
72365641822SToomas Soome rv = CMD_WARN;
72465641822SToomas Soome } else
72565641822SToomas Soome rv = efi_print_other_value(data, datasz);
72665641822SToomas Soome } else if (pager_output("\n"))
72765641822SToomas Soome rv = CMD_WARN;
72865641822SToomas Soome
72965641822SToomas Soome done:
73065641822SToomas Soome free(str);
73165641822SToomas Soome free(data);
73265641822SToomas Soome return (rv);
733ca987d46SWarner Losh }
734ca987d46SWarner Losh
735ca987d46SWarner Losh static int
command_efi_show(int argc,char * argv[])736ca987d46SWarner Losh command_efi_show(int argc, char *argv[])
737ca987d46SWarner Losh {
738ca987d46SWarner Losh /*
739ca987d46SWarner Losh * efi-show [-a]
740ca987d46SWarner Losh * print all the env
74111df3a28SWarner Losh * efi-show -g UUID
742ca987d46SWarner Losh * print all the env vars tagged with UUID
743ca987d46SWarner Losh * efi-show -v var
744ca987d46SWarner Losh * search all the env vars and print the ones matching var
74511df3a28SWarner Losh * efi-show -g UUID -v var
74611df3a28SWarner Losh * efi-show UUID var
747ca987d46SWarner Losh * print all the env vars that match UUID and var
748ca987d46SWarner Losh */
749ca987d46SWarner Losh /* NB: We assume EFI_GUID is the same as uuid_t */
750ca987d46SWarner Losh int aflag = 0, gflag = 0, lflag = 0, vflag = 0;
751ca987d46SWarner Losh int ch, rv;
752ca987d46SWarner Losh unsigned i;
753ca987d46SWarner Losh EFI_STATUS status;
75465641822SToomas Soome EFI_GUID varguid = ZERO_GUID;
75565641822SToomas Soome EFI_GUID matchguid = ZERO_GUID;
756ca987d46SWarner Losh CHAR16 *varname;
757ca987d46SWarner Losh CHAR16 *newnm;
758ca987d46SWarner Losh CHAR16 varnamearg[128];
759ca987d46SWarner Losh UINTN varalloc;
760ca987d46SWarner Losh UINTN varsz;
761ca987d46SWarner Losh
76265641822SToomas Soome optind = 1;
76365641822SToomas Soome optreset = 1;
76465641822SToomas Soome opterr = 1;
76565641822SToomas Soome
766ca987d46SWarner Losh while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
767ca987d46SWarner Losh switch (ch) {
768ca987d46SWarner Losh case 'a':
769ca987d46SWarner Losh aflag = 1;
770ca987d46SWarner Losh break;
771ca987d46SWarner Losh case 'g':
772ca987d46SWarner Losh gflag = 1;
77365641822SToomas Soome if (efi_name_to_guid(optarg, &matchguid) == false) {
77465641822SToomas Soome printf("uuid %s could not be parsed\n", optarg);
775ca987d46SWarner Losh return (CMD_ERROR);
776ca987d46SWarner Losh }
777ca987d46SWarner Losh break;
778ca987d46SWarner Losh case 'l':
779ca987d46SWarner Losh lflag = 1;
780ca987d46SWarner Losh break;
781ca987d46SWarner Losh case 'v':
782ca987d46SWarner Losh vflag = 1;
783ca987d46SWarner Losh if (strlen(optarg) >= nitems(varnamearg)) {
78465641822SToomas Soome printf("Variable %s is longer than %zu "
78565641822SToomas Soome "characters\n", optarg, nitems(varnamearg));
786ca987d46SWarner Losh return (CMD_ERROR);
787ca987d46SWarner Losh }
78865641822SToomas Soome cpy8to16(optarg, varnamearg, nitems(varnamearg));
789ca987d46SWarner Losh break;
790ca987d46SWarner Losh default:
791ca987d46SWarner Losh return (CMD_ERROR);
792ca987d46SWarner Losh }
793ca987d46SWarner Losh }
794ca987d46SWarner Losh
79565641822SToomas Soome if (argc == 1) /* default is -a */
79665641822SToomas Soome aflag = 1;
79765641822SToomas Soome
798ca987d46SWarner Losh if (aflag && (gflag || vflag)) {
79965641822SToomas Soome printf("-a isn't compatible with -g or -v\n");
800ca987d46SWarner Losh return (CMD_ERROR);
801ca987d46SWarner Losh }
802ca987d46SWarner Losh
803ca987d46SWarner Losh if (aflag && optind < argc) {
804ca987d46SWarner Losh printf("-a doesn't take any args\n");
805ca987d46SWarner Losh return (CMD_ERROR);
806ca987d46SWarner Losh }
807ca987d46SWarner Losh
808ca987d46SWarner Losh argc -= optind;
809ca987d46SWarner Losh argv += optind;
810ca987d46SWarner Losh
811ca987d46SWarner Losh pager_open();
812ca987d46SWarner Losh if (vflag && gflag) {
813ca987d46SWarner Losh rv = efi_print_var(varnamearg, &matchguid, lflag);
81465641822SToomas Soome if (rv == CMD_WARN)
81565641822SToomas Soome rv = CMD_OK;
816ca987d46SWarner Losh pager_close();
817ca987d46SWarner Losh return (rv);
818ca987d46SWarner Losh }
819ca987d46SWarner Losh
820ca987d46SWarner Losh if (argc == 2) {
821ca987d46SWarner Losh optarg = argv[0];
822ca987d46SWarner Losh if (strlen(optarg) >= nitems(varnamearg)) {
82365641822SToomas Soome printf("Variable %s is longer than %zu characters\n",
824ca987d46SWarner Losh optarg, nitems(varnamearg));
825ca987d46SWarner Losh pager_close();
826ca987d46SWarner Losh return (CMD_ERROR);
827ca987d46SWarner Losh }
828ca987d46SWarner Losh for (i = 0; i < strlen(optarg); i++)
829ca987d46SWarner Losh varnamearg[i] = optarg[i];
830ca987d46SWarner Losh varnamearg[i] = 0;
831ca987d46SWarner Losh optarg = argv[1];
83265641822SToomas Soome if (efi_name_to_guid(optarg, &matchguid) == false) {
83365641822SToomas Soome printf("uuid %s could not be parsed\n", optarg);
834ca987d46SWarner Losh pager_close();
835ca987d46SWarner Losh return (CMD_ERROR);
836ca987d46SWarner Losh }
837ca987d46SWarner Losh rv = efi_print_var(varnamearg, &matchguid, lflag);
83865641822SToomas Soome if (rv == CMD_WARN)
83965641822SToomas Soome rv = CMD_OK;
840ca987d46SWarner Losh pager_close();
841ca987d46SWarner Losh return (rv);
842ca987d46SWarner Losh }
843ca987d46SWarner Losh
844ca987d46SWarner Losh if (argc > 0) {
84565641822SToomas Soome printf("Too many args: %d\n", argc);
846ca987d46SWarner Losh pager_close();
847ca987d46SWarner Losh return (CMD_ERROR);
848ca987d46SWarner Losh }
849ca987d46SWarner Losh
850ca987d46SWarner Losh /*
851ca987d46SWarner Losh * Initiate the search -- note the standard takes pain
852ca987d46SWarner Losh * to specify the initial call must be a poiner to a NULL
853ca987d46SWarner Losh * character.
854ca987d46SWarner Losh */
855ca987d46SWarner Losh varalloc = 1024;
856ca987d46SWarner Losh varname = malloc(varalloc);
857ca987d46SWarner Losh if (varname == NULL) {
858ca987d46SWarner Losh printf("Can't allocate memory to get variables\n");
859ca987d46SWarner Losh pager_close();
860ca987d46SWarner Losh return (CMD_ERROR);
861ca987d46SWarner Losh }
862ca987d46SWarner Losh varname[0] = 0;
863ca987d46SWarner Losh while (1) {
864ca987d46SWarner Losh varsz = varalloc;
865ca987d46SWarner Losh status = RS->GetNextVariableName(&varsz, varname, &varguid);
866ca987d46SWarner Losh if (status == EFI_BUFFER_TOO_SMALL) {
867ca987d46SWarner Losh varalloc = varsz;
868ca987d46SWarner Losh newnm = realloc(varname, varalloc);
869ca987d46SWarner Losh if (newnm == NULL) {
87065641822SToomas Soome printf("Can't allocate memory to get "
87165641822SToomas Soome "variables\n");
87265641822SToomas Soome rv = CMD_ERROR;
87365641822SToomas Soome break;
874ca987d46SWarner Losh }
875ca987d46SWarner Losh varname = newnm;
876ca987d46SWarner Losh continue; /* Try again with bigger buffer */
877ca987d46SWarner Losh }
87865641822SToomas Soome if (status == EFI_NOT_FOUND) {
87965641822SToomas Soome rv = CMD_OK;
880ca987d46SWarner Losh break;
88165641822SToomas Soome }
88265641822SToomas Soome if (status != EFI_SUCCESS) {
88365641822SToomas Soome rv = CMD_ERROR;
88465641822SToomas Soome break;
88565641822SToomas Soome }
88665641822SToomas Soome
887ca987d46SWarner Losh if (aflag) {
88865641822SToomas Soome rv = efi_print_var(varname, &varguid, lflag);
88965641822SToomas Soome if (rv != CMD_OK) {
89065641822SToomas Soome if (rv == CMD_WARN)
89165641822SToomas Soome rv = CMD_OK;
892ca987d46SWarner Losh break;
89365641822SToomas Soome }
894ca987d46SWarner Losh continue;
895ca987d46SWarner Losh }
896ca987d46SWarner Losh if (vflag) {
897ca987d46SWarner Losh if (wcscmp(varnamearg, varname) == 0) {
89865641822SToomas Soome rv = efi_print_var(varname, &varguid, lflag);
89965641822SToomas Soome if (rv != CMD_OK) {
90065641822SToomas Soome if (rv == CMD_WARN)
90165641822SToomas Soome rv = CMD_OK;
902ca987d46SWarner Losh break;
90365641822SToomas Soome }
904ca987d46SWarner Losh continue;
905ca987d46SWarner Losh }
906ca987d46SWarner Losh }
907ca987d46SWarner Losh if (gflag) {
90865641822SToomas Soome rv = uuid_equal((uuid_t *)&varguid,
90965641822SToomas Soome (uuid_t *)&matchguid, NULL);
91065641822SToomas Soome if (rv != 0) {
91165641822SToomas Soome rv = efi_print_var(varname, &varguid, lflag);
91265641822SToomas Soome if (rv != CMD_OK) {
91365641822SToomas Soome if (rv == CMD_WARN)
91465641822SToomas Soome rv = CMD_OK;
915ca987d46SWarner Losh break;
91665641822SToomas Soome }
917ca987d46SWarner Losh continue;
918ca987d46SWarner Losh }
919ca987d46SWarner Losh }
920ca987d46SWarner Losh }
921ca987d46SWarner Losh free(varname);
922ca987d46SWarner Losh pager_close();
923ca987d46SWarner Losh
92465641822SToomas Soome return (rv);
925ca987d46SWarner Losh }
926ca987d46SWarner Losh
927ca987d46SWarner Losh COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set);
928ca987d46SWarner Losh
929ca987d46SWarner Losh static int
command_efi_set(int argc,char * argv[])930ca987d46SWarner Losh command_efi_set(int argc, char *argv[])
931ca987d46SWarner Losh {
932ca987d46SWarner Losh char *uuid, *var, *val;
933ca987d46SWarner Losh CHAR16 wvar[128];
934ca987d46SWarner Losh EFI_GUID guid;
93565641822SToomas Soome #if defined(ENABLE_UPDATES)
936ca987d46SWarner Losh EFI_STATUS err;
93765641822SToomas Soome #endif
938ca987d46SWarner Losh
939ca987d46SWarner Losh if (argc != 4) {
940ca987d46SWarner Losh printf("efi-set uuid var new-value\n");
941ca987d46SWarner Losh return (CMD_ERROR);
942ca987d46SWarner Losh }
943ca987d46SWarner Losh uuid = argv[1];
944ca987d46SWarner Losh var = argv[2];
945ca987d46SWarner Losh val = argv[3];
94665641822SToomas Soome if (efi_name_to_guid(uuid, &guid) == false) {
94765641822SToomas Soome printf("Invalid uuid %s\n", uuid);
948ca987d46SWarner Losh return (CMD_ERROR);
949ca987d46SWarner Losh }
95065641822SToomas Soome cpy8to16(var, wvar, nitems(wvar));
95165641822SToomas Soome #if defined(ENABLE_UPDATES)
95265641822SToomas Soome err = RS->SetVariable(wvar, &guid, EFI_VARIABLE_NON_VOLATILE |
95365641822SToomas Soome EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
954ca987d46SWarner Losh strlen(val) + 1, val);
955ca987d46SWarner Losh if (EFI_ERROR(err)) {
95665641822SToomas Soome printf("Failed to set variable: error %lu\n",
95765641822SToomas Soome EFI_ERROR_CODE(err));
958ca987d46SWarner Losh return (CMD_ERROR);
959ca987d46SWarner Losh }
96065641822SToomas Soome #else
96165641822SToomas Soome printf("would set %s %s = %s\n", uuid, var, val);
96265641822SToomas Soome #endif
963ca987d46SWarner Losh return (CMD_OK);
964ca987d46SWarner Losh }
965ca987d46SWarner Losh
966ca987d46SWarner Losh COMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", command_efi_unset);
967ca987d46SWarner Losh
968ca987d46SWarner Losh static int
command_efi_unset(int argc,char * argv[])969ca987d46SWarner Losh command_efi_unset(int argc, char *argv[])
970ca987d46SWarner Losh {
971ca987d46SWarner Losh char *uuid, *var;
972ca987d46SWarner Losh CHAR16 wvar[128];
973ca987d46SWarner Losh EFI_GUID guid;
97465641822SToomas Soome #if defined(ENABLE_UPDATES)
975ca987d46SWarner Losh EFI_STATUS err;
97665641822SToomas Soome #endif
977ca987d46SWarner Losh
978ca987d46SWarner Losh if (argc != 3) {
979ca987d46SWarner Losh printf("efi-unset uuid var\n");
980ca987d46SWarner Losh return (CMD_ERROR);
981ca987d46SWarner Losh }
982ca987d46SWarner Losh uuid = argv[1];
983ca987d46SWarner Losh var = argv[2];
98465641822SToomas Soome if (efi_name_to_guid(uuid, &guid) == false) {
985ca987d46SWarner Losh printf("Invalid uuid %s\n", uuid);
986ca987d46SWarner Losh return (CMD_ERROR);
987ca987d46SWarner Losh }
98865641822SToomas Soome cpy8to16(var, wvar, nitems(wvar));
98965641822SToomas Soome #if defined(ENABLE_UPDATES)
990ca987d46SWarner Losh err = RS->SetVariable(wvar, &guid, 0, 0, NULL);
991ca987d46SWarner Losh if (EFI_ERROR(err)) {
99265641822SToomas Soome printf("Failed to unset variable: error %lu\n",
99365641822SToomas Soome EFI_ERROR_CODE(err));
994ca987d46SWarner Losh return (CMD_ERROR);
995ca987d46SWarner Losh }
99665641822SToomas Soome #else
99765641822SToomas Soome printf("would unset %s %s \n", uuid, var);
99865641822SToomas Soome #endif
999ca987d46SWarner Losh return (CMD_OK);
1000ca987d46SWarner Losh }
1001