1300081Simp/* 2300081Simp * Copyright (c) 2015 Netflix, Inc. All Rights Reserved. 3300081Simp * 4300081Simp * Redistribution and use in source and binary forms, with or without 5300081Simp * modification, are permitted provided that the following conditions 6300081Simp * are met: 7300081Simp * 1. Redistributions of source code must retain the above copyright 8300081Simp * notice, this list of conditions and the following disclaimer. 9300081Simp * 2. Redistributions in binary form must reproduce the above copyright 10300081Simp * notice, this list of conditions and the following disclaimer in the 11300081Simp * documentation and/or other materials provided with the distribution. 12300081Simp * 13300081Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14300081Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15300081Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16300081Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17300081Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18300081Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19300081Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20300081Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21300081Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22300081Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23300081Simp * SUCH DAMAGE. 24300081Simp */ 25300081Simp 26300081Simp#include <sys/cdefs.h> 27300081Simp__FBSDID("$FreeBSD: stable/11/stand/efi/libefi/env.c 346482 2019-04-21 04:26:02Z kevans $"); 28300081Simp 29329011Skevans#include <stand.h> 30329011Skevans#include <string.h> 31300081Simp#include <efi.h> 32346482Skevans#include <efichar.h> 33300081Simp#include <efilib.h> 34346482Skevans#include <efigpt.h> /* Partition GUIDS */ 35346482Skevans#include <Guid/MemoryTypeInformation.h> 36346482Skevans#include <Guid/MtcVendor.h> 37346482Skevans#include <Guid/ZeroGuid.h> 38346482Skevans#include <Protocol/EdidActive.h> 39346482Skevans#include <Protocol/EdidDiscovered.h> 40329011Skevans#include <uuid.h> 41329099Skevans#include <stdbool.h> 42346482Skevans#include <sys/param.h> 43329011Skevans#include "bootstrap.h" 44300081Simp 45346482Skevans/* 46346482Skevans * About ENABLE_UPDATES 47346482Skevans * 48346482Skevans * The UEFI variables are identified only by GUID and name, there is no 49346482Skevans * way to (auto)detect the type for the value, so we need to process the 50346482Skevans * variables case by case, as we do learn about them. 51346482Skevans * 52346482Skevans * While showing the variable name and the value is safe, we must not store 53346482Skevans * random values nor allow removing (random) variables. 54346482Skevans * 55346482Skevans * Since we do have stub code to set/unset the variables, I do want to keep 56346482Skevans * it to make the future development a bit easier, but the updates are disabled 57346482Skevans * by default till: 58346482Skevans * a) the validation and data translation to values is properly implemented 59346482Skevans * b) We have established which variables we do allow to be updated. 60346482Skevans * Therefore the set/unset code is included only for developers aid. 61346482Skevans */ 62346482Skevans 63346482Skevansstatic struct efi_uuid_mapping { 64346482Skevans const char *efi_guid_name; 65346482Skevans EFI_GUID efi_guid; 66346482Skevans} efi_uuid_mapping[] = { 67346482Skevans { .efi_guid_name = "global", .efi_guid = EFI_GLOBAL_VARIABLE }, 68346482Skevans { .efi_guid_name = "freebsd", .efi_guid = FREEBSD_BOOT_VAR_GUID }, 69346482Skevans /* EFI Systab entry names. */ 70346482Skevans { .efi_guid_name = "MPS Table", .efi_guid = MPS_TABLE_GUID }, 71346482Skevans { .efi_guid_name = "ACPI Table", .efi_guid = ACPI_TABLE_GUID }, 72346482Skevans { .efi_guid_name = "ACPI 2.0 Table", .efi_guid = ACPI_20_TABLE_GUID }, 73346482Skevans { .efi_guid_name = "SMBIOS Table", .efi_guid = SMBIOS_TABLE_GUID }, 74346482Skevans { .efi_guid_name = "SMBIOS3 Table", .efi_guid = SMBIOS3_TABLE_GUID }, 75346482Skevans { .efi_guid_name = "DXE Table", .efi_guid = DXE_SERVICES_TABLE_GUID }, 76346482Skevans { .efi_guid_name = "HOB List Table", .efi_guid = HOB_LIST_TABLE_GUID }, 77346482Skevans { .efi_guid_name = EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, 78346482Skevans .efi_guid = EFI_MEMORY_TYPE_INFORMATION_GUID }, 79346482Skevans { .efi_guid_name = "Debug Image Info Table", 80346482Skevans .efi_guid = DEBUG_IMAGE_INFO_TABLE_GUID }, 81346482Skevans { .efi_guid_name = "FDT Table", .efi_guid = FDT_TABLE_GUID }, 82346482Skevans /* 83346482Skevans * Protocol names for debug purposes. 84346482Skevans * Can be removed along with lsefi command. 85346482Skevans */ 86346482Skevans { .efi_guid_name = "device path", .efi_guid = DEVICE_PATH_PROTOCOL }, 87346482Skevans { .efi_guid_name = "block io", .efi_guid = BLOCK_IO_PROTOCOL }, 88346482Skevans { .efi_guid_name = "disk io", .efi_guid = DISK_IO_PROTOCOL }, 89346482Skevans { .efi_guid_name = "disk info", .efi_guid = 90346482Skevans EFI_DISK_INFO_PROTOCOL_GUID }, 91346482Skevans { .efi_guid_name = "simple fs", 92346482Skevans .efi_guid = SIMPLE_FILE_SYSTEM_PROTOCOL }, 93346482Skevans { .efi_guid_name = "load file", .efi_guid = LOAD_FILE_PROTOCOL }, 94346482Skevans { .efi_guid_name = "device io", .efi_guid = DEVICE_IO_PROTOCOL }, 95346482Skevans { .efi_guid_name = "unicode collation", 96346482Skevans .efi_guid = UNICODE_COLLATION_PROTOCOL }, 97346482Skevans { .efi_guid_name = "unicode collation2", 98346482Skevans .efi_guid = EFI_UNICODE_COLLATION2_PROTOCOL_GUID }, 99346482Skevans { .efi_guid_name = "simple network", 100346482Skevans .efi_guid = EFI_SIMPLE_NETWORK_PROTOCOL }, 101346482Skevans { .efi_guid_name = "simple text output", 102346482Skevans .efi_guid = SIMPLE_TEXT_OUTPUT_PROTOCOL }, 103346482Skevans { .efi_guid_name = "simple text input", 104346482Skevans .efi_guid = SIMPLE_TEXT_INPUT_PROTOCOL }, 105346482Skevans { .efi_guid_name = "simple text ex input", 106346482Skevans .efi_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID }, 107346482Skevans { .efi_guid_name = "console control", 108346482Skevans .efi_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID }, 109346482Skevans { .efi_guid_name = "stdin", .efi_guid = EFI_CONSOLE_IN_DEVICE_GUID }, 110346482Skevans { .efi_guid_name = "stdout", .efi_guid = EFI_CONSOLE_OUT_DEVICE_GUID }, 111346482Skevans { .efi_guid_name = "stderr", 112346482Skevans .efi_guid = EFI_STANDARD_ERROR_DEVICE_GUID }, 113346482Skevans { .efi_guid_name = "GOP", 114346482Skevans .efi_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID }, 115346482Skevans { .efi_guid_name = "UGA draw", .efi_guid = EFI_UGA_DRAW_PROTOCOL_GUID }, 116346482Skevans { .efi_guid_name = "PXE base code", 117346482Skevans .efi_guid = EFI_PXE_BASE_CODE_PROTOCOL }, 118346482Skevans { .efi_guid_name = "PXE base code callback", 119346482Skevans .efi_guid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL }, 120346482Skevans { .efi_guid_name = "serial io", .efi_guid = SERIAL_IO_PROTOCOL }, 121346482Skevans { .efi_guid_name = "loaded image", .efi_guid = LOADED_IMAGE_PROTOCOL }, 122346482Skevans { .efi_guid_name = "loaded image device path", 123346482Skevans .efi_guid = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID }, 124346482Skevans { .efi_guid_name = "ISA io", .efi_guid = EFI_ISA_IO_PROTOCOL_GUID }, 125346482Skevans { .efi_guid_name = "IDE controller init", 126346482Skevans .efi_guid = EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID }, 127346482Skevans { .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID }, 128346482Skevans { .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID }, 129346482Skevans { .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID }, 130346482Skevans { .efi_guid_name = "PCI enumeration", 131346482Skevans .efi_guid = EFI_PCI_ENUMERATION_COMPLETE_GUID }, 132346482Skevans { .efi_guid_name = "Driver diagnostics", 133346482Skevans .efi_guid = EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID }, 134346482Skevans { .efi_guid_name = "Driver diagnostics2", 135346482Skevans .efi_guid = EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID }, 136346482Skevans { .efi_guid_name = "simple pointer", 137346482Skevans .efi_guid = EFI_SIMPLE_POINTER_PROTOCOL_GUID }, 138346482Skevans { .efi_guid_name = "absolute pointer", 139346482Skevans .efi_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID }, 140346482Skevans { .efi_guid_name = "VLAN config", 141346482Skevans .efi_guid = EFI_VLAN_CONFIG_PROTOCOL_GUID }, 142346482Skevans { .efi_guid_name = "ARP service binding", 143346482Skevans .efi_guid = EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID }, 144346482Skevans { .efi_guid_name = "ARP", .efi_guid = EFI_ARP_PROTOCOL_GUID }, 145346482Skevans { .efi_guid_name = "IPv4 service binding", 146346482Skevans .efi_guid = EFI_IP4_SERVICE_BINDING_PROTOCOL }, 147346482Skevans { .efi_guid_name = "IPv4", .efi_guid = EFI_IP4_PROTOCOL }, 148346482Skevans { .efi_guid_name = "IPv4 config", 149346482Skevans .efi_guid = EFI_IP4_CONFIG_PROTOCOL_GUID }, 150346482Skevans { .efi_guid_name = "IPv6 service binding", 151346482Skevans .efi_guid = EFI_IP6_SERVICE_BINDING_PROTOCOL }, 152346482Skevans { .efi_guid_name = "IPv6", .efi_guid = EFI_IP6_PROTOCOL }, 153346482Skevans { .efi_guid_name = "IPv6 config", 154346482Skevans .efi_guid = EFI_IP6_CONFIG_PROTOCOL_GUID }, 155346482Skevans { .efi_guid_name = "UDPv4", .efi_guid = EFI_UDP4_PROTOCOL }, 156346482Skevans { .efi_guid_name = "UDPv4 service binding", 157346482Skevans .efi_guid = EFI_UDP4_SERVICE_BINDING_PROTOCOL }, 158346482Skevans { .efi_guid_name = "UDPv6", .efi_guid = EFI_UDP6_PROTOCOL }, 159346482Skevans { .efi_guid_name = "UDPv6 service binding", 160346482Skevans .efi_guid = EFI_UDP6_SERVICE_BINDING_PROTOCOL }, 161346482Skevans { .efi_guid_name = "TCPv4", .efi_guid = EFI_TCP4_PROTOCOL }, 162346482Skevans { .efi_guid_name = "TCPv4 service binding", 163346482Skevans .efi_guid = EFI_TCP4_SERVICE_BINDING_PROTOCOL }, 164346482Skevans { .efi_guid_name = "TCPv6", .efi_guid = EFI_TCP6_PROTOCOL }, 165346482Skevans { .efi_guid_name = "TCPv6 service binding", 166346482Skevans .efi_guid = EFI_TCP6_SERVICE_BINDING_PROTOCOL }, 167346482Skevans { .efi_guid_name = "EFI System partition", 168346482Skevans .efi_guid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID }, 169346482Skevans { .efi_guid_name = "MBR legacy", 170346482Skevans .efi_guid = EFI_PART_TYPE_LEGACY_MBR_GUID }, 171346482Skevans { .efi_guid_name = "device tree", .efi_guid = EFI_DEVICE_TREE_GUID }, 172346482Skevans { .efi_guid_name = "USB io", .efi_guid = EFI_USB_IO_PROTOCOL_GUID }, 173346482Skevans { .efi_guid_name = "USB2 HC", .efi_guid = EFI_USB2_HC_PROTOCOL_GUID }, 174346482Skevans { .efi_guid_name = "component name", 175346482Skevans .efi_guid = EFI_COMPONENT_NAME_PROTOCOL_GUID }, 176346482Skevans { .efi_guid_name = "component name2", 177346482Skevans .efi_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID }, 178346482Skevans { .efi_guid_name = "driver binding", 179346482Skevans .efi_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID }, 180346482Skevans { .efi_guid_name = "driver configuration", 181346482Skevans .efi_guid = EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID }, 182346482Skevans { .efi_guid_name = "driver configuration2", 183346482Skevans .efi_guid = EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID }, 184346482Skevans { .efi_guid_name = "decompress", 185346482Skevans .efi_guid = EFI_DECOMPRESS_PROTOCOL_GUID }, 186346482Skevans { .efi_guid_name = "ebc interpreter", 187346482Skevans .efi_guid = EFI_EBC_INTERPRETER_PROTOCOL_GUID }, 188346482Skevans { .efi_guid_name = "network interface identifier", 189346482Skevans .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL }, 190346482Skevans { .efi_guid_name = "network interface identifier_31", 191346482Skevans .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31 }, 192346482Skevans { .efi_guid_name = "managed network service binding", 193346482Skevans .efi_guid = EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID }, 194346482Skevans { .efi_guid_name = "managed network", 195346482Skevans .efi_guid = EFI_MANAGED_NETWORK_PROTOCOL_GUID }, 196346482Skevans { .efi_guid_name = "form browser", 197346482Skevans .efi_guid = EFI_FORM_BROWSER2_PROTOCOL_GUID }, 198346482Skevans { .efi_guid_name = "HII config routing", 199346482Skevans .efi_guid = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID }, 200346482Skevans { .efi_guid_name = "HII database", 201346482Skevans .efi_guid = EFI_HII_DATABASE_PROTOCOL_GUID }, 202346482Skevans { .efi_guid_name = "HII string", 203346482Skevans .efi_guid = EFI_HII_STRING_PROTOCOL_GUID }, 204346482Skevans { .efi_guid_name = "HII image", 205346482Skevans .efi_guid = EFI_HII_IMAGE_PROTOCOL_GUID }, 206346482Skevans { .efi_guid_name = "HII font", .efi_guid = EFI_HII_FONT_PROTOCOL_GUID }, 207346482Skevans { .efi_guid_name = "HII config", 208346482Skevans .efi_guid = EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID }, 209346482Skevans { .efi_guid_name = "MTFTP4 service binding", 210346482Skevans .efi_guid = EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID }, 211346482Skevans { .efi_guid_name = "MTFTP4", .efi_guid = EFI_MTFTP4_PROTOCOL_GUID }, 212346482Skevans { .efi_guid_name = "MTFTP6 service binding", 213346482Skevans .efi_guid = EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID }, 214346482Skevans { .efi_guid_name = "MTFTP6", .efi_guid = EFI_MTFTP6_PROTOCOL_GUID }, 215346482Skevans { .efi_guid_name = "DHCP4 service binding", 216346482Skevans .efi_guid = EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID }, 217346482Skevans { .efi_guid_name = "DHCP4", .efi_guid = EFI_DHCP4_PROTOCOL_GUID }, 218346482Skevans { .efi_guid_name = "DHCP6 service binding", 219346482Skevans .efi_guid = EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID }, 220346482Skevans { .efi_guid_name = "DHCP6", .efi_guid = EFI_DHCP6_PROTOCOL_GUID }, 221346482Skevans { .efi_guid_name = "SCSI io", .efi_guid = EFI_SCSI_IO_PROTOCOL_GUID }, 222346482Skevans { .efi_guid_name = "SCSI pass thru", 223346482Skevans .efi_guid = EFI_SCSI_PASS_THRU_PROTOCOL_GUID }, 224346482Skevans { .efi_guid_name = "SCSI pass thru ext", 225346482Skevans .efi_guid = EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID }, 226346482Skevans { .efi_guid_name = "Capsule arch", 227346482Skevans .efi_guid = EFI_CAPSULE_ARCH_PROTOCOL_GUID }, 228346482Skevans { .efi_guid_name = "monotonic counter arch", 229346482Skevans .efi_guid = EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID }, 230346482Skevans { .efi_guid_name = "realtime clock arch", 231346482Skevans .efi_guid = EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID }, 232346482Skevans { .efi_guid_name = "variable arch", 233346482Skevans .efi_guid = EFI_VARIABLE_ARCH_PROTOCOL_GUID }, 234346482Skevans { .efi_guid_name = "variable write arch", 235346482Skevans .efi_guid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID }, 236346482Skevans { .efi_guid_name = "watchdog timer arch", 237346482Skevans .efi_guid = EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID }, 238346482Skevans { .efi_guid_name = "ACPI support", 239346482Skevans .efi_guid = EFI_ACPI_SUPPORT_PROTOCOL_GUID }, 240346482Skevans { .efi_guid_name = "BDS arch", .efi_guid = EFI_BDS_ARCH_PROTOCOL_GUID }, 241346482Skevans { .efi_guid_name = "metronome arch", 242346482Skevans .efi_guid = EFI_METRONOME_ARCH_PROTOCOL_GUID }, 243346482Skevans { .efi_guid_name = "timer arch", 244346482Skevans .efi_guid = EFI_TIMER_ARCH_PROTOCOL_GUID }, 245346482Skevans { .efi_guid_name = "DPC", .efi_guid = EFI_DPC_PROTOCOL_GUID }, 246346482Skevans { .efi_guid_name = "print2", .efi_guid = EFI_PRINT2_PROTOCOL_GUID }, 247346482Skevans { .efi_guid_name = "device path to text", 248346482Skevans .efi_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID }, 249346482Skevans { .efi_guid_name = "reset arch", 250346482Skevans .efi_guid = EFI_RESET_ARCH_PROTOCOL_GUID }, 251346482Skevans { .efi_guid_name = "CPU arch", .efi_guid = EFI_CPU_ARCH_PROTOCOL_GUID }, 252346482Skevans { .efi_guid_name = "CPU IO2", .efi_guid = EFI_CPU_IO2_PROTOCOL_GUID }, 253346482Skevans { .efi_guid_name = "Legacy 8259", 254346482Skevans .efi_guid = EFI_LEGACY_8259_PROTOCOL_GUID }, 255346482Skevans { .efi_guid_name = "Security arch", 256346482Skevans .efi_guid = EFI_SECURITY_ARCH_PROTOCOL_GUID }, 257346482Skevans { .efi_guid_name = "Security2 arch", 258346482Skevans .efi_guid = EFI_SECURITY2_ARCH_PROTOCOL_GUID }, 259346482Skevans { .efi_guid_name = "Runtime arch", 260346482Skevans .efi_guid = EFI_RUNTIME_ARCH_PROTOCOL_GUID }, 261346482Skevans { .efi_guid_name = "status code runtime", 262346482Skevans .efi_guid = EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID }, 263346482Skevans { .efi_guid_name = "data hub", .efi_guid = EFI_DATA_HUB_PROTOCOL_GUID }, 264346482Skevans { .efi_guid_name = "PCD", .efi_guid = PCD_PROTOCOL_GUID }, 265346482Skevans { .efi_guid_name = "EFI PCD", .efi_guid = EFI_PCD_PROTOCOL_GUID }, 266346482Skevans { .efi_guid_name = "firmware volume block", 267346482Skevans .efi_guid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID }, 268346482Skevans { .efi_guid_name = "firmware volume2", 269346482Skevans .efi_guid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID }, 270346482Skevans { .efi_guid_name = "firmware volume dispatch", 271346482Skevans .efi_guid = EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID }, 272346482Skevans { .efi_guid_name = "lzma compress", .efi_guid = LZMA_COMPRESS_GUID }, 273346482Skevans { .efi_guid_name = "MP services", 274346482Skevans .efi_guid = EFI_MP_SERVICES_PROTOCOL_GUID }, 275346482Skevans { .efi_guid_name = MTC_VARIABLE_NAME, .efi_guid = MTC_VENDOR_GUID }, 276346482Skevans { .efi_guid_name = "RTC", .efi_guid = { 0x378D7B65, 0x8DA9, 0x4773, 277346482Skevans { 0xB6, 0xE4, 0xA4, 0x78, 0x26, 0xA8, 0x33, 0xE1} } }, 278346482Skevans { .efi_guid_name = "Active EDID", 279346482Skevans .efi_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID }, 280346482Skevans { .efi_guid_name = "Discovered EDID", 281346482Skevans .efi_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID } 282346482Skevans}; 283346482Skevans 284346482Skevansbool 285346482Skevansefi_guid_to_str(const EFI_GUID *guid, char **sp) 286346482Skevans{ 287346482Skevans uint32_t status; 288346482Skevans 289346482Skevans uuid_to_string((const uuid_t *)guid, sp, &status); 290346482Skevans return (status == uuid_s_ok ? true : false); 291346482Skevans} 292346482Skevans 293346482Skevansbool 294346482Skevansefi_str_to_guid(const char *s, EFI_GUID *guid) 295346482Skevans{ 296346482Skevans uint32_t status; 297346482Skevans 298346482Skevans uuid_from_string(s, (uuid_t *)guid, &status); 299346482Skevans return (status == uuid_s_ok ? true : false); 300346482Skevans} 301346482Skevans 302346482Skevansbool 303346482Skevansefi_name_to_guid(const char *name, EFI_GUID *guid) 304346482Skevans{ 305346482Skevans uint32_t i; 306346482Skevans 307346482Skevans for (i = 0; i < nitems(efi_uuid_mapping); i++) { 308346482Skevans if (strcasecmp(name, efi_uuid_mapping[i].efi_guid_name) == 0) { 309346482Skevans *guid = efi_uuid_mapping[i].efi_guid; 310346482Skevans return (true); 311346482Skevans } 312346482Skevans } 313346482Skevans return (efi_str_to_guid(name, guid)); 314346482Skevans} 315346482Skevans 316346482Skevansbool 317346482Skevansefi_guid_to_name(EFI_GUID *guid, char **name) 318346482Skevans{ 319346482Skevans uint32_t i; 320346482Skevans int rv; 321346482Skevans 322346482Skevans for (i = 0; i < nitems(efi_uuid_mapping); i++) { 323346482Skevans rv = uuid_equal((uuid_t *)guid, 324346482Skevans (uuid_t *)&efi_uuid_mapping[i].efi_guid, NULL); 325346482Skevans if (rv != 0) { 326346482Skevans *name = strdup(efi_uuid_mapping[i].efi_guid_name); 327346482Skevans if (*name == NULL) 328346482Skevans return (false); 329346482Skevans return (true); 330346482Skevans } 331346482Skevans } 332346482Skevans return (efi_guid_to_str(guid, name)); 333346482Skevans} 334346482Skevans 335329099Skevansvoid 336329099Skevansefi_init_environment(void) 337329099Skevans{ 338329099Skevans char var[128]; 339329099Skevans 340329099Skevans snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16, 341329099Skevans ST->Hdr.Revision & 0xffff); 342329099Skevans env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset); 343329099Skevans} 344329099Skevans 345329099SkevansCOMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show); 346329099Skevans 347329099Skevansstatic int 348346482Skevansefi_print_other_value(uint8_t *data, UINTN datasz) 349346482Skevans{ 350346482Skevans UINTN i; 351346482Skevans bool is_ascii = true; 352346482Skevans 353346482Skevans printf(" = "); 354346482Skevans for (i = 0; i < datasz - 1; i++) { 355346482Skevans /* 356346482Skevans * Quick hack to see if this ascii-ish string is printable 357346482Skevans * range plus tab, cr and lf. 358346482Skevans */ 359346482Skevans if ((data[i] < 32 || data[i] > 126) 360346482Skevans && data[i] != 9 && data[i] != 10 && data[i] != 13) { 361346482Skevans is_ascii = false; 362346482Skevans break; 363346482Skevans } 364346482Skevans } 365346482Skevans if (data[datasz - 1] != '\0') 366346482Skevans is_ascii = false; 367346482Skevans if (is_ascii == true) { 368346482Skevans printf("%s", data); 369346482Skevans if (pager_output("\n")) 370346482Skevans return (CMD_WARN); 371346482Skevans } else { 372346482Skevans if (pager_output("\n")) 373346482Skevans return (CMD_WARN); 374346482Skevans /* 375346482Skevans * Dump hex bytes grouped by 4. 376346482Skevans */ 377346482Skevans for (i = 0; i < datasz; i++) { 378346482Skevans printf("%02x ", data[i]); 379346482Skevans if ((i + 1) % 4 == 0) 380346482Skevans printf(" "); 381346482Skevans if ((i + 1) % 20 == 0) { 382346482Skevans if (pager_output("\n")) 383346482Skevans return (CMD_WARN); 384346482Skevans } 385346482Skevans } 386346482Skevans if (pager_output("\n")) 387346482Skevans return (CMD_WARN); 388346482Skevans } 389346482Skevans 390346482Skevans return (CMD_OK); 391346482Skevans} 392346482Skevans 393346482Skevans/* This appears to be some sort of UEFI shell alias table. */ 394346482Skevansstatic int 395346482Skevansefi_print_shell_str(const CHAR16 *varnamearg __unused, uint8_t *data, 396346482Skevans UINTN datasz __unused) 397346482Skevans{ 398346482Skevans printf(" = %S", (CHAR16 *)data); 399346482Skevans if (pager_output("\n")) 400346482Skevans return (CMD_WARN); 401346482Skevans return (CMD_OK); 402346482Skevans} 403346482Skevans 404346482Skevansconst char * 405346482Skevansefi_memory_type(EFI_MEMORY_TYPE type) 406346482Skevans{ 407346482Skevans const char *types[] = { 408346482Skevans "Reserved", 409346482Skevans "LoaderCode", 410346482Skevans "LoaderData", 411346482Skevans "BootServicesCode", 412346482Skevans "BootServicesData", 413346482Skevans "RuntimeServicesCode", 414346482Skevans "RuntimeServicesData", 415346482Skevans "ConventionalMemory", 416346482Skevans "UnusableMemory", 417346482Skevans "ACPIReclaimMemory", 418346482Skevans "ACPIMemoryNVS", 419346482Skevans "MemoryMappedIO", 420346482Skevans "MemoryMappedIOPortSpace", 421346482Skevans "PalCode", 422346482Skevans "PersistentMemory" 423346482Skevans }; 424346482Skevans 425346482Skevans switch (type) { 426346482Skevans case EfiReservedMemoryType: 427346482Skevans case EfiLoaderCode: 428346482Skevans case EfiLoaderData: 429346482Skevans case EfiBootServicesCode: 430346482Skevans case EfiBootServicesData: 431346482Skevans case EfiRuntimeServicesCode: 432346482Skevans case EfiRuntimeServicesData: 433346482Skevans case EfiConventionalMemory: 434346482Skevans case EfiUnusableMemory: 435346482Skevans case EfiACPIReclaimMemory: 436346482Skevans case EfiACPIMemoryNVS: 437346482Skevans case EfiMemoryMappedIO: 438346482Skevans case EfiMemoryMappedIOPortSpace: 439346482Skevans case EfiPalCode: 440346482Skevans case EfiPersistentMemory: 441346482Skevans return (types[type]); 442346482Skevans default: 443346482Skevans return ("Unknown"); 444346482Skevans } 445346482Skevans} 446346482Skevans 447346482Skevans/* Print memory type table. */ 448346482Skevansstatic int 449346482Skevansefi_print_mem_type(const CHAR16 *varnamearg __unused, uint8_t *data, 450346482Skevans UINTN datasz) 451346482Skevans{ 452346482Skevans int i, n; 453346482Skevans EFI_MEMORY_TYPE_INFORMATION *ti; 454346482Skevans 455346482Skevans ti = (EFI_MEMORY_TYPE_INFORMATION *)data; 456346482Skevans if (pager_output(" = \n")) 457346482Skevans return (CMD_WARN); 458346482Skevans 459346482Skevans n = datasz / sizeof (EFI_MEMORY_TYPE_INFORMATION); 460346482Skevans for (i = 0; i < n && ti[i].NumberOfPages != 0; i++) { 461346482Skevans printf("\t%23s pages: %u", efi_memory_type(ti[i].Type), 462346482Skevans ti[i].NumberOfPages); 463346482Skevans if (pager_output("\n")) 464346482Skevans return (CMD_WARN); 465346482Skevans } 466346482Skevans 467346482Skevans return (CMD_OK); 468346482Skevans} 469346482Skevans 470346482Skevans/* 471346482Skevans * Print FreeBSD variables. 472346482Skevans * We have LoaderPath and LoaderDev as CHAR16 strings. 473346482Skevans */ 474346482Skevansstatic int 475346482Skevansefi_print_freebsd(const CHAR16 *varnamearg, uint8_t *data, 476346482Skevans UINTN datasz __unused) 477346482Skevans{ 478346482Skevans int rv = -1; 479346482Skevans char *var = NULL; 480346482Skevans 481346482Skevans if (ucs2_to_utf8(varnamearg, &var) != 0) 482346482Skevans return (CMD_ERROR); 483346482Skevans 484346482Skevans if (strcmp("LoaderPath", var) == 0 || 485346482Skevans strcmp("LoaderDev", var) == 0) { 486346482Skevans printf(" = "); 487346482Skevans printf("%S", (CHAR16 *)data); 488346482Skevans 489346482Skevans if (pager_output("\n")) 490346482Skevans rv = CMD_WARN; 491346482Skevans else 492346482Skevans rv = CMD_OK; 493346482Skevans } 494346482Skevans 495346482Skevans free(var); 496346482Skevans return (rv); 497346482Skevans} 498346482Skevans 499346482Skevans/* Print global variables. */ 500346482Skevansstatic int 501346482Skevansefi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz) 502346482Skevans{ 503346482Skevans int rv = -1; 504346482Skevans char *var = NULL; 505346482Skevans 506346482Skevans if (ucs2_to_utf8(varnamearg, &var) != 0) 507346482Skevans return (CMD_ERROR); 508346482Skevans 509346482Skevans if (strcmp("AuditMode", var) == 0) { 510346482Skevans printf(" = "); 511346482Skevans printf("0x%x", *data); /* 8-bit int */ 512346482Skevans goto done; 513346482Skevans } 514346482Skevans 515346482Skevans if (strcmp("BootOptionSupport", var) == 0) { 516346482Skevans printf(" = "); 517346482Skevans printf("0x%x", *((uint32_t *)data)); /* UINT32 */ 518346482Skevans goto done; 519346482Skevans } 520346482Skevans 521346482Skevans if (strcmp("BootCurrent", var) == 0 || 522346482Skevans strcmp("BootNext", var) == 0 || 523346482Skevans strcmp("Timeout", var) == 0) { 524346482Skevans printf(" = "); 525346482Skevans printf("%u", *((uint16_t *)data)); /* UINT16 */ 526346482Skevans goto done; 527346482Skevans } 528346482Skevans 529346482Skevans if (strcmp("BootOrder", var) == 0 || 530346482Skevans strcmp("DriverOrder", var) == 0) { 531346482Skevans UINTN i; 532346482Skevans UINT16 *u16 = (UINT16 *)data; 533346482Skevans 534346482Skevans printf(" ="); 535346482Skevans for (i = 0; i < datasz / sizeof (UINT16); i++) 536346482Skevans printf(" %u", u16[i]); 537346482Skevans goto done; 538346482Skevans } 539346482Skevans if (strncmp("Boot", var, 4) == 0 || 540346482Skevans strncmp("Driver", var, 5) == 0 || 541346482Skevans strncmp("SysPrep", var, 7) == 0 || 542346482Skevans strncmp("OsRecovery", var, 10) == 0) { 543346482Skevans UINT16 filepathlistlen; 544346482Skevans CHAR16 *text; 545346482Skevans int desclen; 546346482Skevans EFI_DEVICE_PATH *dp; 547346482Skevans 548346482Skevans data += sizeof(UINT32); 549346482Skevans filepathlistlen = *(uint16_t *)data; 550346482Skevans data += sizeof (UINT16); 551346482Skevans text = (CHAR16 *)data; 552346482Skevans 553346482Skevans for (desclen = 0; text[desclen] != 0; desclen++) 554346482Skevans ; 555346482Skevans if (desclen != 0) { 556346482Skevans /* Add terminating zero and we have CHAR16. */ 557346482Skevans desclen = (desclen + 1) * 2; 558346482Skevans } 559346482Skevans 560346482Skevans printf(" = "); 561346482Skevans printf("%S", text); 562346482Skevans if (filepathlistlen != 0) { 563346482Skevans /* Output pathname from new line. */ 564346482Skevans if (pager_output("\n")) { 565346482Skevans rv = CMD_WARN; 566346482Skevans goto done; 567346482Skevans } 568346482Skevans dp = malloc(filepathlistlen); 569346482Skevans if (dp == NULL) 570346482Skevans goto done; 571346482Skevans 572346482Skevans memcpy(dp, data + desclen, filepathlistlen); 573346482Skevans text = efi_devpath_name(dp); 574346482Skevans if (text != NULL) { 575346482Skevans printf("\t%S", text); 576346482Skevans efi_free_devpath_name(text); 577346482Skevans } 578346482Skevans free(dp); 579346482Skevans } 580346482Skevans goto done; 581346482Skevans } 582346482Skevans 583346482Skevans if (strcmp("ConIn", var) == 0 || 584346482Skevans strcmp("ConInDev", var) == 0 || 585346482Skevans strcmp("ConOut", var) == 0 || 586346482Skevans strcmp("ConOutDev", var) == 0 || 587346482Skevans strcmp("ErrOut", var) == 0 || 588346482Skevans strcmp("ErrOutDev", var) == 0) { 589346482Skevans CHAR16 *text; 590346482Skevans 591346482Skevans printf(" = "); 592346482Skevans text = efi_devpath_name((EFI_DEVICE_PATH *)data); 593346482Skevans if (text != NULL) { 594346482Skevans printf("%S", text); 595346482Skevans efi_free_devpath_name(text); 596346482Skevans } 597346482Skevans goto done; 598346482Skevans } 599346482Skevans 600346482Skevans if (strcmp("PlatformLang", var) == 0 || 601346482Skevans strcmp("PlatformLangCodes", var) == 0 || 602346482Skevans strcmp("LangCodes", var) == 0 || 603346482Skevans strcmp("Lang", var) == 0) { 604346482Skevans printf(" = "); 605346482Skevans printf("%s", data); /* ASCII string */ 606346482Skevans goto done; 607346482Skevans } 608346482Skevans 609346482Skevans /* 610346482Skevans * Feature bitmap from firmware to OS. 611346482Skevans * Older UEFI provides UINT32, newer UINT64. 612346482Skevans */ 613346482Skevans if (strcmp("OsIndicationsSupported", var) == 0) { 614346482Skevans printf(" = "); 615346482Skevans if (datasz == 4) 616346482Skevans printf("0x%x", *((uint32_t *)data)); 617346482Skevans else 618346482Skevans printf("0x%jx", *((uint64_t *)data)); 619346482Skevans goto done; 620346482Skevans } 621346482Skevans 622346482Skevans /* Fallback for anything else. */ 623346482Skevans rv = efi_print_other_value(data, datasz); 624346482Skevansdone: 625346482Skevans if (rv == -1) { 626346482Skevans if (pager_output("\n")) 627346482Skevans rv = CMD_WARN; 628346482Skevans else 629346482Skevans rv = CMD_OK; 630346482Skevans } 631346482Skevans free(var); 632346482Skevans return (rv); 633346482Skevans} 634346482Skevans 635346482Skevansstatic void 636346482Skevansefi_print_var_attr(UINT32 attr) 637346482Skevans{ 638346482Skevans bool comma = false; 639346482Skevans 640346482Skevans if (attr & EFI_VARIABLE_NON_VOLATILE) { 641346482Skevans printf("NV"); 642346482Skevans comma = true; 643346482Skevans } 644346482Skevans if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS) { 645346482Skevans if (comma == true) 646346482Skevans printf(","); 647346482Skevans printf("BS"); 648346482Skevans comma = true; 649346482Skevans } 650346482Skevans if (attr & EFI_VARIABLE_RUNTIME_ACCESS) { 651346482Skevans if (comma == true) 652346482Skevans printf(","); 653346482Skevans printf("RS"); 654346482Skevans comma = true; 655346482Skevans } 656346482Skevans if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 657346482Skevans if (comma == true) 658346482Skevans printf(","); 659346482Skevans printf("HR"); 660346482Skevans comma = true; 661346482Skevans } 662346482Skevans if (attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) { 663346482Skevans if (comma == true) 664346482Skevans printf(","); 665346482Skevans printf("AT"); 666346482Skevans comma = true; 667346482Skevans } 668346482Skevans} 669346482Skevans 670346482Skevansstatic int 671329099Skevansefi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag) 672329099Skevans{ 673346482Skevans UINTN datasz; 674329099Skevans EFI_STATUS status; 675329099Skevans UINT32 attr; 676329099Skevans char *str; 677346482Skevans uint8_t *data; 678346482Skevans int rv = CMD_OK; 679329099Skevans 680346482Skevans str = NULL; 681329099Skevans datasz = 0; 682346482Skevans status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, NULL); 683329099Skevans if (status != EFI_BUFFER_TOO_SMALL) { 684329099Skevans printf("Can't get the variable: error %#lx\n", 685329099Skevans EFI_ERROR_CODE(status)); 686329099Skevans return (CMD_ERROR); 687329099Skevans } 688329099Skevans data = malloc(datasz); 689346482Skevans if (data == NULL) { 690346482Skevans printf("Out of memory\n"); 691346482Skevans return (CMD_ERROR); 692346482Skevans } 693346482Skevans 694346482Skevans status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, data); 695329099Skevans if (status != EFI_SUCCESS) { 696329099Skevans printf("Can't get the variable: error %#lx\n", 697329099Skevans EFI_ERROR_CODE(status)); 698346482Skevans free(data); 699329099Skevans return (CMD_ERROR); 700329099Skevans } 701346482Skevans 702346482Skevans if (efi_guid_to_name(matchguid, &str) == false) { 703346482Skevans rv = CMD_ERROR; 704346482Skevans goto done; 705329099Skevans } 706346482Skevans printf("%s ", str); 707346482Skevans efi_print_var_attr(attr); 708346482Skevans printf(" %S", varnamearg); 709346482Skevans 710346482Skevans if (lflag == 0) { 711346482Skevans if (strcmp(str, "global") == 0) 712346482Skevans rv = efi_print_global(varnamearg, data, datasz); 713346482Skevans else if (strcmp(str, "freebsd") == 0) 714346482Skevans rv = efi_print_freebsd(varnamearg, data, datasz); 715346482Skevans else if (strcmp(str, 716346482Skevans EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0) 717346482Skevans rv = efi_print_mem_type(varnamearg, data, datasz); 718346482Skevans else if (strcmp(str, 719346482Skevans "47c7b227-c42a-11d2-8e57-00a0c969723b") == 0) 720346482Skevans rv = efi_print_shell_str(varnamearg, data, datasz); 721346482Skevans else if (strcmp(str, MTC_VARIABLE_NAME) == 0) { 722346482Skevans printf(" = "); 723346482Skevans printf("%u", *((uint32_t *)data)); /* UINT32 */ 724346482Skevans rv = CMD_OK; 725346482Skevans if (pager_output("\n")) 726346482Skevans rv = CMD_WARN; 727346482Skevans } else 728346482Skevans rv = efi_print_other_value(data, datasz); 729346482Skevans } else if (pager_output("\n")) 730346482Skevans rv = CMD_WARN; 731346482Skevans 732346482Skevansdone: 733346482Skevans free(str); 734329099Skevans free(data); 735346482Skevans return (rv); 736329099Skevans} 737329099Skevans 738329099Skevansstatic int 739329099Skevanscommand_efi_show(int argc, char *argv[]) 740329099Skevans{ 741329099Skevans /* 742329099Skevans * efi-show [-a] 743329099Skevans * print all the env 744346472Skevans * efi-show -g UUID 745329099Skevans * print all the env vars tagged with UUID 746329099Skevans * efi-show -v var 747329099Skevans * search all the env vars and print the ones matching var 748346472Skevans * efi-show -g UUID -v var 749346472Skevans * efi-show UUID var 750329099Skevans * print all the env vars that match UUID and var 751329099Skevans */ 752329099Skevans /* NB: We assume EFI_GUID is the same as uuid_t */ 753329099Skevans int aflag = 0, gflag = 0, lflag = 0, vflag = 0; 754329099Skevans int ch, rv; 755329099Skevans unsigned i; 756329099Skevans EFI_STATUS status; 757346482Skevans EFI_GUID varguid = ZERO_GUID; 758346482Skevans EFI_GUID matchguid = ZERO_GUID; 759329099Skevans CHAR16 *varname; 760329099Skevans CHAR16 *newnm; 761329099Skevans CHAR16 varnamearg[128]; 762329099Skevans UINTN varalloc; 763329099Skevans UINTN varsz; 764329099Skevans 765346482Skevans optind = 1; 766346482Skevans optreset = 1; 767346482Skevans opterr = 1; 768346482Skevans 769329099Skevans while ((ch = getopt(argc, argv, "ag:lv:")) != -1) { 770329099Skevans switch (ch) { 771329099Skevans case 'a': 772329099Skevans aflag = 1; 773329099Skevans break; 774329099Skevans case 'g': 775329099Skevans gflag = 1; 776346482Skevans if (efi_name_to_guid(optarg, &matchguid) == false) { 777346482Skevans printf("uuid %s could not be parsed\n", optarg); 778329099Skevans return (CMD_ERROR); 779329099Skevans } 780329099Skevans break; 781329099Skevans case 'l': 782329099Skevans lflag = 1; 783329099Skevans break; 784329099Skevans case 'v': 785329099Skevans vflag = 1; 786329099Skevans if (strlen(optarg) >= nitems(varnamearg)) { 787346482Skevans printf("Variable %s is longer than %zu " 788346482Skevans "characters\n", optarg, nitems(varnamearg)); 789329099Skevans return (CMD_ERROR); 790329099Skevans } 791346482Skevans cpy8to16(optarg, varnamearg, nitems(varnamearg)); 792329099Skevans break; 793329099Skevans default: 794329099Skevans return (CMD_ERROR); 795329099Skevans } 796329099Skevans } 797329099Skevans 798346482Skevans if (argc == 1) /* default is -a */ 799346482Skevans aflag = 1; 800346482Skevans 801329099Skevans if (aflag && (gflag || vflag)) { 802346482Skevans printf("-a isn't compatible with -g or -v\n"); 803329099Skevans return (CMD_ERROR); 804329099Skevans } 805329099Skevans 806329099Skevans if (aflag && optind < argc) { 807329099Skevans printf("-a doesn't take any args\n"); 808329099Skevans return (CMD_ERROR); 809329099Skevans } 810329099Skevans 811329099Skevans argc -= optind; 812329099Skevans argv += optind; 813329099Skevans 814329099Skevans pager_open(); 815329099Skevans if (vflag && gflag) { 816329099Skevans rv = efi_print_var(varnamearg, &matchguid, lflag); 817346482Skevans if (rv == CMD_WARN) 818346482Skevans rv = CMD_OK; 819329099Skevans pager_close(); 820329099Skevans return (rv); 821329099Skevans } 822329099Skevans 823329099Skevans if (argc == 2) { 824329099Skevans optarg = argv[0]; 825329099Skevans if (strlen(optarg) >= nitems(varnamearg)) { 826346482Skevans printf("Variable %s is longer than %zu characters\n", 827329099Skevans optarg, nitems(varnamearg)); 828329099Skevans pager_close(); 829329099Skevans return (CMD_ERROR); 830329099Skevans } 831329099Skevans for (i = 0; i < strlen(optarg); i++) 832329099Skevans varnamearg[i] = optarg[i]; 833329099Skevans varnamearg[i] = 0; 834329099Skevans optarg = argv[1]; 835346482Skevans if (efi_name_to_guid(optarg, &matchguid) == false) { 836346482Skevans printf("uuid %s could not be parsed\n", optarg); 837329099Skevans pager_close(); 838329099Skevans return (CMD_ERROR); 839329099Skevans } 840329099Skevans rv = efi_print_var(varnamearg, &matchguid, lflag); 841346482Skevans if (rv == CMD_WARN) 842346482Skevans rv = CMD_OK; 843329099Skevans pager_close(); 844329099Skevans return (rv); 845329099Skevans } 846329099Skevans 847329099Skevans if (argc > 0) { 848346482Skevans printf("Too many args: %d\n", argc); 849329099Skevans pager_close(); 850329099Skevans return (CMD_ERROR); 851329099Skevans } 852329099Skevans 853329099Skevans /* 854329099Skevans * Initiate the search -- note the standard takes pain 855329099Skevans * to specify the initial call must be a poiner to a NULL 856329099Skevans * character. 857329099Skevans */ 858329099Skevans varalloc = 1024; 859329099Skevans varname = malloc(varalloc); 860329099Skevans if (varname == NULL) { 861329099Skevans printf("Can't allocate memory to get variables\n"); 862329099Skevans pager_close(); 863329099Skevans return (CMD_ERROR); 864329099Skevans } 865329099Skevans varname[0] = 0; 866329099Skevans while (1) { 867329099Skevans varsz = varalloc; 868329099Skevans status = RS->GetNextVariableName(&varsz, varname, &varguid); 869329099Skevans if (status == EFI_BUFFER_TOO_SMALL) { 870329099Skevans varalloc = varsz; 871329099Skevans newnm = realloc(varname, varalloc); 872329099Skevans if (newnm == NULL) { 873346482Skevans printf("Can't allocate memory to get " 874346482Skevans "variables\n"); 875346482Skevans rv = CMD_ERROR; 876346482Skevans break; 877329099Skevans } 878329099Skevans varname = newnm; 879329099Skevans continue; /* Try again with bigger buffer */ 880329099Skevans } 881346482Skevans if (status == EFI_NOT_FOUND) { 882346482Skevans rv = CMD_OK; 883329099Skevans break; 884346482Skevans } 885346482Skevans if (status != EFI_SUCCESS) { 886346482Skevans rv = CMD_ERROR; 887346482Skevans break; 888346482Skevans } 889346482Skevans 890329099Skevans if (aflag) { 891346482Skevans rv = efi_print_var(varname, &varguid, lflag); 892346482Skevans if (rv != CMD_OK) { 893346482Skevans if (rv == CMD_WARN) 894346482Skevans rv = CMD_OK; 895329099Skevans break; 896346482Skevans } 897329099Skevans continue; 898329099Skevans } 899329099Skevans if (vflag) { 900329099Skevans if (wcscmp(varnamearg, varname) == 0) { 901346482Skevans rv = efi_print_var(varname, &varguid, lflag); 902346482Skevans if (rv != CMD_OK) { 903346482Skevans if (rv == CMD_WARN) 904346482Skevans rv = CMD_OK; 905329099Skevans break; 906346482Skevans } 907329099Skevans continue; 908329099Skevans } 909329099Skevans } 910329099Skevans if (gflag) { 911346482Skevans rv = uuid_equal((uuid_t *)&varguid, 912346482Skevans (uuid_t *)&matchguid, NULL); 913346482Skevans if (rv != 0) { 914346482Skevans rv = efi_print_var(varname, &varguid, lflag); 915346482Skevans if (rv != CMD_OK) { 916346482Skevans if (rv == CMD_WARN) 917346482Skevans rv = CMD_OK; 918329099Skevans break; 919346482Skevans } 920329099Skevans continue; 921329099Skevans } 922329099Skevans } 923329099Skevans } 924329099Skevans free(varname); 925329099Skevans pager_close(); 926329099Skevans 927346482Skevans return (rv); 928329099Skevans} 929329099Skevans 930329099SkevansCOMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set); 931329099Skevans 932329099Skevansstatic int 933329099Skevanscommand_efi_set(int argc, char *argv[]) 934329099Skevans{ 935329099Skevans char *uuid, *var, *val; 936329099Skevans CHAR16 wvar[128]; 937329099Skevans EFI_GUID guid; 938346482Skevans#if defined(ENABLE_UPDATES) 939329099Skevans EFI_STATUS err; 940346482Skevans#endif 941329099Skevans 942329099Skevans if (argc != 4) { 943329099Skevans printf("efi-set uuid var new-value\n"); 944329099Skevans return (CMD_ERROR); 945329099Skevans } 946329099Skevans uuid = argv[1]; 947329099Skevans var = argv[2]; 948329099Skevans val = argv[3]; 949346482Skevans if (efi_name_to_guid(uuid, &guid) == false) { 950346482Skevans printf("Invalid uuid %s\n", uuid); 951329099Skevans return (CMD_ERROR); 952329099Skevans } 953346482Skevans cpy8to16(var, wvar, nitems(wvar)); 954346482Skevans#if defined(ENABLE_UPDATES) 955346482Skevans err = RS->SetVariable(wvar, &guid, EFI_VARIABLE_NON_VOLATILE | 956346482Skevans EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, 957329099Skevans strlen(val) + 1, val); 958329099Skevans if (EFI_ERROR(err)) { 959346482Skevans printf("Failed to set variable: error %lu\n", 960346482Skevans EFI_ERROR_CODE(err)); 961329099Skevans return (CMD_ERROR); 962329099Skevans } 963346482Skevans#else 964346482Skevans printf("would set %s %s = %s\n", uuid, var, val); 965346482Skevans#endif 966329099Skevans return (CMD_OK); 967329099Skevans} 968329099Skevans 969329099SkevansCOMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", command_efi_unset); 970329099Skevans 971329099Skevansstatic int 972329099Skevanscommand_efi_unset(int argc, char *argv[]) 973329099Skevans{ 974329099Skevans char *uuid, *var; 975329099Skevans CHAR16 wvar[128]; 976329099Skevans EFI_GUID guid; 977346482Skevans#if defined(ENABLE_UPDATES) 978329099Skevans EFI_STATUS err; 979346482Skevans#endif 980329099Skevans 981329099Skevans if (argc != 3) { 982329099Skevans printf("efi-unset uuid var\n"); 983329099Skevans return (CMD_ERROR); 984329099Skevans } 985329099Skevans uuid = argv[1]; 986329099Skevans var = argv[2]; 987346482Skevans if (efi_name_to_guid(uuid, &guid) == false) { 988329099Skevans printf("Invalid uuid %s\n", uuid); 989329099Skevans return (CMD_ERROR); 990329099Skevans } 991346482Skevans cpy8to16(var, wvar, nitems(wvar)); 992346482Skevans#if defined(ENABLE_UPDATES) 993329099Skevans err = RS->SetVariable(wvar, &guid, 0, 0, NULL); 994329099Skevans if (EFI_ERROR(err)) { 995346482Skevans printf("Failed to unset variable: error %lu\n", 996346482Skevans EFI_ERROR_CODE(err)); 997329099Skevans return (CMD_ERROR); 998329099Skevans } 999346482Skevans#else 1000346482Skevans printf("would unset %s %s \n", uuid, var); 1001346482Skevans#endif 1002329099Skevans return (CMD_OK); 1003329099Skevans} 1004