1 /* 2 * Copyright (c) 2015 Netflix, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 28 #include <stand.h> 29 #include <string.h> 30 #include <efi.h> 31 #include <efichar.h> 32 #include <efilib.h> 33 #include <eficonsctl.h> 34 #include <Guid/Acpi.h> 35 #include <Guid/ConsoleInDevice.h> 36 #include <Guid/ConsoleOutDevice.h> 37 #include <Guid/DebugImageInfoTable.h> 38 #include <Guid/DxeServices.h> 39 #include <Guid/Fdt.h> 40 #include <Guid/GlobalVariable.h> 41 #include <Guid/Gpt.h> 42 #include <Guid/HobList.h> 43 #include <Guid/MemoryTypeInformation.h> 44 #include <Guid/Mps.h> 45 #include <Guid/MtcVendor.h> 46 #include <Guid/SmBios.h> 47 #include <Guid/StandardErrorDevice.h> 48 #include <Guid/ZeroGuid.h> 49 #include <Pi/PiStatusCode.h> 50 #include <Protocol/AbsolutePointer.h> 51 #include <Protocol/AdapterInformation.h> 52 #include <Protocol/Arp.h> 53 #include <Protocol/AtaPassThru.h> 54 #include <Protocol/Bds.h> 55 #include <Protocol/BlockIo.h> 56 #include <Protocol/BlockIo2.h> 57 #include <Protocol/BusSpecificDriverOverride.h> 58 #include <Protocol/Capsule.h> 59 #include <Protocol/ComponentName.h> 60 #include <Protocol/ComponentName2.h> 61 #include <Protocol/Cpu.h> 62 #include <Protocol/CpuIo2.h> 63 #include <Protocol/DataHub.h> 64 #include <Protocol/Decompress.h> 65 #include <Protocol/DeviceIo.h> 66 #include <Protocol/DevicePath.h> 67 #include <Protocol/DevicePathFromText.h> 68 #include <Protocol/DevicePathToText.h> 69 #include <Protocol/DevicePathUtilities.h> 70 #include <Protocol/Dhcp4.h> 71 #include <Protocol/Dhcp6.h> 72 #include <Protocol/DiskInfo.h> 73 #include <Protocol/DiskIo.h> 74 #include <Protocol/DiskIo2.h> 75 #include <Protocol/Dpc.h> 76 #include <Protocol/DriverBinding.h> 77 #include <Protocol/DriverConfiguration.h> 78 #include <Protocol/DriverConfiguration2.h> 79 #include <Protocol/DriverDiagnostics.h> 80 #include <Protocol/DriverDiagnostics2.h> 81 #include <Protocol/DriverFamilyOverride.h> 82 #include <Protocol/DriverHealth.h> 83 #include <Protocol/DriverSupportedEfiVersion.h> 84 #include <Protocol/Ebc.h> 85 #include <Protocol/EdidActive.h> 86 #include <Protocol/EdidDiscovered.h> 87 #include <Pi/PiFirmwareVolume.h> 88 #include <Protocol/FirmwareVolumeBlock.h> 89 #include <Uefi/UefiInternalFormRepresentation.h> 90 #include <Protocol/FormBrowser2.h> 91 #include <Protocol/GraphicsOutput.h> 92 #include <Protocol/HiiConfigAccess.h> 93 #include <Protocol/HiiConfigKeyword.h> 94 #include <Protocol/HiiConfigRouting.h> 95 #include <Protocol/HiiFont.h> 96 #include <Protocol/HiiImage.h> 97 #include <Protocol/HiiDatabase.h> 98 #include <Protocol/HiiString.h> 99 #include <Protocol/IdeControllerInit.h> 100 #include <Protocol/Ip4.h> 101 #include <Protocol/Ip4Config.h> 102 #include <Protocol/Ip4Config2.h> 103 #include <Protocol/Ip6.h> 104 #include <Protocol/Ip6Config.h> 105 #include <Protocol/IpSec.h> 106 #include <Protocol/IpSecConfig.h> 107 #include <Protocol/IsaAcpi.h> 108 #include <Protocol/IsaIo.h> 109 #include <Protocol/Kms.h> 110 #include <Protocol/Legacy8259.h> 111 #include <Protocol/LoadFile.h> 112 #include <Protocol/LoadFile2.h> 113 #include <Protocol/Metronome.h> 114 #include <Protocol/MonotonicCounter.h> 115 #include <Pi/PiMultiPhase.h> 116 #include <Protocol/MpService.h> 117 #include <Protocol/Mtftp4.h> 118 #include <Protocol/Mtftp6.h> 119 #include <Protocol/NetworkInterfaceIdentifier.h> 120 #include <Protocol/NvmExpressPassthru.h> 121 #include <Protocol/PciIo.h> 122 #include <Protocol/Pcd.h> 123 #include <Protocol/PciEnumerationComplete.h> 124 #include <Protocol/PciRootBridgeIo.h> 125 #include <Protocol/PiPcd.h> 126 #include <Protocol/PlatformDriverOverride.h> 127 #include <Protocol/PlatformToDriverConfiguration.h> 128 #include <Protocol/Print2.h> 129 #include <Protocol/PxeBaseCode.h> 130 #include <Protocol/PxeBaseCodeCallBack.h> 131 #include <Protocol/RealTimeClock.h> 132 #include <Protocol/ReportStatusCodeHandler.h> 133 #include <Protocol/Reset.h> 134 #include <Protocol/Rng.h> 135 #include <Protocol/Runtime.h> 136 #include <Protocol/ScsiIo.h> 137 #include <Protocol/ScsiPassThru.h> 138 #include <Protocol/ScsiPassThruExt.h> 139 #include <Protocol/Security.h> 140 #include <Protocol/Security2.h> 141 #include <Protocol/SecurityPolicy.h> 142 #include <Protocol/SerialIo.h> 143 #include <Protocol/SimpleFileSystem.h> 144 #include <Protocol/SimplePointer.h> 145 #include <Protocol/SimpleTextIn.h> 146 #include <Protocol/SimpleTextInEx.h> 147 #include <Protocol/SimpleTextOut.h> 148 #include <Protocol/SmartCardReader.h> 149 #include <Protocol/StatusCode.h> 150 #include <Protocol/StorageSecurityCommand.h> 151 #include <Protocol/Tcg2Protocol.h> 152 #include <Protocol/Tcp4.h> 153 #include <Protocol/Tcp6.h> 154 #include <Protocol/Timer.h> 155 #include <Protocol/Udp4.h> 156 #include <Protocol/Udp6.h> 157 #include <Protocol/UgaDraw.h> 158 #include <Protocol/UgaIo.h> 159 #include <Protocol/UnicodeCollation.h> 160 #include <Protocol/UsbIo.h> 161 #include <Protocol/Usb2HostController.h> 162 #include <Protocol/Variable.h> 163 #include <Protocol/VariableWrite.h> 164 #include <Protocol/VlanConfig.h> 165 #include <Protocol/WatchdogTimer.h> 166 #include <uuid.h> 167 #include <stdbool.h> 168 #include <sys/param.h> 169 #include "bootstrap.h" 170 #include "ficl.h" 171 172 /* 173 * About ENABLE_UPDATES 174 * 175 * The UEFI variables are identified only by GUID and name, there is no 176 * way to (auto)detect the type for the value, so we need to process the 177 * variables case by case, as we do learn about them. 178 * 179 * While showing the variable name and the value is safe, we must not store 180 * random values nor allow removing (random) variables. 181 * 182 * Since we do have stub code to set/unset the variables, I do want to keep 183 * it to make the future development a bit easier, but the updates are disabled 184 * by default till: 185 * a) the validation and data translation to values is properly implemented 186 * b) We have established which variables we do allow to be updated. 187 * Therefore the set/unset code is included only for developers aid. 188 */ 189 190 /* If GUID is not defined elsewhere, define it here. */ 191 EFI_GUID gEfiAbsolutePointerProtocolGuid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID; 192 EFI_GUID gEfiAdapterInformationProtocolGuid = 193 EFI_ADAPTER_INFORMATION_PROTOCOL_GUID; 194 EFI_GUID gEfiAtaPassThruProtocolGuid = EFI_ATA_PASS_THRU_PROTOCOL_GUID; 195 EFI_GUID gEfiBdsArchProtocolGuid = EFI_BDS_ARCH_PROTOCOL_GUID; 196 EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid = 197 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID; 198 EFI_GUID gEfiCapsuleArchProtocolGuid = EFI_CAPSULE_ARCH_PROTOCOL_GUID; 199 EFI_GUID gEfiComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; 200 EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; 201 EFI_GUID gEfiCpuArchProtocolGuid = EFI_CPU_ARCH_PROTOCOL_GUID; 202 EFI_GUID gEfiCpuIo2ProtocolGuid = EFI_CPU_IO2_PROTOCOL_GUID; 203 EFI_GUID gEfiDataHubProtocolGuid = EFI_DATA_HUB_PROTOCOL_GUID; 204 EFI_GUID gEfiDebugImageInfoTableGuid = EFI_DEBUG_IMAGE_INFO_TABLE_GUID; 205 EFI_GUID gEfiDecompressProtocolGuid = EFI_DECOMPRESS_PROTOCOL_GUID; 206 EFI_GUID gEfiDeviceIoProtocolGuid = EFI_DEVICE_IO_PROTOCOL_GUID; 207 EFI_GUID gEfiDhcp4ProtocolGuid = EFI_DHCP4_PROTOCOL_GUID; 208 EFI_GUID gEfiDhcp4ServiceBindingProtocolGuid = 209 EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID; 210 EFI_GUID gEfiDhcp6ProtocolGuid = EFI_DHCP4_PROTOCOL_GUID; 211 EFI_GUID gEfiDhcp6ServiceBindingProtocolGuid = 212 EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID; 213 EFI_GUID gEfiDiskInfoProtocolGuid = EFI_DISK_INFO_PROTOCOL_GUID; 214 EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID; 215 EFI_GUID gEfiDiskIo2ProtocolGuid = EFI_DISK_IO2_PROTOCOL_GUID; 216 EFI_GUID gEfiDpcProtocolGuid = EFI_DPC_PROTOCOL_GUID; 217 EFI_GUID gEfiDriverConfigurationProtocolGuid = 218 EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID; 219 EFI_GUID gEfiDriverConfiguration2ProtocolGuid = 220 EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID; 221 EFI_GUID gEfiDriverDiagnosticsProtocolGuid = 222 EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID; 223 EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = 224 EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID; 225 EFI_GUID gEfiDriverFamilyOverrideProtocolGuid = 226 EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID; 227 EFI_GUID gEfiDriverHealthProtocolGuid = 228 EFI_DRIVER_HEALTH_PROTOCOL_GUID; 229 EFI_GUID gEfiDriverSupportedEfiVersionProtocolGuid = 230 EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL_GUID; 231 EFI_GUID gEfiDxeServicesTableGuid = DXE_SERVICES_TABLE_GUID; 232 EFI_GUID gEfiEbcProtocolGuid = EFI_EBC_INTERPRETER_PROTOCOL_GUID; 233 EFI_GUID gEfiFormBrowser2ProtocolGuid = EFI_FORM_BROWSER2_PROTOCOL_GUID; 234 EFI_GUID gEfiFirmwareVolumeBlockProtocolGuid = 235 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID; 236 EFI_GUID gEfiFirmwareVolumeBlock2ProtocolGuid = 237 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL_GUID; 238 EFI_GUID gEfiHiiConfigAccessProtocolGuid = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; 239 EFI_GUID gEfiConfigKeywordHandlerProtocolGuid = 240 EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL_GUID; 241 EFI_GUID gEfiHiiConfigRoutingProtocolGuid = 242 EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID; 243 EFI_GUID gEfiHiiFontProtocolGuid = EFI_HII_FONT_PROTOCOL_GUID; 244 EFI_GUID gEfiHiiImageProtocolGuid = EFI_HII_IMAGE_PROTOCOL_GUID; 245 EFI_GUID gEfiHiiStringProtocolGuid = EFI_HII_STRING_PROTOCOL_GUID; 246 EFI_GUID gEfiHiiDatabaseProtocolGuid = EFI_HII_DATABASE_PROTOCOL_GUID; 247 EFI_GUID gEfiHobListGuid = HOB_LIST_GUID; 248 EFI_GUID gEfiIdeControllerInitProtocolGuid = 249 EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID; 250 EFI_GUID gEfiIp4ProtocolGuid = EFI_IP4_PROTOCOL_GUID; 251 EFI_GUID gEfiIp4ServiceBindingProtocolGuid = 252 EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID; 253 EFI_GUID gEfiIp4ConfigProtocolGuid = EFI_IP4_CONFIG_PROTOCOL_GUID; 254 EFI_GUID gEfiIp4Config2ProtocolGuid = EFI_IP4_CONFIG2_PROTOCOL_GUID; 255 EFI_GUID gEfiIp6ProtocolGuid = EFI_IP6_PROTOCOL_GUID; 256 EFI_GUID gEfiIp6ServiceBindingProtocolGuid = 257 EFI_IP6_SERVICE_BINDING_PROTOCOL_GUID; 258 EFI_GUID gEfiIp6ConfigProtocolGuid = EFI_IP6_CONFIG_PROTOCOL_GUID; 259 EFI_GUID gEfiIpSecProtocolGuid = EFI_IPSEC_PROTOCOL_GUID; 260 EFI_GUID gEfiIpSec2ProtocolGuid = EFI_IPSEC2_PROTOCOL_GUID; 261 EFI_GUID gEfiIpSecConfigProtocolGuid = EFI_IPSEC_CONFIG_PROTOCOL_GUID; 262 EFI_GUID gEfiIsaAcpiProtocolGuid = EFI_ISA_ACPI_PROTOCOL_GUID; 263 EFI_GUID gEfiIsaIoProtocolGuid = EFI_ISA_IO_PROTOCOL_GUID; 264 EFI_GUID gEfiKmsProtocolGuid = EFI_KMS_PROTOCOL_GUID; 265 EFI_GUID gEfiLegacy8259ProtocolGuid = EFI_LEGACY_8259_PROTOCOL_GUID; 266 EFI_GUID gEfiLoadFileProtocolGuid = EFI_LOAD_FILE_PROTOCOL_GUID; 267 EFI_GUID gEfiLoadFile2ProtocolGuid = EFI_LOAD_FILE2_PROTOCOL_GUID; 268 EFI_GUID gEfiManagedNetworkProtocolGuid = EFI_MANAGED_NETWORK_PROTOCOL_GUID; 269 EFI_GUID gEfiManagedNetworkServiceBindingProtocolGuid = 270 EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID; 271 EFI_GUID gEfiMemoryTypeInformationGuid = EFI_MEMORY_TYPE_INFORMATION_GUID; 272 EFI_GUID gEfiMetronomeArchProtocolGuid = EFI_METRONOME_ARCH_PROTOCOL_GUID; 273 EFI_GUID gEfiMonotonicCounterArchProtocolGuid = 274 EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID; 275 EFI_GUID gEfiMpServiceProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID; 276 EFI_GUID gEfiMpsTableGuid = MPS_TABLE_GUID; 277 EFI_GUID gEfiMtftp4ProtocolGuid = EFI_MTFTP4_PROTOCOL_GUID; 278 EFI_GUID gEfiMtftp4ServiceBindingProtocolGuid = 279 EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID; 280 EFI_GUID gEfiMtftp6ProtocolGuid = EFI_MTFTP6_PROTOCOL_GUID; 281 EFI_GUID gEfiMtftp6ServiceBindingProtocolGuid = 282 EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID; 283 EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid = 284 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID; 285 EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid_31 = 286 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31; 287 EFI_GUID gEfiNvmExpressPassThruProtocolGuid = 288 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL_GUID; 289 EFI_GUID gEfiPartTypeLegacyMbrGuid = EFI_PART_TYPE_LEGACY_MBR_GUID; 290 EFI_GUID gEfiPartTypeSystemPartGuid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID; 291 EFI_GUID gEfiPcdProtocolGuid = EFI_PCD_PROTOCOL_GUID; 292 EFI_GUID gEfiPciEnumerationCompleteProtocolGuid = 293 EFI_PCI_ENUMERATION_COMPLETE_GUID; 294 EFI_GUID gEfiPciRootBridgeIoProtocolGuid = 295 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; 296 EFI_GUID gEfiPlatformDriverOverrideProtocolGuid = 297 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID; 298 EFI_GUID gEfiPlatformToDriverConfigurationProtocolGuid = 299 EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL_GUID; 300 EFI_GUID gEfiPrint2SProtocolGuid = EFI_PRINT2_PROTOCOL_GUID; 301 EFI_GUID gEfiPxeBaseCodeProtocolGuid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; 302 EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid = 303 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID; 304 EFI_GUID gEfiRealTimeClockArchProtocolGuid = 305 EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID; 306 EFI_GUID gEfiResetArchProtocolGuid = EFI_RESET_ARCH_PROTOCOL_GUID; 307 EFI_GUID gEfiRngProtocolGuid = EFI_RNG_PROTOCOL_GUID; 308 EFI_GUID gEfiRuntimeArchProtocolGuid = EFI_RUNTIME_ARCH_PROTOCOL_GUID; 309 EFI_GUID gEfiScsiIoProtocolGuid = EFI_SCSI_IO_PROTOCOL_GUID; 310 EFI_GUID gEfiScsiPassThruProtocolGuid = EFI_SCSI_PASS_THRU_PROTOCOL_GUID; 311 EFI_GUID gEfiExtScsiPassThruProtocolGuid = 312 EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID; 313 EFI_GUID gEfiSecurityArchProtocolGuid = EFI_SECURITY_ARCH_PROTOCOL_GUID; 314 EFI_GUID gEfiSecurity2ArchProtocolGuid = EFI_SECURITY2_ARCH_PROTOCOL_GUID; 315 EFI_GUID gEfiSecurityPolicyProtocolGuid = EFI_SECURITY_POLICY_PROTOCOL_GUID; 316 EFI_GUID gEfiSimpleFileSystemProtocolGuid = 317 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; 318 EFI_GUID gEfiSimplePointerProtocolGuid = EFI_SIMPLE_POINTER_PROTOCOL_GUID; 319 EFI_GUID gEfiSmartCardReaderProtocolGuid = EFI_SMART_CARD_READER_PROTOCOL_GUID; 320 EFI_GUID gEfiStatusCodeRuntimeProtocolGuid = 321 EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID; 322 EFI_GUID gEfiStorageSecurityCommandProtocolGuid = 323 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL_GUID; 324 EFI_GUID gEfiTcg2ProtocolGuid = EFI_TCG2_PROTOCOL_GUID; 325 EFI_GUID gEfiTcp4ProtocolGuid = EFI_TCP4_PROTOCOL_GUID; 326 EFI_GUID gEfiTcp4ServiceBindingProtocolGuid = 327 EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID; 328 EFI_GUID gEfiTcp6ProtocolGuid = EFI_TCP6_PROTOCOL_GUID; 329 EFI_GUID gEfiTcp6ServiceBindingProtocolGuid = 330 EFI_TCP6_SERVICE_BINDING_PROTOCOL_GUID; 331 EFI_GUID gEfiTimerArchProtocolGuid = EFI_TIMER_ARCH_PROTOCOL_GUID; 332 EFI_GUID gEfiUdp4ProtocolGuid = EFI_UDP4_PROTOCOL_GUID; 333 EFI_GUID gEfiUdp4ServiceBindingProtocolGuid = 334 EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID; 335 EFI_GUID gEfiUdp6ProtocolGuid = EFI_UDP6_PROTOCOL_GUID; 336 EFI_GUID gEfiUdp6ServiceBindingProtocolGuid = 337 EFI_UDP6_SERVICE_BINDING_PROTOCOL_GUID; 338 EFI_GUID gEfiUnicodeCollationProtocolGuid = EFI_UNICODE_COLLATION_PROTOCOL_GUID; 339 EFI_GUID gEfiUnicodeCollation2ProtocolGuid = 340 EFI_UNICODE_COLLATION_PROTOCOL2_GUID; 341 EFI_GUID gEfiUsbIoProtocolGuid = EFI_USB_IO_PROTOCOL_GUID; 342 EFI_GUID gEfiUsb2HcProtocolGuid = EFI_USB2_HC_PROTOCOL_GUID; 343 EFI_GUID gEfiVariableArchProtocolGuid = EFI_VARIABLE_ARCH_PROTOCOL_GUID; 344 EFI_GUID gEfiVariableWriteArchProtocolGuid = 345 EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID; 346 EFI_GUID gEfiWatchdogTimerArchProtocolGuid = 347 EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID; 348 EFI_GUID gFdtTableGuid = FDT_TABLE_GUID; 349 EFI_GUID gLzmaCompress = LZMA_COMPRESS_GUID; 350 EFI_GUID gMtcVendorGuid = MTC_VENDOR_GUID; 351 EFI_GUID gPcdProtocolGuid = PCD_PROTOCOL_GUID; 352 EFI_GUID gEfiSerialIoProtocolGuid = EFI_SERIAL_IO_PROTOCOL_GUID; 353 EFI_GUID gEfiSerialTerminalDeviceTypeGuid = 354 EFI_SERIAL_TERMINAL_DEVICE_TYPE_GUID; 355 356 static struct efi_uuid_mapping { 357 const char *efi_guid_name; 358 EFI_GUID *efi_guid; 359 } efi_uuid_mapping[] = { 360 { .efi_guid_name = "global", 361 .efi_guid = &gEfiGlobalVariableGuid }, 362 { .efi_guid_name = "illumos", 363 .efi_guid = &gillumosBootVarGuid }, 364 /* EFI Systab entry names. */ 365 { .efi_guid_name = "MPS Table", 366 .efi_guid = &gEfiMpsTableGuid }, 367 { .efi_guid_name = "ACPI Table", 368 .efi_guid = &gEfiAcpiTableGuid }, 369 { .efi_guid_name = "ACPI 2.0 Table", 370 .efi_guid = &gEfiAcpi20TableGuid }, 371 { .efi_guid_name = "ATA pass thru", 372 .efi_guid = &gEfiAtaPassThruProtocolGuid }, 373 { .efi_guid_name = "SMBIOS Table", 374 .efi_guid = &gEfiSmbiosTableGuid }, 375 { .efi_guid_name = "SMBIOS3 Table", 376 .efi_guid = &gEfiSmbios3TableGuid }, 377 { .efi_guid_name = "DXE Table", 378 .efi_guid = &gEfiDxeServicesTableGuid }, 379 { .efi_guid_name = "HOB List Table", 380 .efi_guid = &gEfiHobListGuid }, 381 { .efi_guid_name = EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, 382 .efi_guid = &gEfiMemoryTypeInformationGuid }, 383 { .efi_guid_name = "Debug Image Info Table", 384 .efi_guid = &gEfiDebugImageInfoTableGuid }, 385 { .efi_guid_name = "FDT Table", 386 .efi_guid = &gFdtTableGuid }, 387 /* 388 * Protocol names for debug purposes. 389 * Can be removed along with lsefi command. 390 */ 391 { .efi_guid_name = "absolute pointer", 392 .efi_guid = &gEfiAbsolutePointerProtocolGuid }, 393 { .efi_guid_name = "device path", 394 .efi_guid = &gEfiDevicePathProtocolGuid }, 395 { .efi_guid_name = "block io", 396 .efi_guid = &gEfiBlockIoProtocolGuid }, 397 { .efi_guid_name = "block io2", 398 .efi_guid = &gEfiBlockIo2ProtocolGuid }, 399 { .efi_guid_name = "disk io", 400 .efi_guid = &gEfiDiskIoProtocolGuid }, 401 { .efi_guid_name = "disk io2", 402 .efi_guid = &gEfiDiskIo2ProtocolGuid }, 403 { .efi_guid_name = "disk info", 404 .efi_guid = &gEfiDiskInfoProtocolGuid }, 405 { .efi_guid_name = "simple fs", 406 .efi_guid = &gEfiSimpleFileSystemProtocolGuid }, 407 { .efi_guid_name = "load file", 408 .efi_guid = &gEfiLoadFileProtocolGuid }, 409 { .efi_guid_name = "load file2", 410 .efi_guid = &gEfiLoadFile2ProtocolGuid }, 411 { .efi_guid_name = "device io", 412 .efi_guid = &gEfiDeviceIoProtocolGuid }, 413 { .efi_guid_name = "unicode collation", 414 .efi_guid = &gEfiUnicodeCollationProtocolGuid }, 415 { .efi_guid_name = "unicode collation2", 416 .efi_guid = &gEfiUnicodeCollation2ProtocolGuid }, 417 { .efi_guid_name = "simple network", 418 .efi_guid = &gEfiSimpleNetworkProtocolGuid }, 419 { .efi_guid_name = "simple pointer", 420 .efi_guid = &gEfiSimplePointerProtocolGuid }, 421 { .efi_guid_name = "simple text output", 422 .efi_guid = &gEfiSimpleTextOutProtocolGuid }, 423 { .efi_guid_name = "simple text input", 424 .efi_guid = &gEfiSimpleTextInProtocolGuid }, 425 { .efi_guid_name = "simple text ex input", 426 .efi_guid = &gEfiSimpleTextInputExProtocolGuid }, 427 { .efi_guid_name = "console control", 428 .efi_guid = &gEfiConsoleControlProtocolGuid }, 429 { .efi_guid_name = "stdin", 430 .efi_guid = &gEfiConsoleInDeviceGuid }, 431 { .efi_guid_name = "stdout", 432 .efi_guid = &gEfiConsoleOutDeviceGuid }, 433 { .efi_guid_name = "stderr", 434 .efi_guid = &gEfiStandardErrorDeviceGuid }, 435 { .efi_guid_name = "GOP", 436 .efi_guid = &gEfiGraphicsOutputProtocolGuid }, 437 { .efi_guid_name = "UGA draw", 438 .efi_guid = &gEfiUgaDrawProtocolGuid }, 439 { .efi_guid_name = "UGA io", 440 .efi_guid = &gEfiUgaIoProtocolGuid }, 441 { .efi_guid_name = "PXE base code", 442 .efi_guid = &gEfiPxeBaseCodeProtocolGuid }, 443 { .efi_guid_name = "PXE base code callback", 444 .efi_guid = &gEfiPxeBaseCodeCallbackProtocolGuid }, 445 { .efi_guid_name = "serial io", 446 .efi_guid = &gEfiSerialIoProtocolGuid }, 447 { .efi_guid_name = "serial device type", 448 .efi_guid = &gEfiSerialTerminalDeviceTypeGuid }, 449 { .efi_guid_name = "loaded image", 450 .efi_guid = &gEfiLoadedImageProtocolGuid }, 451 { .efi_guid_name = "loaded image device path", 452 .efi_guid = &gEfiLoadedImageDevicePathProtocolGuid }, 453 { .efi_guid_name = "ISA ACPI", 454 .efi_guid = &gEfiIsaAcpiProtocolGuid }, 455 { .efi_guid_name = "ISA io", 456 .efi_guid = &gEfiIsaIoProtocolGuid }, 457 { .efi_guid_name = "IDE controller init", 458 .efi_guid = &gEfiIdeControllerInitProtocolGuid }, 459 { .efi_guid_name = "PCI", 460 .efi_guid = &gEfiPciIoProtocolGuid }, 461 { .efi_guid_name = "PCI enumeration", 462 .efi_guid = &gEfiPciEnumerationCompleteProtocolGuid }, 463 { .efi_guid_name = "PCI root bridge", 464 .efi_guid = &gEfiPciRootBridgeIoProtocolGuid }, 465 { .efi_guid_name = "driver binding", 466 .efi_guid = &gEfiDriverBindingProtocolGuid }, 467 { .efi_guid_name = "driver configuration", 468 .efi_guid = &gEfiDriverConfigurationProtocolGuid }, 469 { .efi_guid_name = "driver configuration2", 470 .efi_guid = &gEfiDriverConfiguration2ProtocolGuid }, 471 { .efi_guid_name = "driver diagnostics", 472 .efi_guid = &gEfiDriverDiagnosticsProtocolGuid }, 473 { .efi_guid_name = "driver diagnostics2", 474 .efi_guid = &gEfiDriverDiagnostics2ProtocolGuid }, 475 { .efi_guid_name = "driver override", 476 .efi_guid = &gEfiPlatformDriverOverrideProtocolGuid }, 477 { .efi_guid_name = "bus specific driver override", 478 .efi_guid = &gEfiBusSpecificDriverOverrideProtocolGuid }, 479 { .efi_guid_name = "platform to driver configuration", 480 .efi_guid = &gEfiPlatformToDriverConfigurationProtocolGuid }, 481 { .efi_guid_name = "driver supported EFI version", 482 .efi_guid = &gEfiDriverSupportedEfiVersionProtocolGuid }, 483 { .efi_guid_name = "driver family override", 484 .efi_guid = &gEfiDriverFamilyOverrideProtocolGuid }, 485 { .efi_guid_name = "driver health", 486 .efi_guid = &gEfiDriverHealthProtocolGuid }, 487 { .efi_guid_name = "adapter information", 488 .efi_guid = &gEfiAdapterInformationProtocolGuid }, 489 { .efi_guid_name = "VLAN config", 490 .efi_guid = &gEfiVlanConfigProtocolGuid }, 491 { .efi_guid_name = "ARP service binding", 492 .efi_guid = &gEfiArpServiceBindingProtocolGuid }, 493 { .efi_guid_name = "ARP", 494 .efi_guid = &gEfiArpProtocolGuid }, 495 { .efi_guid_name = "IPv4 service binding", 496 .efi_guid = &gEfiIp4ServiceBindingProtocolGuid }, 497 { .efi_guid_name = "IPv4", 498 .efi_guid = &gEfiIp4ProtocolGuid }, 499 { .efi_guid_name = "IPv4 config", 500 .efi_guid = &gEfiIp4ConfigProtocolGuid }, 501 { .efi_guid_name = "IPv4 config2", 502 .efi_guid = &gEfiIp4Config2ProtocolGuid }, 503 { .efi_guid_name = "IPv6 service binding", 504 .efi_guid = &gEfiIp6ServiceBindingProtocolGuid }, 505 { .efi_guid_name = "IPv6", 506 .efi_guid = &gEfiIp6ProtocolGuid }, 507 { .efi_guid_name = "IPv6 config", 508 .efi_guid = &gEfiIp6ConfigProtocolGuid }, 509 { .efi_guid_name = "NVMe pass thru", 510 .efi_guid = &gEfiNvmExpressPassThruProtocolGuid }, 511 { .efi_guid_name = "UDPv4", 512 .efi_guid = &gEfiUdp4ProtocolGuid }, 513 { .efi_guid_name = "UDPv4 service binding", 514 .efi_guid = &gEfiUdp4ServiceBindingProtocolGuid }, 515 { .efi_guid_name = "UDPv6", 516 .efi_guid = &gEfiUdp6ProtocolGuid }, 517 { .efi_guid_name = "UDPv6 service binding", 518 .efi_guid = &gEfiUdp6ServiceBindingProtocolGuid }, 519 { .efi_guid_name = "TCPv4", 520 .efi_guid = &gEfiTcp4ProtocolGuid }, 521 { .efi_guid_name = "TCPv4 service binding", 522 .efi_guid = &gEfiTcp4ServiceBindingProtocolGuid }, 523 { .efi_guid_name = "TCPv6", 524 .efi_guid = &gEfiTcp6ProtocolGuid }, 525 { .efi_guid_name = "TCPv6 service binding", 526 .efi_guid = &gEfiTcp6ServiceBindingProtocolGuid }, 527 { .efi_guid_name = "EFI System partition", 528 .efi_guid = &gEfiPartTypeSystemPartGuid }, 529 { .efi_guid_name = "MBR legacy", 530 .efi_guid = &gEfiPartTypeLegacyMbrGuid }, 531 { .efi_guid_name = "USB io", 532 .efi_guid = &gEfiUsbIoProtocolGuid }, 533 { .efi_guid_name = "USB2 HC", 534 .efi_guid = &gEfiUsb2HcProtocolGuid }, 535 { .efi_guid_name = "component name", 536 .efi_guid = &gEfiComponentNameProtocolGuid }, 537 { .efi_guid_name = "component name2", 538 .efi_guid = &gEfiComponentName2ProtocolGuid }, 539 { .efi_guid_name = "decompress", 540 .efi_guid = &gEfiDecompressProtocolGuid }, 541 { .efi_guid_name = "ebc interpreter", 542 .efi_guid = &gEfiEbcProtocolGuid }, 543 { .efi_guid_name = "network interface identifier", 544 .efi_guid = &gEfiNetworkInterfaceIdentifierProtocolGuid }, 545 { .efi_guid_name = "network interface identifier_31", 546 .efi_guid = &gEfiNetworkInterfaceIdentifierProtocolGuid_31 }, 547 { .efi_guid_name = "managed network service binding", 548 .efi_guid = &gEfiManagedNetworkServiceBindingProtocolGuid }, 549 { .efi_guid_name = "managed network", 550 .efi_guid = &gEfiManagedNetworkProtocolGuid }, 551 { .efi_guid_name = "form browser", 552 .efi_guid = &gEfiFormBrowser2ProtocolGuid }, 553 { .efi_guid_name = "HII config access", 554 .efi_guid = &gEfiHiiConfigAccessProtocolGuid }, 555 { .efi_guid_name = "HII config keyword handler", 556 .efi_guid = &gEfiConfigKeywordHandlerProtocolGuid }, 557 { .efi_guid_name = "HII config routing", 558 .efi_guid = &gEfiHiiConfigRoutingProtocolGuid }, 559 { .efi_guid_name = "HII database", 560 .efi_guid = &gEfiHiiDatabaseProtocolGuid }, 561 { .efi_guid_name = "HII string", 562 .efi_guid = &gEfiHiiStringProtocolGuid }, 563 { .efi_guid_name = "HII image", 564 .efi_guid = &gEfiHiiImageProtocolGuid }, 565 { .efi_guid_name = "HII font", 566 .efi_guid = &gEfiHiiFontProtocolGuid }, 567 { .efi_guid_name = "MTFTP3 service binding", 568 .efi_guid = &gEfiMtftp4ServiceBindingProtocolGuid }, 569 { .efi_guid_name = "MTFTP4", 570 .efi_guid = &gEfiMtftp4ProtocolGuid }, 571 { .efi_guid_name = "MTFTP6 service binding", 572 .efi_guid = &gEfiMtftp6ServiceBindingProtocolGuid }, 573 { .efi_guid_name = "MTFTP6", 574 .efi_guid = &gEfiMtftp6ProtocolGuid }, 575 { .efi_guid_name = "DHCP4 service binding", 576 .efi_guid = &gEfiDhcp4ServiceBindingProtocolGuid }, 577 { .efi_guid_name = "DHCP4", 578 .efi_guid = &gEfiDhcp4ProtocolGuid }, 579 { .efi_guid_name = "DHCP6 service binding", 580 .efi_guid = &gEfiDhcp6ServiceBindingProtocolGuid }, 581 { .efi_guid_name = "DHCP6", 582 .efi_guid = &gEfiDhcp6ProtocolGuid }, 583 { .efi_guid_name = "SCSI io", 584 .efi_guid = &gEfiScsiIoProtocolGuid }, 585 { .efi_guid_name = "SCSI pass thru", 586 .efi_guid = &gEfiScsiPassThruProtocolGuid }, 587 { .efi_guid_name = "SCSI pass thru ext", 588 .efi_guid = &gEfiExtScsiPassThruProtocolGuid }, 589 { .efi_guid_name = "Capsule arch", 590 .efi_guid = &gEfiCapsuleArchProtocolGuid }, 591 { .efi_guid_name = "monotonic counter arch", 592 .efi_guid = &gEfiMonotonicCounterArchProtocolGuid }, 593 { .efi_guid_name = "realtime clock arch", 594 .efi_guid = &gEfiRealTimeClockArchProtocolGuid }, 595 { .efi_guid_name = "variable arch", 596 .efi_guid = &gEfiVariableArchProtocolGuid }, 597 { .efi_guid_name = "variable write arch", 598 .efi_guid = &gEfiVariableWriteArchProtocolGuid }, 599 { .efi_guid_name = "watchdog timer arch", 600 .efi_guid = &gEfiWatchdogTimerArchProtocolGuid }, 601 { .efi_guid_name = "BDS arch", 602 .efi_guid = &gEfiBdsArchProtocolGuid }, 603 { .efi_guid_name = "metronome arch", 604 .efi_guid = &gEfiMetronomeArchProtocolGuid }, 605 { .efi_guid_name = "timer arch", 606 .efi_guid = &gEfiTimerArchProtocolGuid }, 607 { .efi_guid_name = "DPC", 608 .efi_guid = &gEfiDpcProtocolGuid }, 609 { .efi_guid_name = "print2", 610 .efi_guid = &gEfiPrint2SProtocolGuid }, 611 { .efi_guid_name = "device path to text", 612 .efi_guid = &gEfiDevicePathToTextProtocolGuid }, 613 { .efi_guid_name = "reset arch", 614 .efi_guid = &gEfiResetArchProtocolGuid }, 615 { .efi_guid_name = "CPU arch", 616 .efi_guid = &gEfiCpuArchProtocolGuid }, 617 { .efi_guid_name = "CPU IO2", 618 .efi_guid = &gEfiCpuIo2ProtocolGuid }, 619 { .efi_guid_name = "Legacy 8259", 620 .efi_guid = &gEfiLegacy8259ProtocolGuid }, 621 { .efi_guid_name = "Security arch", 622 .efi_guid = &gEfiSecurityArchProtocolGuid }, 623 { .efi_guid_name = "Security2 arch", 624 .efi_guid = &gEfiSecurity2ArchProtocolGuid }, 625 { .efi_guid_name = "Security Policy", 626 .efi_guid = &gEfiSecurityPolicyProtocolGuid }, 627 { .efi_guid_name = "Runtime arch", 628 .efi_guid = &gEfiRuntimeArchProtocolGuid }, 629 { .efi_guid_name = "status code runtime", 630 .efi_guid = &gEfiStatusCodeRuntimeProtocolGuid }, 631 { .efi_guid_name = "storage security command", 632 .efi_guid = &gEfiStorageSecurityCommandProtocolGuid }, 633 { .efi_guid_name = "data hub", 634 .efi_guid = &gEfiDataHubProtocolGuid }, 635 { .efi_guid_name = "PCD", 636 .efi_guid = &gPcdProtocolGuid }, 637 { .efi_guid_name = "EFI PCD", 638 .efi_guid = &gEfiPcdProtocolGuid }, 639 { .efi_guid_name = "firmware volume block", 640 .efi_guid = &gEfiFirmwareVolumeBlockProtocolGuid }, 641 { .efi_guid_name = "firmware volume2", 642 .efi_guid = &gEfiFirmwareVolumeBlock2ProtocolGuid }, 643 { .efi_guid_name = "lzma compress", 644 .efi_guid = &gLzmaCompress }, 645 { .efi_guid_name = "MP services", 646 .efi_guid = &gEfiMpServiceProtocolGuid }, 647 { .efi_guid_name = MTC_VARIABLE_NAME, 648 .efi_guid = &gMtcVendorGuid }, 649 { .efi_guid_name = "Active EDID", 650 .efi_guid = &gEfiEdidActiveProtocolGuid }, 651 { .efi_guid_name = "Discovered EDID", 652 .efi_guid = &gEfiEdidDiscoveredProtocolGuid }, 653 { .efi_guid_name = "key management service", 654 .efi_guid = &gEfiKmsProtocolGuid }, 655 { .efi_guid_name = "smart card reader", 656 .efi_guid = &gEfiSmartCardReaderProtocolGuid }, 657 { .efi_guid_name = "rng source", 658 .efi_guid = &gEfiRngProtocolGuid }, 659 { .efi_guid_name = "IPsec config", 660 .efi_guid = &gEfiIpSecConfigProtocolGuid }, 661 { .efi_guid_name = "IPsec", 662 .efi_guid = &gEfiIpSecProtocolGuid }, 663 { .efi_guid_name = "IPsec2", 664 .efi_guid = &gEfiIpSec2ProtocolGuid }, 665 { .efi_guid_name = "TCG2 tpm", 666 .efi_guid = &gEfiTcg2ProtocolGuid } 667 }; 668 669 bool 670 efi_guid_to_str(const EFI_GUID *guid, char **sp) 671 { 672 uint32_t status; 673 674 uuid_to_string((const uuid_t *)guid, sp, &status); 675 return (status == uuid_s_ok ? true : false); 676 } 677 678 bool 679 efi_str_to_guid(const char *s, EFI_GUID *guid) 680 { 681 uint32_t status; 682 683 uuid_from_string(s, (uuid_t *)guid, &status); 684 return (status == uuid_s_ok ? true : false); 685 } 686 687 bool 688 efi_name_to_guid(const char *name, EFI_GUID *guid) 689 { 690 uint32_t i; 691 692 for (i = 0; i < nitems(efi_uuid_mapping); i++) { 693 if (strcasecmp(name, efi_uuid_mapping[i].efi_guid_name) == 0) { 694 *guid = *efi_uuid_mapping[i].efi_guid; 695 return (true); 696 } 697 } 698 return (efi_str_to_guid(name, guid)); 699 } 700 701 bool 702 efi_guid_to_name(EFI_GUID *guid, char **name) 703 { 704 uint32_t i; 705 int rv; 706 707 for (i = 0; i < nitems(efi_uuid_mapping); i++) { 708 rv = uuid_equal((uuid_t *)guid, 709 (uuid_t *)efi_uuid_mapping[i].efi_guid, NULL); 710 if (rv != 0) { 711 *name = strdup(efi_uuid_mapping[i].efi_guid_name); 712 if (*name == NULL) 713 return (false); 714 return (true); 715 } 716 } 717 return (efi_guid_to_str(guid, name)); 718 } 719 720 void 721 efi_init_environment(void) 722 { 723 char var[128]; 724 725 snprintf(var, sizeof (var), "%d.%02d", ST->Hdr.Revision >> 16, 726 ST->Hdr.Revision & 0xffff); 727 env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset); 728 } 729 730 COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", 731 command_efi_show); 732 733 static int 734 efi_print_other_value(uint8_t *data, UINTN datasz) 735 { 736 UINTN i; 737 bool is_ascii = true; 738 739 printf(" = "); 740 for (i = 0; i < datasz - 1; i++) { 741 /* 742 * Quick hack to see if this ascii-ish string is printable 743 * range plus tab, cr and lf. 744 */ 745 if ((data[i] < 32 || data[i] > 126) && 746 data[i] != 9 && data[i] != 10 && data[i] != 13) { 747 is_ascii = false; 748 break; 749 } 750 } 751 if (data[datasz - 1] != '\0') 752 is_ascii = false; 753 if (is_ascii == true) { 754 printf("%s", data); 755 if (pager_output("\n")) 756 return (CMD_WARN); 757 } else { 758 if (pager_output("\n")) 759 return (CMD_WARN); 760 /* 761 * Dump hex bytes grouped by 4. 762 */ 763 for (i = 0; i < datasz; i++) { 764 printf("%02x ", data[i]); 765 if ((i + 1) % 4 == 0) 766 printf(" "); 767 if ((i + 1) % 20 == 0) { 768 if (pager_output("\n")) 769 return (CMD_WARN); 770 } 771 } 772 if (pager_output("\n")) 773 return (CMD_WARN); 774 } 775 776 return (CMD_OK); 777 } 778 779 /* This appears to be some sort of UEFI shell alias table. */ 780 static int 781 efi_print_shell_str(const CHAR16 *varnamearg __unused, uint8_t *data, 782 UINTN datasz __unused) 783 { 784 printf(" = %S", (CHAR16 *)data); 785 if (pager_output("\n")) 786 return (CMD_WARN); 787 return (CMD_OK); 788 } 789 790 const char * 791 efi_memory_type(EFI_MEMORY_TYPE type) 792 { 793 const char *types[] = { 794 "Reserved", 795 "LoaderCode", 796 "LoaderData", 797 "BootServicesCode", 798 "BootServicesData", 799 "RuntimeServicesCode", 800 "RuntimeServicesData", 801 "ConventionalMemory", 802 "UnusableMemory", 803 "ACPIReclaimMemory", 804 "ACPIMemoryNVS", 805 "MemoryMappedIO", 806 "MemoryMappedIOPortSpace", 807 "PalCode", 808 "PersistentMemory" 809 }; 810 811 switch (type) { 812 case EfiReservedMemoryType: 813 case EfiLoaderCode: 814 case EfiLoaderData: 815 case EfiBootServicesCode: 816 case EfiBootServicesData: 817 case EfiRuntimeServicesCode: 818 case EfiRuntimeServicesData: 819 case EfiConventionalMemory: 820 case EfiUnusableMemory: 821 case EfiACPIReclaimMemory: 822 case EfiACPIMemoryNVS: 823 case EfiMemoryMappedIO: 824 case EfiMemoryMappedIOPortSpace: 825 case EfiPalCode: 826 case EfiPersistentMemory: 827 return (types[type]); 828 default: 829 return ("Unknown"); 830 } 831 } 832 833 /* Print memory type table. */ 834 static int 835 efi_print_mem_type(const CHAR16 *varnamearg __unused, uint8_t *data, 836 UINTN datasz) 837 { 838 int i, n; 839 EFI_MEMORY_TYPE_INFORMATION *ti; 840 841 ti = (EFI_MEMORY_TYPE_INFORMATION *)data; 842 if (pager_output(" = \n")) 843 return (CMD_WARN); 844 845 n = datasz / sizeof (EFI_MEMORY_TYPE_INFORMATION); 846 for (i = 0; i < n && ti[i].NumberOfPages != 0; i++) { 847 printf("\t%23s pages: %u", efi_memory_type(ti[i].Type), 848 ti[i].NumberOfPages); 849 if (pager_output("\n")) 850 return (CMD_WARN); 851 } 852 853 return (CMD_OK); 854 } 855 856 /* 857 * Print illumos variables. 858 * We have LoaderPath and LoaderDev as CHAR16 strings. 859 */ 860 static int 861 efi_print_illumos(const CHAR16 *varnamearg, uint8_t *data, 862 UINTN datasz __unused) 863 { 864 int rv = -1; 865 char *var = NULL; 866 867 if (ucs2_to_utf8(varnamearg, &var) != 0) 868 return (CMD_ERROR); 869 870 if (strcmp("LoaderPath", var) == 0 || 871 strcmp("LoaderDev", var) == 0) { 872 printf(" = "); 873 printf("%S", (CHAR16 *)data); 874 875 if (pager_output("\n")) 876 rv = CMD_WARN; 877 else 878 rv = CMD_OK; 879 } 880 881 free(var); 882 return (rv); 883 } 884 885 /* Print global variables. */ 886 static int 887 efi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz) 888 { 889 int rv = -1; 890 char *var = NULL; 891 892 if (ucs2_to_utf8(varnamearg, &var) != 0) 893 return (CMD_ERROR); 894 895 if (strcmp("AuditMode", var) == 0) { 896 printf(" = "); 897 printf("0x%x", *data); /* 8-bit int */ 898 goto done; 899 } 900 901 if (strcmp("BootOptionSupport", var) == 0) { 902 printf(" = "); 903 printf("0x%x", *((uint32_t *)data)); /* UINT32 */ 904 goto done; 905 } 906 907 if (strcmp("BootCurrent", var) == 0 || 908 strcmp("BootNext", var) == 0 || 909 strcmp("Timeout", var) == 0) { 910 printf(" = "); 911 printf("%u", *((uint16_t *)data)); /* UINT16 */ 912 goto done; 913 } 914 915 if (strcmp("BootOrder", var) == 0 || 916 strcmp("DriverOrder", var) == 0) { 917 int i; 918 UINT16 *u16 = (UINT16 *)data; 919 920 printf(" ="); 921 for (i = 0; i < datasz / sizeof (UINT16); i++) 922 printf(" %u", u16[i]); 923 goto done; 924 } 925 if (strncmp("Boot", var, 4) == 0 || 926 strncmp("Driver", var, 5) == 0 || 927 strncmp("SysPrep", var, 7) == 0 || 928 strncmp("OsRecovery", var, 10) == 0) { 929 UINT16 filepathlistlen; 930 CHAR16 *text; 931 int desclen; 932 EFI_DEVICE_PATH *dp; 933 934 data += sizeof (UINT32); 935 filepathlistlen = *(uint16_t *)data; 936 data += sizeof (UINT16); 937 text = (CHAR16 *)data; 938 939 for (desclen = 0; text[desclen] != 0; desclen++) 940 ; 941 if (desclen != 0) { 942 /* Add terminating zero and we have CHAR16. */ 943 desclen = (desclen + 1) * 2; 944 } 945 946 printf(" = "); 947 printf("%S", text); 948 if (filepathlistlen != 0) { 949 /* Output pathname from new line. */ 950 if (pager_output("\n")) { 951 rv = CMD_WARN; 952 goto done; 953 } 954 dp = malloc(filepathlistlen); 955 if (dp == NULL) 956 goto done; 957 958 memcpy(dp, data + desclen, filepathlistlen); 959 text = efi_devpath_name(dp); 960 if (text != NULL) { 961 printf("\t%S", text); 962 efi_free_devpath_name(text); 963 } 964 free(dp); 965 } 966 goto done; 967 } 968 969 if (strcmp("ConIn", var) == 0 || 970 strcmp("ConInDev", var) == 0 || 971 strcmp("ConOut", var) == 0 || 972 strcmp("ConOutDev", var) == 0 || 973 strcmp("ErrOut", var) == 0 || 974 strcmp("ErrOutDev", var) == 0) { 975 CHAR16 *text; 976 977 printf(" = "); 978 text = efi_devpath_name((EFI_DEVICE_PATH *)data); 979 if (text != NULL) { 980 printf("%S", text); 981 efi_free_devpath_name(text); 982 } 983 goto done; 984 } 985 986 if (strcmp("PlatformLang", var) == 0 || 987 strcmp("PlatformLangCodes", var) == 0 || 988 strcmp("LangCodes", var) == 0 || 989 strcmp("Lang", var) == 0) { 990 printf(" = "); 991 printf("%s", data); /* ASCII string */ 992 goto done; 993 } 994 995 /* 996 * Feature bitmap from firmware to OS. 997 * Older UEFI provides UINT32, newer UINT64. 998 */ 999 if (strcmp("OsIndicationsSupported", var) == 0) { 1000 printf(" = "); 1001 if (datasz == 4) 1002 printf("0x%x", *((uint32_t *)data)); 1003 else 1004 printf("0x%jx", *((uint64_t *)data)); 1005 goto done; 1006 } 1007 1008 /* Fallback for anything else. */ 1009 rv = efi_print_other_value(data, datasz); 1010 done: 1011 if (rv == -1) { 1012 if (pager_output("\n")) 1013 rv = CMD_WARN; 1014 else 1015 rv = CMD_OK; 1016 } 1017 free(var); 1018 return (rv); 1019 } 1020 1021 static void 1022 efi_print_var_attr(UINT32 attr) 1023 { 1024 bool comma = false; 1025 1026 if (attr & EFI_VARIABLE_NON_VOLATILE) { 1027 printf("NV"); 1028 comma = true; 1029 } 1030 if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS) { 1031 if (comma == true) 1032 printf(","); 1033 printf("BS"); 1034 comma = true; 1035 } 1036 if (attr & EFI_VARIABLE_RUNTIME_ACCESS) { 1037 if (comma == true) 1038 printf(","); 1039 printf("RS"); 1040 comma = true; 1041 } 1042 if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD) { 1043 if (comma == true) 1044 printf(","); 1045 printf("HR"); 1046 comma = true; 1047 } 1048 if (attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) { 1049 if (comma == true) 1050 printf(","); 1051 printf("AT"); 1052 comma = true; 1053 } 1054 } 1055 1056 static int 1057 efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag) 1058 { 1059 UINTN datasz; 1060 EFI_STATUS status; 1061 UINT32 attr; 1062 char *str; 1063 uint8_t *data; 1064 int rv = CMD_OK; 1065 1066 str = NULL; 1067 datasz = 0; 1068 status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, NULL); 1069 if (status != EFI_BUFFER_TOO_SMALL) { 1070 printf("Can't get the variable: error %#lx\n", 1071 DECODE_ERROR(status)); 1072 return (CMD_ERROR); 1073 } 1074 data = malloc(datasz); 1075 if (data == NULL) { 1076 printf("Out of memory\n"); 1077 return (CMD_ERROR); 1078 } 1079 1080 status = RS->GetVariable(varnamearg, matchguid, &attr, &datasz, data); 1081 if (status != EFI_SUCCESS) { 1082 printf("Can't get the variable: error %#lx\n", 1083 DECODE_ERROR(status)); 1084 free(data); 1085 return (CMD_ERROR); 1086 } 1087 1088 if (efi_guid_to_name(matchguid, &str) == false) { 1089 rv = CMD_ERROR; 1090 goto done; 1091 } 1092 printf("%s ", str); 1093 efi_print_var_attr(attr); 1094 printf(" %S", varnamearg); 1095 1096 if (lflag == 0) { 1097 if (strcmp(str, "global") == 0) 1098 rv = efi_print_global(varnamearg, data, datasz); 1099 else if (strcmp(str, "illumos") == 0) 1100 rv = efi_print_illumos(varnamearg, data, datasz); 1101 else if (strcmp(str, 1102 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0) 1103 rv = efi_print_mem_type(varnamearg, data, datasz); 1104 else if (strcmp(str, 1105 "47c7b227-c42a-11d2-8e57-00a0c969723b") == 0) 1106 rv = efi_print_shell_str(varnamearg, data, datasz); 1107 else if (strcmp(str, MTC_VARIABLE_NAME) == 0) { 1108 printf(" = "); 1109 printf("%u", *((uint32_t *)data)); /* UINT32 */ 1110 rv = CMD_OK; 1111 if (pager_output("\n")) 1112 rv = CMD_WARN; 1113 } else 1114 rv = efi_print_other_value(data, datasz); 1115 } else if (pager_output("\n")) 1116 rv = CMD_WARN; 1117 1118 done: 1119 free(str); 1120 free(data); 1121 return (rv); 1122 } 1123 1124 static int 1125 command_efi_show(int argc, char *argv[]) 1126 { 1127 /* 1128 * efi-show [-a] 1129 * print all the env 1130 * efi-show -g UUID 1131 * print all the env vars tagged with UUID 1132 * efi-show -v var 1133 * search all the env vars and print the ones matching var 1134 * efi-show -g UUID -v var 1135 * efi-show UUID var 1136 * print all the env vars that match UUID and var 1137 */ 1138 /* NB: We assume EFI_GUID is the same as uuid_t */ 1139 int aflag = 0, gflag = 0, lflag = 0, vflag = 0; 1140 int ch, rv; 1141 unsigned i; 1142 EFI_STATUS status; 1143 EFI_GUID varguid = ZERO_GUID; 1144 EFI_GUID matchguid = ZERO_GUID; 1145 CHAR16 *varname; 1146 CHAR16 *newnm; 1147 CHAR16 varnamearg[128]; 1148 UINTN varalloc; 1149 UINTN varsz; 1150 1151 optind = 1; 1152 optreset = 1; 1153 opterr = 1; 1154 1155 while ((ch = getopt(argc, argv, "ag:lv:")) != -1) { 1156 switch (ch) { 1157 case 'a': 1158 aflag = 1; 1159 break; 1160 case 'g': 1161 gflag = 1; 1162 if (efi_name_to_guid(optarg, &matchguid) == false) { 1163 printf("uuid %s could not be parsed\n", optarg); 1164 return (CMD_ERROR); 1165 } 1166 break; 1167 case 'l': 1168 lflag = 1; 1169 break; 1170 case 'v': 1171 vflag = 1; 1172 if (strlen(optarg) >= nitems(varnamearg)) { 1173 printf("Variable %s is longer than %zu " 1174 "characters\n", optarg, nitems(varnamearg)); 1175 return (CMD_ERROR); 1176 } 1177 cpy8to16(optarg, varnamearg, nitems(varnamearg)); 1178 break; 1179 default: 1180 return (CMD_ERROR); 1181 } 1182 } 1183 1184 if (argc == 1) /* default is -a */ 1185 aflag = 1; 1186 1187 if (aflag && (gflag || vflag)) { 1188 printf("-a isn't compatible with -g or -v\n"); 1189 return (CMD_ERROR); 1190 } 1191 1192 if (aflag && optind < argc) { 1193 printf("-a doesn't take any args\n"); 1194 return (CMD_ERROR); 1195 } 1196 1197 argc -= optind; 1198 argv += optind; 1199 1200 pager_open(); 1201 if (vflag && gflag) { 1202 rv = efi_print_var(varnamearg, &matchguid, lflag); 1203 if (rv == CMD_WARN) 1204 rv = CMD_OK; 1205 pager_close(); 1206 return (rv); 1207 } 1208 1209 if (argc == 2) { 1210 optarg = argv[0]; 1211 if (strlen(optarg) >= nitems(varnamearg)) { 1212 printf("Variable %s is longer than %zu characters\n", 1213 optarg, nitems(varnamearg)); 1214 pager_close(); 1215 return (CMD_ERROR); 1216 } 1217 for (i = 0; i < strlen(optarg); i++) 1218 varnamearg[i] = optarg[i]; 1219 varnamearg[i] = 0; 1220 optarg = argv[1]; 1221 if (efi_name_to_guid(optarg, &matchguid) == false) { 1222 printf("uuid %s could not be parsed\n", optarg); 1223 pager_close(); 1224 return (CMD_ERROR); 1225 } 1226 rv = efi_print_var(varnamearg, &matchguid, lflag); 1227 if (rv == CMD_WARN) 1228 rv = CMD_OK; 1229 pager_close(); 1230 return (rv); 1231 } 1232 1233 if (argc > 0) { 1234 printf("Too many args: %d\n", argc); 1235 pager_close(); 1236 return (CMD_ERROR); 1237 } 1238 1239 /* 1240 * Initiate the search -- note the standard takes pain 1241 * to specify the initial call must be a poiner to a NULL 1242 * character. 1243 */ 1244 varalloc = 1024; 1245 varname = malloc(varalloc); 1246 if (varname == NULL) { 1247 printf("Can't allocate memory to get variables\n"); 1248 pager_close(); 1249 return (CMD_ERROR); 1250 } 1251 varname[0] = 0; 1252 while (1) { 1253 varsz = varalloc; 1254 status = RS->GetNextVariableName(&varsz, varname, &varguid); 1255 if (status == EFI_BUFFER_TOO_SMALL) { 1256 varalloc = varsz; 1257 newnm = realloc(varname, varalloc); 1258 if (newnm == NULL) { 1259 printf("Can't allocate memory to get " 1260 "variables\n"); 1261 rv = CMD_ERROR; 1262 break; 1263 } 1264 varname = newnm; 1265 continue; /* Try again with bigger buffer */ 1266 } 1267 if (status == EFI_NOT_FOUND) { 1268 rv = CMD_OK; 1269 break; 1270 } 1271 if (status != EFI_SUCCESS) { 1272 rv = CMD_ERROR; 1273 break; 1274 } 1275 1276 if (aflag) { 1277 rv = efi_print_var(varname, &varguid, lflag); 1278 if (rv != CMD_OK) { 1279 if (rv == CMD_WARN) 1280 rv = CMD_OK; 1281 break; 1282 } 1283 continue; 1284 } 1285 if (vflag) { 1286 if (wcscmp(varnamearg, varname) == 0) { 1287 rv = efi_print_var(varname, &varguid, lflag); 1288 if (rv != CMD_OK) { 1289 if (rv == CMD_WARN) 1290 rv = CMD_OK; 1291 break; 1292 } 1293 continue; 1294 } 1295 } 1296 if (gflag) { 1297 rv = uuid_equal((uuid_t *)&varguid, 1298 (uuid_t *)&matchguid, NULL); 1299 if (rv != 0) { 1300 rv = efi_print_var(varname, &varguid, lflag); 1301 if (rv != CMD_OK) { 1302 if (rv == CMD_WARN) 1303 rv = CMD_OK; 1304 break; 1305 } 1306 continue; 1307 } 1308 } 1309 } 1310 free(varname); 1311 pager_close(); 1312 1313 return (rv); 1314 } 1315 1316 COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set); 1317 1318 static int 1319 command_efi_set(int argc, char *argv[]) 1320 { 1321 char *uuid, *var, *val; 1322 CHAR16 wvar[128]; 1323 EFI_GUID guid; 1324 #if defined(ENABLE_UPDATES) 1325 EFI_STATUS err; 1326 #endif 1327 1328 if (argc != 4) { 1329 printf("efi-set uuid var new-value\n"); 1330 return (CMD_ERROR); 1331 } 1332 uuid = argv[1]; 1333 var = argv[2]; 1334 val = argv[3]; 1335 if (efi_name_to_guid(uuid, &guid) == false) { 1336 printf("Invalid uuid %s\n", uuid); 1337 return (CMD_ERROR); 1338 } 1339 cpy8to16(var, wvar, nitems(wvar)); 1340 #if defined(ENABLE_UPDATES) 1341 err = RS->SetVariable(wvar, &guid, EFI_VARIABLE_NON_VOLATILE | 1342 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, 1343 strlen(val) + 1, val); 1344 if (EFI_ERROR(err)) { 1345 printf("Failed to set variable: error %lu\n", 1346 DECODE_ERROR(err)); 1347 return (CMD_ERROR); 1348 } 1349 #else 1350 printf("would set %s %s = %s\n", uuid, var, val); 1351 #endif 1352 return (CMD_OK); 1353 } 1354 1355 COMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", 1356 command_efi_unset); 1357 1358 static int 1359 command_efi_unset(int argc, char *argv[]) 1360 { 1361 char *uuid, *var; 1362 CHAR16 wvar[128]; 1363 EFI_GUID guid; 1364 #if defined(ENABLE_UPDATES) 1365 EFI_STATUS err; 1366 #endif 1367 1368 if (argc != 3) { 1369 printf("efi-unset uuid var\n"); 1370 return (CMD_ERROR); 1371 } 1372 uuid = argv[1]; 1373 var = argv[2]; 1374 if (efi_name_to_guid(uuid, &guid) == false) { 1375 printf("Invalid uuid %s\n", uuid); 1376 return (CMD_ERROR); 1377 } 1378 cpy8to16(var, wvar, nitems(wvar)); 1379 #if defined(ENABLE_UPDATES) 1380 err = RS->SetVariable(wvar, &guid, 0, 0, NULL); 1381 if (EFI_ERROR(err)) { 1382 printf("Failed to unset variable: error %lu\n", 1383 DECODE_ERROR(err)); 1384 return (CMD_ERROR); 1385 } 1386 #else 1387 printf("would unset %s %s \n", uuid, var); 1388 #endif 1389 return (CMD_OK); 1390 } 1391 1392 /* 1393 * Loader interaction words and extras 1394 * 1395 * efi-setenv ( value n name n guid n attr -- 0 | -1) 1396 * efi-getenv ( guid n addr n -- addr' n' | -1 ) 1397 * efi-unsetenv ( name n guid n'' -- ) 1398 */ 1399 1400 /* 1401 * efi-setenv 1402 * efi-setenv ( value n name n guid n attr -- 0 | -1) 1403 * 1404 * Set environment variables using the SetVariable EFI runtime service. 1405 * 1406 * Value and guid are passed through in binary form (so guid needs to be 1407 * converted to binary form from its string form). Name is converted from 1408 * ASCII to CHAR16. Since ficl doesn't have support for internationalization, 1409 * there's no native CHAR16 interface provided. 1410 * 1411 * attr is an int in the bitmask of the following attributes for this variable. 1412 * 1413 * 1 Non volatile 1414 * 2 Boot service access 1415 * 4 Run time access 1416 * (corresponding to the same bits in the UEFI spec). 1417 */ 1418 static void 1419 ficlEfiSetenv(ficlVm *pVM) 1420 { 1421 char *value = NULL, *guid = NULL; 1422 CHAR16 *name = NULL; 1423 int i; 1424 char *namep, *valuep, *guidp; 1425 int names, values, guids, attr; 1426 EFI_STATUS status; 1427 uuid_t u; 1428 uint32_t ustatus; 1429 char *error = NULL; 1430 ficlStack *pStack = ficlVmGetDataStack(pVM); 1431 1432 FICL_STACK_CHECK(pStack, 6, 0); 1433 1434 attr = ficlStackPopInteger(pStack); 1435 guids = ficlStackPopInteger(pStack); 1436 guidp = (char *)ficlStackPopPointer(pStack); 1437 names = ficlStackPopInteger(pStack); 1438 namep = (char *)ficlStackPopPointer(pStack); 1439 values = ficlStackPopInteger(pStack); 1440 valuep = (char *)ficlStackPopPointer(pStack); 1441 1442 guid = ficlMalloc(guids); 1443 if (guid == NULL) 1444 goto out; 1445 memcpy(guid, guidp, guids); 1446 uuid_from_string(guid, &u, &ustatus); 1447 if (ustatus != uuid_s_ok) { 1448 switch (ustatus) { 1449 case uuid_s_bad_version: 1450 error = "uuid: bad string"; 1451 break; 1452 case uuid_s_invalid_string_uuid: 1453 error = "uuid: invalid string"; 1454 break; 1455 case uuid_s_no_memory: 1456 error = "Out of memory"; 1457 break; 1458 default: 1459 error = "uuid: Unknown error"; 1460 break; 1461 } 1462 ficlStackPushInteger(pStack, -1); 1463 goto out; 1464 } 1465 1466 name = ficlMalloc((names + 1) * sizeof (CHAR16)); 1467 if (name == NULL) { 1468 error = "Out of memory"; 1469 goto out; 1470 } 1471 for (i = 0; i < names; i++) 1472 name[i] = namep[i]; 1473 name[names] = 0; 1474 1475 value = ficlMalloc(values + 1); 1476 if (value == NULL) { 1477 error = "Out of memory"; 1478 goto out; 1479 } 1480 memcpy(value, valuep, values); 1481 1482 status = RS->SetVariable(name, (EFI_GUID *)&u, attr, values, value); 1483 if (status == EFI_SUCCESS) { 1484 ficlStackPushInteger(pStack, 0); 1485 } else { 1486 ficlStackPushInteger(pStack, -1); 1487 error = "Error: SetVariable failed"; 1488 } 1489 1490 out: 1491 ficlFree(name); 1492 ficlFree(value); 1493 ficlFree(guid); 1494 if (error != NULL) 1495 ficlVmThrowError(pVM, error); 1496 } 1497 1498 static void 1499 ficlEfiGetenv(ficlVm *pVM) 1500 { 1501 char *name, *value; 1502 char *namep; 1503 int names; 1504 1505 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2); 1506 1507 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 1508 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 1509 1510 name = ficlMalloc(names+1); 1511 if (name == NULL) 1512 ficlVmThrowError(pVM, "Error: out of memory"); 1513 strncpy(name, namep, names); 1514 name[names] = '\0'; 1515 1516 value = getenv(name); 1517 ficlFree(name); 1518 1519 if (value != NULL) { 1520 ficlStackPushPointer(ficlVmGetDataStack(pVM), value); 1521 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value)); 1522 } else { 1523 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 1524 } 1525 } 1526 1527 static void 1528 ficlEfiUnsetenv(ficlVm *pVM) 1529 { 1530 char *name; 1531 char *namep; 1532 int names; 1533 1534 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0); 1535 1536 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 1537 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 1538 1539 name = ficlMalloc(names+1); 1540 if (name == NULL) 1541 ficlVmThrowError(pVM, "Error: out of memory"); 1542 strncpy(name, namep, names); 1543 name[names] = '\0'; 1544 1545 unsetenv(name); 1546 ficlFree(name); 1547 } 1548 1549 /* 1550 * Build platform extensions into the system dictionary 1551 */ 1552 static void 1553 ficlEfiCompilePlatform(ficlSystem *pSys) 1554 { 1555 ficlDictionary *dp = ficlSystemGetDictionary(pSys); 1556 1557 FICL_SYSTEM_ASSERT(pSys, dp); 1558 1559 ficlDictionarySetPrimitive(dp, "efi-setenv", ficlEfiSetenv, 1560 FICL_WORD_DEFAULT); 1561 ficlDictionarySetPrimitive(dp, "efi-getenv", ficlEfiGetenv, 1562 FICL_WORD_DEFAULT); 1563 ficlDictionarySetPrimitive(dp, "efi-unsetenv", ficlEfiUnsetenv, 1564 FICL_WORD_DEFAULT); 1565 } 1566 1567 FICL_COMPILE_SET(ficlEfiCompilePlatform); 1568