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
efi_guid_to_str(const EFI_GUID * guid,char ** sp)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
efi_str_to_guid(const char * s,EFI_GUID * guid)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
efi_name_to_guid(const char * name,EFI_GUID * guid)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
efi_guid_to_name(EFI_GUID * guid,char ** name)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
efi_init_environment(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
efi_print_other_value(uint8_t * data,UINTN datasz)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
efi_print_shell_str(const CHAR16 * varnamearg __unused,uint8_t * data,UINTN datasz __unused)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 *
efi_memory_type(EFI_MEMORY_TYPE type)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
efi_print_mem_type(const CHAR16 * varnamearg __unused,uint8_t * data,UINTN datasz)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
efi_print_illumos(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz __unused)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
efi_print_global(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz)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
efi_print_var_attr(UINT32 attr)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
efi_print_var(CHAR16 * varnamearg,EFI_GUID * matchguid,int lflag)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
command_efi_show(int argc,char * argv[])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
command_efi_set(int argc,char * argv[])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
command_efi_unset(int argc,char * argv[])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
ficlEfiSetenv(ficlVm * pVM)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
ficlEfiGetenv(ficlVm * pVM)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
ficlEfiUnsetenv(ficlVm * pVM)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
ficlEfiCompilePlatform(ficlSystem * pSys)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