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 <efilib.h>
32 #include <efigpt.h> /* Partition GUIDS */
33 #include <Guid/MemoryTypeInformation.h>
34 #include <Guid/MtcVendor.h>
35 #include <Guid/ZeroGuid.h>
36 #include <Protocol/EdidActive.h>
37 #include <Protocol/EdidDiscovered.h>
38 #include <uuid.h>
39 #include <stdbool.h>
40 #include <sys/param.h>
41 #include "bootstrap.h"
42 #include "ficl.h"
43
44 static struct efi_uuid_mapping {
45 const char *efi_guid_name;
46 EFI_GUID efi_guid;
47 } efi_uuid_mapping[] = {
48 { .efi_guid_name = "global", .efi_guid = EFI_GLOBAL_VARIABLE },
49 /* EFI Systab entry names. */
50 { .efi_guid_name = "MPS Table", .efi_guid = MPS_TABLE_GUID },
51 { .efi_guid_name = "ACPI Table", .efi_guid = ACPI_TABLE_GUID },
52 { .efi_guid_name = "ACPI 2.0 Table", .efi_guid = ACPI_20_TABLE_GUID },
53 { .efi_guid_name = "SMBIOS Table", .efi_guid = SMBIOS_TABLE_GUID },
54 { .efi_guid_name = "SMBIOS3 Table", .efi_guid = SMBIOS3_TABLE_GUID },
55 { .efi_guid_name = "DXE Table", .efi_guid = DXE_SERVICES_TABLE_GUID },
56 { .efi_guid_name = "HOB List Table", .efi_guid = HOB_LIST_TABLE_GUID },
57 { .efi_guid_name = EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
58 .efi_guid = EFI_MEMORY_TYPE_INFORMATION_GUID },
59 { .efi_guid_name = "Debug Image Info Table",
60 .efi_guid = DEBUG_IMAGE_INFO_TABLE_GUID },
61 { .efi_guid_name = "FDT Table", .efi_guid = FDT_TABLE_GUID },
62 /*
63 * Protocol names for debug purposes.
64 * Can be removed along with lsefi command.
65 */
66 { .efi_guid_name = "device path", .efi_guid = DEVICE_PATH_PROTOCOL },
67 { .efi_guid_name = "block io", .efi_guid = BLOCK_IO_PROTOCOL },
68 { .efi_guid_name = "disk io", .efi_guid = DISK_IO_PROTOCOL },
69 { .efi_guid_name = "disk info", .efi_guid =
70 EFI_DISK_INFO_PROTOCOL_GUID },
71 { .efi_guid_name = "simple fs",
72 .efi_guid = SIMPLE_FILE_SYSTEM_PROTOCOL },
73 { .efi_guid_name = "load file", .efi_guid = LOAD_FILE_PROTOCOL },
74 { .efi_guid_name = "device io", .efi_guid = DEVICE_IO_PROTOCOL },
75 { .efi_guid_name = "unicode collation",
76 .efi_guid = UNICODE_COLLATION_PROTOCOL },
77 { .efi_guid_name = "unicode collation2",
78 .efi_guid = EFI_UNICODE_COLLATION2_PROTOCOL_GUID },
79 { .efi_guid_name = "simple network",
80 .efi_guid = EFI_SIMPLE_NETWORK_PROTOCOL },
81 { .efi_guid_name = "simple text output",
82 .efi_guid = SIMPLE_TEXT_OUTPUT_PROTOCOL },
83 { .efi_guid_name = "simple text input",
84 .efi_guid = SIMPLE_TEXT_INPUT_PROTOCOL },
85 { .efi_guid_name = "simple text ex input",
86 .efi_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID },
87 { .efi_guid_name = "console control",
88 .efi_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID },
89 { .efi_guid_name = "stdin", .efi_guid = EFI_CONSOLE_IN_DEVICE_GUID },
90 { .efi_guid_name = "stdout", .efi_guid = EFI_CONSOLE_OUT_DEVICE_GUID },
91 { .efi_guid_name = "stderr",
92 .efi_guid = EFI_STANDARD_ERROR_DEVICE_GUID },
93 { .efi_guid_name = "GOP",
94 .efi_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID },
95 { .efi_guid_name = "UGA draw", .efi_guid = EFI_UGA_DRAW_PROTOCOL_GUID },
96 { .efi_guid_name = "PXE base code",
97 .efi_guid = EFI_PXE_BASE_CODE_PROTOCOL },
98 { .efi_guid_name = "PXE base code callback",
99 .efi_guid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL },
100 { .efi_guid_name = "serial io", .efi_guid = SERIAL_IO_PROTOCOL },
101 { .efi_guid_name = "loaded image", .efi_guid = LOADED_IMAGE_PROTOCOL },
102 { .efi_guid_name = "loaded image device path",
103 .efi_guid = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID },
104 { .efi_guid_name = "ISA io", .efi_guid = EFI_ISA_IO_PROTOCOL_GUID },
105 { .efi_guid_name = "IDE controller init",
106 .efi_guid = EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID },
107 { .efi_guid_name = "ISA ACPI", .efi_guid = EFI_ISA_ACPI_PROTOCOL_GUID },
108 { .efi_guid_name = "PCI", .efi_guid = EFI_PCI_IO_PROTOCOL_GUID },
109 { .efi_guid_name = "PCI root", .efi_guid = EFI_PCI_ROOT_IO_GUID },
110 { .efi_guid_name = "PCI enumeration",
111 .efi_guid = EFI_PCI_ENUMERATION_COMPLETE_GUID },
112 { .efi_guid_name = "Driver diagnostics",
113 .efi_guid = EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID },
114 { .efi_guid_name = "Driver diagnostics2",
115 .efi_guid = EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID },
116 { .efi_guid_name = "simple pointer",
117 .efi_guid = EFI_SIMPLE_POINTER_PROTOCOL_GUID },
118 { .efi_guid_name = "absolute pointer",
119 .efi_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID },
120 { .efi_guid_name = "VLAN config",
121 .efi_guid = EFI_VLAN_CONFIG_PROTOCOL_GUID },
122 { .efi_guid_name = "ARP service binding",
123 .efi_guid = EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID },
124 { .efi_guid_name = "ARP", .efi_guid = EFI_ARP_PROTOCOL_GUID },
125 { .efi_guid_name = "IPv4 service binding",
126 .efi_guid = EFI_IP4_SERVICE_BINDING_PROTOCOL },
127 { .efi_guid_name = "IPv4", .efi_guid = EFI_IP4_PROTOCOL },
128 { .efi_guid_name = "IPv4 config",
129 .efi_guid = EFI_IP4_CONFIG_PROTOCOL_GUID },
130 { .efi_guid_name = "IPv6 service binding",
131 .efi_guid = EFI_IP6_SERVICE_BINDING_PROTOCOL },
132 { .efi_guid_name = "IPv6", .efi_guid = EFI_IP6_PROTOCOL },
133 { .efi_guid_name = "IPv6 config",
134 .efi_guid = EFI_IP6_CONFIG_PROTOCOL_GUID },
135 { .efi_guid_name = "UDPv4", .efi_guid = EFI_UDP4_PROTOCOL },
136 { .efi_guid_name = "UDPv4 service binding",
137 .efi_guid = EFI_UDP4_SERVICE_BINDING_PROTOCOL },
138 { .efi_guid_name = "UDPv6", .efi_guid = EFI_UDP6_PROTOCOL },
139 { .efi_guid_name = "UDPv6 service binding",
140 .efi_guid = EFI_UDP6_SERVICE_BINDING_PROTOCOL },
141 { .efi_guid_name = "TCPv4", .efi_guid = EFI_TCP4_PROTOCOL },
142 { .efi_guid_name = "TCPv4 service binding",
143 .efi_guid = EFI_TCP4_SERVICE_BINDING_PROTOCOL },
144 { .efi_guid_name = "TCPv6", .efi_guid = EFI_TCP6_PROTOCOL },
145 { .efi_guid_name = "TCPv6 service binding",
146 .efi_guid = EFI_TCP6_SERVICE_BINDING_PROTOCOL },
147 { .efi_guid_name = "EFI System partition",
148 .efi_guid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID },
149 { .efi_guid_name = "MBR legacy",
150 .efi_guid = EFI_PART_TYPE_LEGACY_MBR_GUID },
151 { .efi_guid_name = "device tree", .efi_guid = EFI_DEVICE_TREE_GUID },
152 { .efi_guid_name = "USB io", .efi_guid = EFI_USB_IO_PROTOCOL_GUID },
153 { .efi_guid_name = "USB2 HC", .efi_guid = EFI_USB2_HC_PROTOCOL_GUID },
154 { .efi_guid_name = "component name",
155 .efi_guid = EFI_COMPONENT_NAME_PROTOCOL_GUID },
156 { .efi_guid_name = "component name2",
157 .efi_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID },
158 { .efi_guid_name = "driver binding",
159 .efi_guid = EFI_DRIVER_BINDING_PROTOCOL_GUID },
160 { .efi_guid_name = "driver configuration",
161 .efi_guid = EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID },
162 { .efi_guid_name = "driver configuration2",
163 .efi_guid = EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID },
164 { .efi_guid_name = "decompress",
165 .efi_guid = EFI_DECOMPRESS_PROTOCOL_GUID },
166 { .efi_guid_name = "ebc interpreter",
167 .efi_guid = EFI_EBC_INTERPRETER_PROTOCOL_GUID },
168 { .efi_guid_name = "network interface identifier",
169 .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL },
170 { .efi_guid_name = "network interface identifier_31",
171 .efi_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_31 },
172 { .efi_guid_name = "managed network service binding",
173 .efi_guid = EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID },
174 { .efi_guid_name = "managed network",
175 .efi_guid = EFI_MANAGED_NETWORK_PROTOCOL_GUID },
176 { .efi_guid_name = "form browser",
177 .efi_guid = EFI_FORM_BROWSER2_PROTOCOL_GUID },
178 { .efi_guid_name = "HII config routing",
179 .efi_guid = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID },
180 { .efi_guid_name = "HII database",
181 .efi_guid = EFI_HII_DATABASE_PROTOCOL_GUID },
182 { .efi_guid_name = "HII string",
183 .efi_guid = EFI_HII_STRING_PROTOCOL_GUID },
184 { .efi_guid_name = "HII image",
185 .efi_guid = EFI_HII_IMAGE_PROTOCOL_GUID },
186 { .efi_guid_name = "HII font", .efi_guid = EFI_HII_FONT_PROTOCOL_GUID },
187 { .efi_guid_name = "HII config",
188 .efi_guid = EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID },
189 { .efi_guid_name = "MTFTP4 service binding",
190 .efi_guid = EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID },
191 { .efi_guid_name = "MTFTP4", .efi_guid = EFI_MTFTP4_PROTOCOL_GUID },
192 { .efi_guid_name = "MTFTP6 service binding",
193 .efi_guid = EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID },
194 { .efi_guid_name = "MTFTP6", .efi_guid = EFI_MTFTP6_PROTOCOL_GUID },
195 { .efi_guid_name = "DHCP4 service binding",
196 .efi_guid = EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID },
197 { .efi_guid_name = "DHCP4", .efi_guid = EFI_DHCP4_PROTOCOL_GUID },
198 { .efi_guid_name = "DHCP6 service binding",
199 .efi_guid = EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID },
200 { .efi_guid_name = "DHCP6", .efi_guid = EFI_DHCP6_PROTOCOL_GUID },
201 { .efi_guid_name = "SCSI io", .efi_guid = EFI_SCSI_IO_PROTOCOL_GUID },
202 { .efi_guid_name = "SCSI pass thru",
203 .efi_guid = EFI_SCSI_PASS_THRU_PROTOCOL_GUID },
204 { .efi_guid_name = "SCSI pass thru ext",
205 .efi_guid = EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID },
206 { .efi_guid_name = "Capsule arch",
207 .efi_guid = EFI_CAPSULE_ARCH_PROTOCOL_GUID },
208 { .efi_guid_name = "monotonic counter arch",
209 .efi_guid = EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID },
210 { .efi_guid_name = "realtime clock arch",
211 .efi_guid = EFI_REALTIME_CLOCK_ARCH_PROTOCOL_GUID },
212 { .efi_guid_name = "variable arch",
213 .efi_guid = EFI_VARIABLE_ARCH_PROTOCOL_GUID },
214 { .efi_guid_name = "variable write arch",
215 .efi_guid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID },
216 { .efi_guid_name = "watchdog timer arch",
217 .efi_guid = EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID },
218 { .efi_guid_name = "ACPI support",
219 .efi_guid = EFI_ACPI_SUPPORT_PROTOCOL_GUID },
220 { .efi_guid_name = "BDS arch", .efi_guid = EFI_BDS_ARCH_PROTOCOL_GUID },
221 { .efi_guid_name = "metronome arch",
222 .efi_guid = EFI_METRONOME_ARCH_PROTOCOL_GUID },
223 { .efi_guid_name = "timer arch",
224 .efi_guid = EFI_TIMER_ARCH_PROTOCOL_GUID },
225 { .efi_guid_name = "DPC", .efi_guid = EFI_DPC_PROTOCOL_GUID },
226 { .efi_guid_name = "print2", .efi_guid = EFI_PRINT2_PROTOCOL_GUID },
227 { .efi_guid_name = "device path to text",
228 .efi_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID },
229 { .efi_guid_name = "reset arch",
230 .efi_guid = EFI_RESET_ARCH_PROTOCOL_GUID },
231 { .efi_guid_name = "CPU arch", .efi_guid = EFI_CPU_ARCH_PROTOCOL_GUID },
232 { .efi_guid_name = "CPU IO2", .efi_guid = EFI_CPU_IO2_PROTOCOL_GUID },
233 { .efi_guid_name = "Legacy 8259",
234 .efi_guid = EFI_LEGACY_8259_PROTOCOL_GUID },
235 { .efi_guid_name = "Security arch",
236 .efi_guid = EFI_SECURITY_ARCH_PROTOCOL_GUID },
237 { .efi_guid_name = "Security2 arch",
238 .efi_guid = EFI_SECURITY2_ARCH_PROTOCOL_GUID },
239 { .efi_guid_name = "Runtime arch",
240 .efi_guid = EFI_RUNTIME_ARCH_PROTOCOL_GUID },
241 { .efi_guid_name = "status code runtime",
242 .efi_guid = EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID },
243 { .efi_guid_name = "data hub", .efi_guid = EFI_DATA_HUB_PROTOCOL_GUID },
244 { .efi_guid_name = "PCD", .efi_guid = PCD_PROTOCOL_GUID },
245 { .efi_guid_name = "EFI PCD", .efi_guid = EFI_PCD_PROTOCOL_GUID },
246 { .efi_guid_name = "firmware volume block",
247 .efi_guid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID },
248 { .efi_guid_name = "firmware volume2",
249 .efi_guid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID },
250 { .efi_guid_name = "firmware volume dispatch",
251 .efi_guid = EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID },
252 { .efi_guid_name = "lzma compress", .efi_guid = LZMA_COMPRESS_GUID },
253 { .efi_guid_name = "MP services",
254 .efi_guid = EFI_MP_SERVICES_PROTOCOL_GUID },
255 { .efi_guid_name = MTC_VARIABLE_NAME, .efi_guid = MTC_VENDOR_GUID },
256 { .efi_guid_name = "RTC", .efi_guid = { 0x378D7B65, 0x8DA9, 0x4773,
257 { 0xB6, 0xE4, 0xA4, 0x78, 0x26, 0xA8, 0x33, 0xE1} } },
258 { .efi_guid_name = "Active EDID",
259 .efi_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID },
260 { .efi_guid_name = "Discovered EDID",
261 .efi_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID }
262 };
263
264 bool
efi_guid_to_str(const EFI_GUID * guid,char ** sp)265 efi_guid_to_str(const EFI_GUID *guid, char **sp)
266 {
267 uint32_t status;
268
269 uuid_to_string((const uuid_t *)guid, sp, &status);
270 return (status == uuid_s_ok ? true : false);
271 }
272
273 bool
efi_str_to_guid(const char * s,EFI_GUID * guid)274 efi_str_to_guid(const char *s, EFI_GUID *guid)
275 {
276 uint32_t status;
277
278 uuid_from_string(s, (uuid_t *)guid, &status);
279 return (status == uuid_s_ok ? true : false);
280 }
281
282 bool
efi_name_to_guid(const char * name,EFI_GUID * guid)283 efi_name_to_guid(const char *name, EFI_GUID *guid)
284 {
285 uint32_t i;
286
287 for (i = 0; i < nitems(efi_uuid_mapping); i++) {
288 if (strcasecmp(name, efi_uuid_mapping[i].efi_guid_name) == 0) {
289 *guid = efi_uuid_mapping[i].efi_guid;
290 return (true);
291 }
292 }
293 return (efi_str_to_guid(name, guid));
294 }
295
296 bool
efi_guid_to_name(EFI_GUID * guid,char ** name)297 efi_guid_to_name(EFI_GUID *guid, char **name)
298 {
299 uint32_t i;
300 int rv;
301
302 for (i = 0; i < nitems(efi_uuid_mapping); i++) {
303 rv = uuid_equal((uuid_t *)guid,
304 (uuid_t *)&efi_uuid_mapping[i].efi_guid, NULL);
305 if (rv != 0) {
306 *name = strdup(efi_uuid_mapping[i].efi_guid_name);
307 if (*name == NULL)
308 return (false);
309 return (true);
310 }
311 }
312 return (efi_guid_to_str(guid, name));
313 }
314
315 /*
316 * Simple wrappers to the underlying UEFI functions.
317 * See http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES
318 * for details.
319 */
320 EFI_STATUS
efi_get_next_variable_name(UINTN * variable_name_size,CHAR16 * variable_name,EFI_GUID * vendor_guid)321 efi_get_next_variable_name(UINTN *variable_name_size, CHAR16 *variable_name,
322 EFI_GUID *vendor_guid)
323 {
324 return (RS->GetNextVariableName(variable_name_size, variable_name,
325 vendor_guid));
326 }
327
328 EFI_STATUS
efi_get_variable(CHAR16 * variable_name,EFI_GUID * vendor_guid,UINT32 * attributes,UINTN * data_size,void * data)329 efi_get_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid,
330 UINT32 *attributes, UINTN *data_size, void *data)
331 {
332 return (RS->GetVariable(variable_name, vendor_guid, attributes,
333 data_size, data));
334 }
335
336 EFI_STATUS
efi_set_variable(CHAR16 * variable_name,EFI_GUID * vendor_guid,UINT32 attributes,UINTN data_size,void * data)337 efi_set_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid,
338 UINT32 attributes, UINTN data_size, void *data)
339 {
340 return (RS->SetVariable(variable_name, vendor_guid, attributes,
341 data_size, data));
342 }
343
344 void
efi_init_environment(void)345 efi_init_environment(void)
346 {
347 char var[128];
348
349 snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
350 ST->Hdr.Revision & 0xffff);
351 env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
352 }
353
354 COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
355
356 static int
efi_print_other_value(uint8_t * data,UINTN datasz)357 efi_print_other_value(uint8_t *data, UINTN datasz)
358 {
359 UINTN i;
360 bool is_ascii = true;
361
362 printf(" = ");
363 for (i = 0; i < datasz - 1; i++) {
364 /*
365 * Quick hack to see if this ascii-ish string is printable
366 * range plus tab, cr and lf.
367 */
368 if ((data[i] < 32 || data[i] > 126)
369 && data[i] != 9 && data[i] != 10 && data[i] != 13) {
370 is_ascii = false;
371 break;
372 }
373 }
374 if (data[datasz - 1] != '\0')
375 is_ascii = false;
376 if (is_ascii == true) {
377 printf("%s", data);
378 if (pager_output("\n"))
379 return (CMD_WARN);
380 } else {
381 if (pager_output("\n"))
382 return (CMD_WARN);
383 /*
384 * Dump hex bytes grouped by 4.
385 */
386 for (i = 0; i < datasz; i++) {
387 printf("%02x ", data[i]);
388 if ((i + 1) % 4 == 0)
389 printf(" ");
390 if ((i + 1) % 20 == 0) {
391 if (pager_output("\n"))
392 return (CMD_WARN);
393 }
394 }
395 if (pager_output("\n"))
396 return (CMD_WARN);
397 }
398
399 return (CMD_OK);
400 }
401
402 /* This appears to be some sort of UEFI shell alias table. */
403 static int
efi_print_shell_str(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz)404 efi_print_shell_str(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
405 {
406 printf(" = %S", (CHAR16 *)data);
407 if (pager_output("\n"))
408 return (CMD_WARN);
409 return (CMD_OK);
410 }
411
412 const char *
efi_memory_type(EFI_MEMORY_TYPE type)413 efi_memory_type(EFI_MEMORY_TYPE type)
414 {
415 const char *types[] = {
416 "Reserved",
417 "LoaderCode",
418 "LoaderData",
419 "BootServicesCode",
420 "BootServicesData",
421 "RuntimeServicesCode",
422 "RuntimeServicesData",
423 "ConventionalMemory",
424 "UnusableMemory",
425 "ACPIReclaimMemory",
426 "ACPIMemoryNVS",
427 "MemoryMappedIO",
428 "MemoryMappedIOPortSpace",
429 "PalCode",
430 "PersistentMemory"
431 };
432 switch (type) {
433 case EfiReservedMemoryType:
434 case EfiLoaderCode:
435 case EfiLoaderData:
436 case EfiBootServicesCode:
437 case EfiBootServicesData:
438 case EfiRuntimeServicesCode:
439 case EfiRuntimeServicesData:
440 case EfiConventionalMemory:
441 case EfiUnusableMemory:
442 case EfiACPIReclaimMemory:
443 case EfiACPIMemoryNVS:
444 case EfiMemoryMappedIO:
445 case EfiMemoryMappedIOPortSpace:
446 case EfiPalCode:
447 case EfiPersistentMemory:
448 return (types[type]);
449 }
450 return ("Unknown");
451 }
452
453 /* Print memory type table. */
454 static int
efi_print_mem_type(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz)455 efi_print_mem_type(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
456 {
457 int i, n;
458 EFI_MEMORY_TYPE_INFORMATION *ti;
459
460 ti = (EFI_MEMORY_TYPE_INFORMATION *)data;
461 if (pager_output(" = \n"))
462 return (CMD_WARN);
463
464 n = datasz / sizeof (EFI_MEMORY_TYPE_INFORMATION);
465 for (i = 0; i < n && ti[i].NumberOfPages != 0; i++) {
466 printf("\t%23s pages: %u", efi_memory_type(ti[i].Type),
467 ti[i].NumberOfPages);
468 if (pager_output("\n"))
469 return (CMD_WARN);
470 }
471
472 return (CMD_OK);
473 }
474
475 /* Print global variables. */
476 static int
efi_print_global(const CHAR16 * varnamearg,uint8_t * data,UINTN datasz)477 efi_print_global(const CHAR16 *varnamearg, uint8_t *data, UINTN datasz)
478 {
479 int len;
480 int rv = -1;
481 char *var;
482
483 for (len = 0; varnamearg[len] != 0; len++)
484 ;
485
486 if (len == 0)
487 return (CMD_OK);
488 len++;
489
490 if ((var = malloc(len)) == NULL)
491 return (CMD_ERROR);
492 cpy16to8(varnamearg, var, len);
493
494 if (strcmp("AuditMode", var) == 0) {
495 printf(" = ");
496 printf("0x%x", *data); /* 8-bit int */
497 goto done;
498 }
499
500 if (strcmp("BootOptionSupport", var) == 0) {
501 printf(" = ");
502 printf("0x%x", *((uint32_t *)data)); /* UINT32 */
503 goto done;
504 }
505
506 if (strcmp("BootCurrent", var) == 0 ||
507 strcmp("BootNext", var) == 0 ||
508 strcmp("Timeout", var) == 0) {
509 printf(" = ");
510 printf("%u", *((uint16_t *)data)); /* UINT16 */
511 goto done;
512 }
513
514 if (strcmp("BootOrder", var) == 0 ||
515 strcmp("DriverOrder", var) == 0) {
516 int i;
517 UINT16 *u16 = (UINT16 *)data;
518
519 printf(" =");
520 for (i = 0; i < datasz / sizeof (UINT16); i++)
521 printf(" %u", u16[i]);
522 goto done;
523 }
524 if (strncmp("Boot", var, 4) == 0 ||
525 strncmp("Driver", var, 5) == 0 ||
526 strncmp("SysPrep", var, 7) == 0 ||
527 strncmp("OsRecovery", var, 10) == 0) {
528 UINT32 attr;
529 UINT16 filepathlistlen;
530 CHAR16 *text;
531 int desclen;
532 EFI_DEVICE_PATH *dp;
533
534 attr = *(uint32_t *)data;
535 data += sizeof(UINT32);
536 filepathlistlen = *(uint16_t *)data;
537 data += sizeof (UINT16);
538 text = (CHAR16 *)data;
539
540 for (desclen = 0; text[desclen] != 0; desclen++)
541 ;
542 if (desclen != 0) {
543 /* Add terminating zero and we have CHAR16. */
544 desclen = (desclen + 1) * 2;
545 }
546
547 printf(" = ");
548 printf("%S", text);
549 if (filepathlistlen != 0) {
550 /* Output pathname from new line. */
551 if (pager_output("\n")) {
552 rv = CMD_WARN;
553 goto done;
554 }
555 dp = malloc(filepathlistlen);
556 if (dp == NULL)
557 goto done;
558
559 memcpy(dp, data + desclen, filepathlistlen);
560 text = efi_devpath_name(dp);
561 if (text != NULL) {
562 printf("\t%S", text);
563 efi_free_devpath_name(text);
564 }
565 free(dp);
566 }
567 goto done;
568 }
569
570 if (strcmp("ConIn", var) == 0 ||
571 strcmp("ConInDev", var) == 0 ||
572 strcmp("ConOut", var) == 0 ||
573 strcmp("ConOutDev", var) == 0 ||
574 strcmp("ErrOut", var) == 0 ||
575 strcmp("ErrOutDev", var) == 0) {
576 CHAR16 *text;
577
578 printf(" = ");
579 text = efi_devpath_name((EFI_DEVICE_PATH *)data);
580 if (text != NULL) {
581 printf("%S", text);
582 efi_free_devpath_name(text);
583 }
584 goto done;
585 }
586
587 if (strcmp("PlatformLang", var) == 0 ||
588 strcmp("PlatformLangCodes", var) == 0 ||
589 strcmp("LangCodes", var) == 0 ||
590 strcmp("Lang", var) == 0) {
591 printf(" = ");
592 printf("%s", data); /* ASCII string */
593 goto done;
594 }
595
596 /*
597 * Feature bitmap from firmware to OS.
598 * Older UEFI provides UINT32, newer UINT64.
599 */
600 if (strcmp("OsIndicationsSupported", var) == 0) {
601 printf(" = ");
602 if (datasz == 4)
603 printf("0x%x", *((uint32_t *)data));
604 else
605 printf("0x%jx", *((uint64_t *)data));
606 goto done;
607 }
608
609 /* Fallback for anything else. */
610 rv = efi_print_other_value(data, datasz);
611 done:
612 if (rv == -1) {
613 if (pager_output("\n"))
614 rv = CMD_WARN;
615 else
616 rv = CMD_OK;
617 }
618 free(var);
619 return (rv);
620 }
621
622 static void
efi_print_var_attr(UINT32 attr)623 efi_print_var_attr(UINT32 attr)
624 {
625 bool comma = false;
626
627 if (attr & EFI_VARIABLE_NON_VOLATILE) {
628 printf("NV");
629 comma = true;
630 }
631 if (attr & EFI_VARIABLE_BOOTSERVICE_ACCESS) {
632 if (comma == true)
633 printf(",");
634 printf("BS");
635 comma = true;
636 }
637 if (attr & EFI_VARIABLE_RUNTIME_ACCESS) {
638 if (comma == true)
639 printf(",");
640 printf("RS");
641 comma = true;
642 }
643 if (attr & EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
644 if (comma == true)
645 printf(",");
646 printf("HR");
647 comma = true;
648 }
649 if (attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
650 if (comma == true)
651 printf(",");
652 printf("AT");
653 comma = true;
654 }
655 }
656
657 static int
efi_print_var(CHAR16 * varnamearg,EFI_GUID * matchguid,int lflag)658 efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
659 {
660 UINTN datasz;
661 EFI_STATUS status;
662 UINT32 attr;
663 char *str, *data;
664 int rv = CMD_OK;
665
666 str = NULL;
667 datasz = 0;
668 status = efi_get_variable(varnamearg, matchguid, &attr, &datasz, NULL);
669 if (status != EFI_BUFFER_TOO_SMALL) {
670 printf("Can't get the variable: error %#lx\n",
671 EFI_ERROR_CODE(status));
672 return (CMD_ERROR);
673 }
674 data = malloc(datasz);
675 if (data == NULL) {
676 printf("Out of memory\n");
677 return (CMD_ERROR);
678 }
679
680 status = efi_get_variable(varnamearg, matchguid, &attr, &datasz, data);
681 if (status != EFI_SUCCESS) {
682 printf("Can't get the variable: error %#lx\n",
683 EFI_ERROR_CODE(status));
684 free(data);
685 return (CMD_ERROR);
686 }
687
688 if (efi_guid_to_name(matchguid, &str) == false) {
689 rv = CMD_ERROR;
690 goto done;
691 }
692 printf("%s ", str);
693 efi_print_var_attr(attr);
694 printf(" %S", varnamearg);
695
696 if (lflag == 0) {
697 if (strcmp(str, "global") == 0)
698 rv = efi_print_global(varnamearg, data, datasz);
699 else if (strcmp(str,
700 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME) == 0)
701 rv = efi_print_mem_type(varnamearg, data, datasz);
702 else if (strcmp(str,
703 "47c7b227-c42a-11d2-8e57-00a0c969723b") == 0)
704 rv = efi_print_shell_str(varnamearg, data, datasz);
705 else if (strcmp(str, MTC_VARIABLE_NAME) == 0) {
706 printf(" = ");
707 printf("%u", *((uint32_t *)data)); /* UINT32 */
708 rv = CMD_OK;
709 if (pager_output("\n"))
710 rv = CMD_WARN;
711 } else
712 rv = efi_print_other_value(data, datasz);
713 } else if (pager_output("\n"))
714 rv = CMD_WARN;
715
716 done:
717 free(str);
718 free(data);
719 return (rv);
720 }
721
722 static int
command_efi_show(int argc,char * argv[])723 command_efi_show(int argc, char *argv[])
724 {
725 /*
726 * efi-show [-a]
727 * print all the env
728 * efi-show -g UUID
729 * print all the env vars tagged with UUID
730 * efi-show -v var
731 * search all the env vars and print the ones matching var
732 * eif-show -g UUID -v var
733 * eif-show UUID var
734 * print all the env vars that match UUID and var
735 */
736 /* NB: We assume EFI_GUID is the same as uuid_t */
737 int aflag = 0, gflag = 0, lflag = 0, vflag = 0;
738 int ch, rv;
739 unsigned i;
740 EFI_STATUS status;
741 EFI_GUID varguid = ZERO_GUID;
742 EFI_GUID matchguid = ZERO_GUID;
743 CHAR16 *varname;
744 CHAR16 *newnm;
745 CHAR16 varnamearg[128];
746 UINTN varalloc;
747 UINTN varsz;
748
749 optind = 1;
750 optreset = 1;
751 opterr = 1;
752
753 while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
754 switch (ch) {
755 case 'a':
756 aflag = 1;
757 break;
758 case 'g':
759 gflag = 1;
760 if (efi_name_to_guid(optarg, &matchguid) == false) {
761 printf("uuid %s could not be parsed\n", optarg);
762 return (CMD_ERROR);
763 }
764 break;
765 case 'l':
766 lflag = 1;
767 break;
768 case 'v':
769 vflag = 1;
770 if (strlen(optarg) >= nitems(varnamearg)) {
771 printf("Variable %s is longer than %zd "
772 "characters\n", optarg, nitems(varnamearg));
773 return (CMD_ERROR);
774 }
775 cpy8to16(optarg, varnamearg, nitems(varnamearg));
776 break;
777 default:
778 return (CMD_ERROR);
779 }
780 }
781
782 if (argc == 1) /* default is -a */
783 aflag = 1;
784
785 if (aflag && (gflag || vflag)) {
786 printf("-a isn't compatible with -g or -v\n");
787 return (CMD_ERROR);
788 }
789
790 if (aflag && optind < argc) {
791 printf("-a doesn't take any args\n");
792 return (CMD_ERROR);
793 }
794
795 argc -= optind;
796 argv += optind;
797
798 pager_open();
799 if (vflag && gflag) {
800 rv = efi_print_var(varnamearg, &matchguid, lflag);
801 if (rv == CMD_WARN)
802 rv = CMD_OK;
803 pager_close();
804 return (rv);
805 }
806
807 if (argc == 2) {
808 optarg = argv[0];
809 if (strlen(optarg) >= nitems(varnamearg)) {
810 printf("Variable %s is longer than %zd characters\n",
811 optarg, nitems(varnamearg));
812 pager_close();
813 return (CMD_ERROR);
814 }
815 for (i = 0; i < strlen(optarg); i++)
816 varnamearg[i] = optarg[i];
817 varnamearg[i] = 0;
818 optarg = argv[1];
819 if (efi_name_to_guid(optarg, &matchguid) == false) {
820 printf("uuid %s could not be parsed\n", optarg);
821 pager_close();
822 return (CMD_ERROR);
823 }
824 rv = efi_print_var(varnamearg, &matchguid, lflag);
825 if (rv == CMD_WARN)
826 rv = CMD_OK;
827 pager_close();
828 return (rv);
829 }
830
831 if (argc > 0) {
832 printf("Too many args: %d\n", argc);
833 pager_close();
834 return (CMD_ERROR);
835 }
836
837 /*
838 * Initiate the search -- note the standard takes pain
839 * to specify the initial call must be a poiner to a NULL
840 * character.
841 */
842 varalloc = 1024;
843 varname = malloc(varalloc);
844 if (varname == NULL) {
845 printf("Can't allocate memory to get variables\n");
846 pager_close();
847 return (CMD_ERROR);
848 }
849 varname[0] = 0;
850 while (1) {
851 varsz = varalloc;
852 status = efi_get_next_variable_name(&varsz, varname, &varguid);
853 if (status == EFI_BUFFER_TOO_SMALL) {
854 varalloc = varsz;
855 newnm = realloc(varname, varalloc);
856 if (newnm == NULL) {
857 printf("Can't allocate memory to get "
858 "variables\n");
859 rv = CMD_ERROR;
860 break;
861 }
862 varname = newnm;
863 continue; /* Try again with bigger buffer */
864 }
865 if (status == EFI_NOT_FOUND) {
866 rv = CMD_OK;
867 break;
868 }
869 if (status != EFI_SUCCESS) {
870 rv = CMD_ERROR;
871 break;
872 }
873
874 if (aflag) {
875 rv = efi_print_var(varname, &varguid, lflag);
876 if (rv != CMD_OK) {
877 if (rv == CMD_WARN)
878 rv = CMD_OK;
879 break;
880 }
881 continue;
882 }
883 if (vflag) {
884 if (wcscmp(varnamearg, varname) == 0) {
885 rv = efi_print_var(varname, &varguid, lflag);
886 if (rv != CMD_OK) {
887 if (rv == CMD_WARN)
888 rv = CMD_OK;
889 break;
890 }
891 continue;
892 }
893 }
894 if (gflag) {
895 rv = uuid_equal((uuid_t *)&varguid,
896 (uuid_t *)&matchguid, NULL);
897 if (rv != 0) {
898 rv = efi_print_var(varname, &varguid, lflag);
899 if (rv != CMD_OK) {
900 if (rv == CMD_WARN)
901 rv = CMD_OK;
902 break;
903 }
904 continue;
905 }
906 }
907 }
908 free(varname);
909 pager_close();
910
911 return (rv);
912 }
913
914 COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set);
915
916 static int
command_efi_set(int argc,char * argv[])917 command_efi_set(int argc, char *argv[])
918 {
919 char *uuid, *var, *val;
920 CHAR16 wvar[128];
921 EFI_GUID guid;
922 EFI_STATUS err;
923
924 if (argc != 4) {
925 printf("efi-set uuid var new-value\n");
926 return (CMD_ERROR);
927 }
928 uuid = argv[1];
929 var = argv[2];
930 val = argv[3];
931 if (efi_name_to_guid(uuid, &guid) == false) {
932 printf("Invalid uuid %s\n", uuid);
933 return (CMD_ERROR);
934 }
935 cpy8to16(var, wvar, nitems(wvar));
936 #if 0
937 err = efi_set_variable(wvar, &guid, EFI_VARIABLE_NON_VOLATILE |
938 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
939 strlen(val) + 1, val);
940 if (EFI_ERROR(err)) {
941 printf("Failed to set variable: error %lu\n",
942 EFI_ERROR_CODE(err));
943 return (CMD_ERROR);
944 }
945 #else
946 printf("would set %s %s = %s\n", uuid, var, val);
947 #endif
948 return (CMD_OK);
949 }
950
951 COMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", command_efi_unset);
952
953 static int
command_efi_unset(int argc,char * argv[])954 command_efi_unset(int argc, char *argv[])
955 {
956 char *uuid, *var;
957 CHAR16 wvar[128];
958 EFI_GUID guid;
959 EFI_STATUS err;
960
961 if (argc != 3) {
962 printf("efi-unset uuid var\n");
963 return (CMD_ERROR);
964 }
965 uuid = argv[1];
966 var = argv[2];
967 if (efi_name_to_guid(uuid, &guid) == false) {
968 printf("Invalid uuid %s\n", uuid);
969 return (CMD_ERROR);
970 }
971 cpy8to16(var, wvar, nitems(wvar));
972 #if 0
973 err = efi_set_variable(wvar, &guid, 0, 0, NULL);
974 if (EFI_ERROR(err)) {
975 printf("Failed to unset variable: error %lu\n",
976 EFI_ERROR_CODE(err));
977 return (CMD_ERROR);
978 }
979 #else
980 printf("would unset %s %s \n", uuid, var);
981 #endif
982 return (CMD_OK);
983 }
984
985 /*
986 * Loader interaction words and extras
987 *
988 * efi-setenv ( value n name n guid n attr -- 0 | -1)
989 * efi-getenv ( guid n addr n -- addr' n' | -1 )
990 * efi-unsetenv ( name n guid n'' -- )
991 */
992
993 /*
994 * efi-setenv
995 * efi-setenv ( value n name n guid n attr -- 0 | -1)
996 *
997 * Set environment variables using the SetVariable EFI runtime service.
998 *
999 * Value and guid are passed through in binary form (so guid needs to be
1000 * converted to binary form from its string form). Name is converted from
1001 * ASCII to CHAR16. Since ficl doesn't have support for internationalization,
1002 * there's no native CHAR16 interface provided.
1003 *
1004 * attr is an int in the bitmask of the following attributes for this variable.
1005 *
1006 * 1 Non volatile
1007 * 2 Boot service access
1008 * 4 Run time access
1009 * (corresponding to the same bits in the UEFI spec).
1010 */
1011 static void
ficlEfiSetenv(ficlVm * pVM)1012 ficlEfiSetenv(ficlVm *pVM)
1013 {
1014 char *value = NULL, *guid = NULL;
1015 CHAR16 *name = NULL;
1016 int i;
1017 char *namep, *valuep, *guidp;
1018 int names, values, guids, attr;
1019 EFI_STATUS status;
1020 uuid_t u;
1021 uint32_t ustatus;
1022 char *error = NULL;
1023 ficlStack *pStack = ficlVmGetDataStack(pVM);
1024
1025 FICL_STACK_CHECK(pStack, 6, 0);
1026
1027 attr = ficlStackPopInteger(pStack);
1028 guids = ficlStackPopInteger(pStack);
1029 guidp = (char*)ficlStackPopPointer(pStack);
1030 names = ficlStackPopInteger(pStack);
1031 namep = (char*)ficlStackPopPointer(pStack);
1032 values = ficlStackPopInteger(pStack);
1033 valuep = (char*)ficlStackPopPointer(pStack);
1034
1035 guid = ficlMalloc(guids);
1036 if (guid == NULL)
1037 goto out;
1038 memcpy(guid, guidp, guids);
1039 uuid_from_string(guid, &u, &ustatus);
1040 if (ustatus != uuid_s_ok) {
1041 switch (ustatus) {
1042 case uuid_s_bad_version:
1043 error = "uuid: bad string";
1044 break;
1045 case uuid_s_invalid_string_uuid:
1046 error = "uuid: invalid string";
1047 break;
1048 case uuid_s_no_memory:
1049 error = "Out of memory";
1050 break;
1051 default:
1052 error = "uuid: Unknown error";
1053 break;
1054 }
1055 ficlStackPushInteger(pStack, -1);
1056 goto out;
1057 }
1058
1059 name = ficlMalloc((names + 1) * sizeof (CHAR16));
1060 if (name == NULL) {
1061 error = "Out of memory";
1062 goto out;
1063 }
1064 for (i = 0; i < names; i++)
1065 name[i] = namep[i];
1066 name[names] = 0;
1067
1068 value = ficlMalloc(values + 1);
1069 if (value == NULL) {
1070 error = "Out of memory";
1071 goto out;
1072 }
1073 memcpy(value, valuep, values);
1074
1075 status = efi_set_variable(name, (EFI_GUID *)&u, attr, values, value);
1076 if (status == EFI_SUCCESS) {
1077 ficlStackPushInteger(pStack, 0);
1078 } else {
1079 ficlStackPushInteger(pStack, -1);
1080 error = "Error: efi_set_variable failed";
1081 }
1082
1083 out:
1084 ficlFree(name);
1085 ficlFree(value);
1086 ficlFree(guid);
1087 if (error != NULL)
1088 ficlVmThrowError(pVM, error);
1089 }
1090
1091 static void
ficlEfiGetenv(ficlVm * pVM)1092 ficlEfiGetenv(ficlVm *pVM)
1093 {
1094 char *name, *value;
1095 char *namep;
1096 int names;
1097
1098 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2);
1099
1100 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1101 namep = (char*)ficlStackPopPointer(ficlVmGetDataStack(pVM));
1102
1103 name = ficlMalloc(names+1);
1104 if (name == NULL)
1105 ficlVmThrowError(pVM, "Error: out of memory");
1106 strncpy(name, namep, names);
1107 name[names] = '\0';
1108
1109 value = getenv(name);
1110 ficlFree(name);
1111
1112 if(value != NULL) {
1113 ficlStackPushPointer(ficlVmGetDataStack(pVM), value);
1114 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value));
1115 } else {
1116 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
1117 }
1118 }
1119
1120 static void
ficlEfiUnsetenv(ficlVm * pVM)1121 ficlEfiUnsetenv(ficlVm *pVM)
1122 {
1123 char *name;
1124 char *namep;
1125 int names;
1126
1127 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
1128
1129 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1130 namep = (char*)ficlStackPopPointer(ficlVmGetDataStack(pVM));
1131
1132 name = ficlMalloc(names+1);
1133 if (name == NULL)
1134 ficlVmThrowError(pVM, "Error: out of memory");
1135 strncpy(name, namep, names);
1136 name[names] = '\0';
1137
1138 unsetenv(name);
1139 ficlFree(name);
1140 }
1141
1142 /*
1143 * Build platform extensions into the system dictionary
1144 */
1145 static void
ficlEfiCompilePlatform(ficlSystem * pSys)1146 ficlEfiCompilePlatform(ficlSystem *pSys)
1147 {
1148 ficlDictionary *dp = ficlSystemGetDictionary(pSys);
1149
1150 FICL_SYSTEM_ASSERT(pSys, dp);
1151
1152 ficlDictionarySetPrimitive(dp, "efi-setenv", ficlEfiSetenv,
1153 FICL_WORD_DEFAULT);
1154 ficlDictionarySetPrimitive(dp, "efi-getenv", ficlEfiGetenv,
1155 FICL_WORD_DEFAULT);
1156 ficlDictionarySetPrimitive(dp, "efi-unsetenv", ficlEfiUnsetenv,
1157 FICL_WORD_DEFAULT);
1158 }
1159
1160 FICL_COMPILE_SET(ficlEfiCompilePlatform);
1161