2 * Copyright (c) 2008-2010 Rui Paulo
3 * Copyright (c) 2006 Marcel Moolenaar
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: head/sys/boot/efi/loader/main.c 295408 2016-02-08 19:34:17Z imp $");
31 #include <sys/param.h>
32 #include <sys/reboot.h>
43 #include <bootstrap.h>
46 #include "loader_efi.h"
48 extern char bootprog_name
[];
49 extern char bootprog_rev
[];
50 extern char bootprog_date
[];
51 extern char bootprog_maker
[];
53 struct arch_switch archsw
; /* MI/MD interface boundary */
55 EFI_GUID acpi
= ACPI_TABLE_GUID
;
56 EFI_GUID acpi20
= ACPI_20_TABLE_GUID
;
57 EFI_GUID devid
= DEVICE_PATH_PROTOCOL
;
58 EFI_GUID imgid
= LOADED_IMAGE_PROTOCOL
;
59 EFI_GUID mps
= MPS_TABLE_GUID
;
60 EFI_GUID netid
= EFI_SIMPLE_NETWORK_PROTOCOL
;
61 EFI_GUID smbios
= SMBIOS_TABLE_GUID
;
62 EFI_GUID dxe
= DXE_SERVICES_TABLE_GUID
;
63 EFI_GUID hoblist
= HOB_LIST_TABLE_GUID
;
64 EFI_GUID memtype
= MEMORY_TYPE_INFORMATION_TABLE_GUID
;
65 EFI_GUID debugimg
= DEBUG_IMAGE_INFO_TABLE_GUID
;
66 EFI_GUID fdtdtb
= FDT_TABLE_GUID
;
67 EFI_GUID inputid
= SIMPLE_TEXT_INPUT_PROTOCOL
;
70 * Need this because EFI uses UTF-16 unicode string constants, but we
71 * use UTF-8. We can't use printf due to the possiblity of \0 and we
72 * don't support support wide characters either.
75 print_str16(const CHAR16
*str
)
79 for (i
= 0; str
[i
]; i
++)
80 printf("%c", (char)str
[i
]);
84 * cpy8to16 copies a traditional C string into a CHAR16 string and
85 * 0 terminates it. len is the size of *dst in bytes.
88 cpy8to16(const char *src
, CHAR16
*dst
, size_t len
)
90 len
<<= 1; /* Assume CHAR16 is 2 bytes */
91 while (len
> 0 && *src
) {
99 cp16to8(const CHAR16
*src
, char *dst
, size_t len
)
103 for (i
= 0; i
< len
&& src
[i
]; i
++)
104 dst
[i
] = (char)src
[i
];
111 EFI_DEVICE_PATH
*path
;
112 EFI_HANDLE
*hin
, *hin_end
, *walker
;
117 * Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
118 * do the typical dance to get the right sized buffer.
122 status
= BS
->LocateHandle(ByProtocol
, &inputid
, 0, &sz
, 0);
123 if (status
== EFI_BUFFER_TOO_SMALL
) {
124 hin
= (EFI_HANDLE
*)malloc(sz
);
125 status
= BS
->LocateHandle(ByProtocol
, &inputid
, 0, &sz
,
127 if (EFI_ERROR(status
))
130 if (EFI_ERROR(status
))
134 * Look at each of the handles. If it supports the device path protocol,
135 * use it to get the device path for this handle. Then see if that
136 * device path matches either the USB device path for keyboards or the
137 * legacy device path for keyboards.
139 hin_end
= &hin
[sz
/ sizeof(*hin
)];
140 for (walker
= hin
; walker
< hin_end
; walker
++) {
141 status
= BS
->HandleProtocol(*walker
, &devid
, (VOID
**)&path
);
142 if (EFI_ERROR(status
))
145 while (!IsDevicePathEnd(path
)) {
147 * Check for the ACPI keyboard node. All PNP3xx nodes
148 * are keyboards of different flavors. Note: It is
149 * unclear of there's always a keyboard node when
150 * there's a keyboard controller, or if there's only one
151 * when a keyboard is detected at boot.
153 if (DevicePathType(path
) == ACPI_DEVICE_PATH
&&
154 (DevicePathSubType(path
) == ACPI_DP
||
155 DevicePathSubType(path
) == ACPI_EXTENDED_DP
)) {
156 ACPI_HID_DEVICE_PATH
*acpi
;
158 acpi
= (ACPI_HID_DEVICE_PATH
*)(void *)path
;
159 if ((EISA_ID_TO_NUM(acpi
->HID
) & 0xff00) == 0x300 &&
160 (acpi
->HID
& 0xffff) == PNP_EISA_ID_CONST
) {
165 * Check for USB keyboard node, if present. Unlike a
166 * PS/2 keyboard, these definitely only appear when
167 * connected to the system.
169 } else if (DevicePathType(path
) == MESSAGING_DEVICE_PATH
&&
170 DevicePathSubType(path
) == MSG_USB_CLASS_DP
) {
171 USB_CLASS_DEVICE_PATH
*usb
;
173 usb
= (USB_CLASS_DEVICE_PATH
*)(void *)path
;
174 if (usb
->DeviceClass
== 3 && /* HID */
175 usb
->DeviceSubClass
== 1 && /* Boot devices */
176 usb
->DeviceProtocol
== 1) { /* Boot keyboards */
181 path
= NextDevicePathNode(path
);
190 main(int argc
, CHAR16
*argv
[])
193 EFI_LOADED_IMAGE
*img
;
195 int i
, j
, vargood
, unit
, howto
;
201 archsw
.arch_autoload
= efi_autoload
;
202 archsw
.arch_getdev
= efi_getdev
;
203 archsw
.arch_copyin
= efi_copyin
;
204 archsw
.arch_copyout
= efi_copyout
;
205 archsw
.arch_readin
= efi_readin
;
207 has_kbd
= has_keyboard();
210 * XXX Chicken-and-egg problem; we want to have console output
211 * early, but some console attributes may depend on reading from
212 * eg. the boot device, which we can't do yet. We can use
213 * printf() etc. once this is done.
218 * Parse the args to set the console settings, etc
219 * boot1.efi passes these in, if it can read /boot.config or /boot/config
220 * or iPXE may be setup to pass these in.
222 * Loop through the args, and for each one that contains an '=' that is
223 * not the first character, add it to the environment. This allows
224 * loader and kernel env vars to be passed on the command line. Convert
225 * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
228 for (i
= 1; i
< argc
; i
++) {
229 if (argv
[i
][0] == '-') {
230 for (j
= 1; argv
[i
][j
] != 0; j
++) {
252 howto
&= ~(RB_MUTE
|RB_VIDEO
);
257 howto
|= RB_DFLTROOT
;
263 if (argv
[i
][j
+ 1] == 0) {
265 setenv("comconsole_speed", "115200", 1);
267 cp16to8(&argv
[i
+ 1][0], var
,
269 setenv("comconsole_speedspeed", var
, 1);
274 cp16to8(&argv
[i
][j
+ 1], var
,
276 setenv("comconsole_speed", var
, 1);
286 for (j
= 0; argv
[i
][j
] != 0; j
++) {
287 if (j
== sizeof(var
)) {
291 if (j
> 0 && argv
[i
][j
] == '=')
293 var
[j
] = (char)argv
[i
][j
];
301 for (i
= 0; howto_names
[i
].ev
!= NULL
; i
++)
302 if (howto
& howto_names
[i
].mask
)
303 setenv(howto_names
[i
].ev
, "YES", 1);
304 if (howto
& RB_SERIAL
) {
305 setenv("console", "comconsole" , 1);
308 if (efi_copy_init()) {
309 printf("failed to allocate staging area\n");
310 return (EFI_BUFFER_TOO_SMALL
);
314 * March through the device switch probing for things.
316 for (i
= 0; devsw
[i
] != NULL
; i
++)
317 if (devsw
[i
]->dv_init
!= NULL
)
318 (devsw
[i
]->dv_init
)();
320 /* Get our loaded image protocol interface structure. */
321 BS
->HandleProtocol(IH
, &imgid
, (VOID
**)&img
);
323 printf("Command line arguments:");
324 for (i
= 0; i
< argc
; i
++) {
326 print_str16(argv
[i
]);
330 printf("Image base: 0x%lx\n", (u_long
)img
->ImageBase
);
331 printf("EFI version: %d.%02d\n", ST
->Hdr
.Revision
>> 16,
332 ST
->Hdr
.Revision
& 0xffff);
333 printf("EFI Firmware: ");
334 /* printf doesn't understand EFI Unicode */
335 ST
->ConOut
->OutputString(ST
->ConOut
, ST
->FirmwareVendor
);
336 printf(" (rev %d.%02d)\n", ST
->FirmwareRevision
>> 16,
337 ST
->FirmwareRevision
& 0xffff);
340 printf("%s, Revision %s\n", bootprog_name
, bootprog_rev
);
341 printf("(%s, %s)\n", bootprog_maker
, bootprog_date
);
344 * Disable the watchdog timer. By default the boot manager sets
345 * the timer to 5 minutes before invoking a boot option. If we
346 * want to return to the boot manager, we have to disable the
347 * watchdog timer and since we're an interactive program, we don't
348 * want to wait until the user types "quit". The timer may have
349 * fired by then. We don't care if this fails. It does not prevent
350 * normal functioning in any way...
352 BS
->SetWatchdogTimer(0, 0, 0, NULL
);
354 if (efi_handle_lookup(img
->DeviceHandle
, &dev
, &unit
, &pool_guid
) != 0)
355 return (EFI_NOT_FOUND
);
357 switch (dev
->dv_type
) {
359 struct efi_devdesc currdev
;
362 currdev
.d_kind
.efidisk
.unit
= unit
;
363 currdev
.d_kind
.efidisk
.data
= NULL
;
364 currdev
.d_type
= currdev
.d_dev
->dv_type
;
365 env_setenv("currdev", EV_VOLATILE
, efi_fmtdev(&currdev
),
366 efi_setcurrdev
, env_nounset
);
367 env_setenv("loaddev", EV_VOLATILE
, efi_fmtdev(&currdev
), env_noset
,
374 setenv("ehci_load", "YES", 1);
377 setenv("xhci_load", "YES", 1);
379 /* Check if ACPI is available */
380 if (efi_get_table(&acpi20
) != NULL
||
381 efi_get_table(&acpi
) != NULL
) {
382 setenv("acpi_load", "YES", 1);
385 setenv("LINES", "24", 1); /* optional */
387 for (k
= 0; k
< ST
->NumberOfTableEntries
; k
++) {
388 guid
= &ST
->ConfigurationTable
[k
].VendorGuid
;
389 if (!memcmp(guid
, &smbios
, sizeof(EFI_GUID
))) {
390 smbios_detect(ST
->ConfigurationTable
[k
].VendorTable
);
395 interact(); /* doesn't return */
397 return (EFI_SUCCESS
); /* keep compiler happy */
400 /* XXX move to lib stand ? */
402 wcscmp(CHAR16
*a
, CHAR16
*b
)
405 while (*a
&& *b
&& *a
== *b
) {
413 COMMAND_SET(reboot
, "reboot", "reboot the system", command_reboot
);
416 command_reboot(int argc
, char *argv
[])
420 for (i
= 0; devsw
[i
] != NULL
; ++i
)
421 if (devsw
[i
]->dv_cleanup
!= NULL
)
422 (devsw
[i
]->dv_cleanup
)();
424 RS
->ResetSystem(EfiResetCold
, EFI_SUCCESS
, 23,
425 (CHAR16
*)"Reboot from the loader");
431 COMMAND_SET(quit
, "quit", "exit the loader", command_quit
);
434 command_quit(int argc
, char *argv
[])
440 COMMAND_SET(memmap
, "memmap", "print memory map", command_memmap
);
443 command_memmap(int argc
, char *argv
[])
446 EFI_MEMORY_DESCRIPTOR
*map
, *p
;
452 static char *types
[] = {
458 "RuntimeServicesCode",
459 "RuntimeServicesData",
460 "ConventionalMemory",
465 "MemoryMappedIOPortSpace",
470 status
= BS
->GetMemoryMap(&sz
, 0, &key
, &dsz
, &dver
);
471 if (status
!= EFI_BUFFER_TOO_SMALL
) {
472 printf("Can't determine memory map size\n");
476 status
= BS
->GetMemoryMap(&sz
, map
, &key
, &dsz
, &dver
);
477 if (EFI_ERROR(status
)) {
478 printf("Can't read memory map\n");
483 snprintf(line
, sizeof(line
), "%23s %12s %12s %8s %4s\n",
484 "Type", "Physical", "Virtual", "#Pages", "Attr");
486 if (pager_output(line
)) {
491 for (i
= 0, p
= map
; i
< ndesc
;
492 i
++, p
= NextMemoryDescriptor(p
, dsz
)) {
493 printf("%23s %012jx %012jx %08jx ", types
[p
->Type
],
494 (uintmax_t)p
->PhysicalStart
, (uintmax_t)p
->VirtualStart
,
495 (uintmax_t)p
->NumberOfPages
);
496 if (p
->Attribute
& EFI_MEMORY_UC
)
498 if (p
->Attribute
& EFI_MEMORY_WC
)
500 if (p
->Attribute
& EFI_MEMORY_WT
)
502 if (p
->Attribute
& EFI_MEMORY_WB
)
504 if (p
->Attribute
& EFI_MEMORY_UCE
)
506 if (p
->Attribute
& EFI_MEMORY_WP
)
508 if (p
->Attribute
& EFI_MEMORY_RP
)
510 if (p
->Attribute
& EFI_MEMORY_XP
)
512 if (pager_output("\n"))
520 COMMAND_SET(configuration
, "configuration", "print configuration tables",
521 command_configuration
);
524 guid_to_string(EFI_GUID
*guid
)
528 sprintf(buf
, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
529 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0],
530 guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3], guid
->Data4
[4],
531 guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
536 command_configuration(int argc
, char *argv
[])
541 snprintf(line
, sizeof(line
), "NumberOfTableEntries=%lu\n",
542 (unsigned long)ST
->NumberOfTableEntries
);
544 if (pager_output(line
)) {
549 for (i
= 0; i
< ST
->NumberOfTableEntries
; i
++) {
553 guid
= &ST
->ConfigurationTable
[i
].VendorGuid
;
554 if (!memcmp(guid
, &mps
, sizeof(EFI_GUID
)))
556 else if (!memcmp(guid
, &acpi
, sizeof(EFI_GUID
)))
557 printf("ACPI Table");
558 else if (!memcmp(guid
, &acpi20
, sizeof(EFI_GUID
)))
559 printf("ACPI 2.0 Table");
560 else if (!memcmp(guid
, &smbios
, sizeof(EFI_GUID
)))
561 printf("SMBIOS Table");
562 else if (!memcmp(guid
, &dxe
, sizeof(EFI_GUID
)))
564 else if (!memcmp(guid
, &hoblist
, sizeof(EFI_GUID
)))
565 printf("HOB List Table");
566 else if (!memcmp(guid
, &memtype
, sizeof(EFI_GUID
)))
567 printf("Memory Type Information Table");
568 else if (!memcmp(guid
, &debugimg
, sizeof(EFI_GUID
)))
569 printf("Debug Image Info Table");
570 else if (!memcmp(guid
, &fdtdtb
, sizeof(EFI_GUID
)))
573 printf("Unknown Table (%s)", guid_to_string(guid
));
574 snprintf(line
, sizeof(line
), " at %p\n",
575 ST
->ConfigurationTable
[i
].VendorTable
);
576 if (pager_output(line
))
585 COMMAND_SET(mode
, "mode", "change or display EFI text modes", command_mode
);
588 command_mode(int argc
, char *argv
[])
596 SIMPLE_TEXT_OUTPUT_INTERFACE
*conout
;
597 extern void HO(void);
602 mode
= strtol(argv
[1], &cp
, 0);
604 printf("Invalid mode\n");
607 status
= conout
->QueryMode(conout
, mode
, &cols
, &rows
);
608 if (EFI_ERROR(status
)) {
609 printf("invalid mode %d\n", mode
);
612 status
= conout
->SetMode(conout
, mode
);
613 if (EFI_ERROR(status
)) {
614 printf("couldn't set mode %d\n", mode
);
617 sprintf(rowenv
, "%u", (unsigned)rows
);
618 setenv("LINES", rowenv
, 1);
619 HO(); /* set cursor */
623 printf("Current mode: %d\n", conout
->Mode
->Mode
);
624 for (i
= 0; i
<= conout
->Mode
->MaxMode
; i
++) {
625 status
= conout
->QueryMode(conout
, i
, &cols
, &rows
);
626 if (EFI_ERROR(status
))
628 printf("Mode %d: %u columns, %u rows\n", i
, (unsigned)cols
,
633 printf("Select a mode with the command \"mode <number>\"\n");
638 COMMAND_SET(efishow
, "efi-show", "print some or all EFI variables", command_efi_show
);
641 efi_print_var(CHAR16
*varnamearg
, EFI_GUID
*matchguid
, int lflag
)
648 uint32_t uuid_status
;
652 status
= RS
->GetVariable(varnamearg
, matchguid
, &attr
,
654 if (status
!= EFI_BUFFER_TOO_SMALL
) {
655 printf("Can't get the variable: error %#lx\n", status
);
658 data
= malloc(datasz
);
659 status
= RS
->GetVariable(varnamearg
, matchguid
, &attr
,
661 if (status
!= EFI_SUCCESS
) {
662 printf("Can't get the variable: error %#lx\n", status
);
665 uuid_to_string((uuid_t
*)matchguid
, &str
, &uuid_status
);
667 printf("%s 0x%x %S", str
, attr
, varnamearg
);
669 printf("%s 0x%x %S=", str
, attr
, varnamearg
);
673 for (i
= 0; i
< datasz
- 1; i
++) {
674 /* Quick hack to see if this ascii-ish string printable range plus tab, cr and lf */
675 if ((str
[i
] < 32 || str
[i
] > 126) && str
[i
] != 9 && str
[i
] != 10 && str
[i
] != 13) {
680 if (str
[datasz
- 1] != '\0')
685 for (i
= 0; i
< datasz
/ 2; i
++) {
686 if (isalnum(data
[i
]) || isspace(data
[i
]))
687 printf("%c", data
[i
]);
689 printf("\\x%02x", data
[i
]);
699 command_efi_show(int argc
, char *argv
[])
705 * print all the env vars tagged with UUID
707 * search all the env vars and print the ones matching var
708 * eif-show -u UUID -v var
710 * print all the env vars that match UUID and var
712 /* NB: We assume EFI_GUID is the same as uuid_t */
713 int aflag
= 0, gflag
= 0, lflag
= 0, vflag
= 0;
717 EFI_GUID varguid
= { 0,0,0,{0,0,0,0,0,0,0,0} };
718 EFI_GUID matchguid
= { 0,0,0,{0,0,0,0,0,0,0,0} };
719 uint32_t uuid_status
;
722 CHAR16 varnamearg
[128];
726 while ((ch
= getopt(argc
, argv
, "ag:lv:")) != -1) {
733 uuid_from_string(optarg
, (uuid_t
*)&matchguid
,
735 if (uuid_status
!= uuid_s_ok
) {
736 printf("uid %s could not be parsed\n", optarg
);
745 if (strlen(optarg
) >= nitems(varnamearg
)) {
746 printf("Variable %s is longer than %zd characters\n",
747 optarg
, nitems(varnamearg
));
750 for (i
= 0; i
< strlen(optarg
); i
++)
751 varnamearg
[i
] = optarg
[i
];
755 printf("Invalid argument %c\n", ch
);
760 if (aflag
&& (gflag
|| vflag
)) {
761 printf("-a isn't compatible with -v or -u\n");
765 if (aflag
&& optind
< argc
) {
766 printf("-a doesn't take any args");
777 if (vflag
&& gflag
) {
778 rv
= efi_print_var(varnamearg
, &matchguid
, lflag
);
785 if (strlen(optarg
) >= nitems(varnamearg
)) {
786 printf("Variable %s is longer than %zd characters\n",
787 optarg
, nitems(varnamearg
));
791 for (i
= 0; i
< strlen(optarg
); i
++)
792 varnamearg
[i
] = optarg
[i
];
795 uuid_from_string(optarg
, (uuid_t
*)&matchguid
,
797 if (uuid_status
!= uuid_s_ok
) {
798 printf("uid %s could not be parsed\n", optarg
);
802 rv
= efi_print_var(varnamearg
, &matchguid
, lflag
);
808 printf("Too many args %d\n", argc
);
814 * Initiate the search -- note the standard takes pain
815 * to specify the initial call must be a poiner to a NULL
819 varname
= malloc(varalloc
);
820 if (varname
== NULL
) {
821 printf("Can't allocate memory to get variables\n");
828 status
= RS
->GetNextVariableName(&varsz
, varname
, &varguid
);
829 if (status
== EFI_BUFFER_TOO_SMALL
) {
831 newnm
= malloc(varalloc
);
833 printf("Can't allocate memory to get variables\n");
838 memcpy(newnm
, varname
, varsz
);
841 continue; /* Try again with bigger buffer */
843 if (status
!= EFI_SUCCESS
)
846 if (efi_print_var(varname
, &varguid
, lflag
) != CMD_OK
)
851 if (wcscmp(varnamearg
, varname
) == 0) {
852 if (efi_print_var(varname
, &varguid
, lflag
) != CMD_OK
)
858 if (memcmp(&varguid
, &matchguid
, sizeof(varguid
)) == 0) {
859 if (efi_print_var(varname
, &varguid
, lflag
) != CMD_OK
)
871 COMMAND_SET(efiset
, "efi-set", "set EFI variables", command_efi_set
);
874 command_efi_set(int argc
, char *argv
[])
876 char *uuid
, *var
, *val
;
883 printf("efi-set uuid var new-value\n");
889 uuid_from_string(uuid
, (uuid_t
*)&guid
, &status
);
890 if (status
!= uuid_s_ok
) {
891 printf("Invalid uuid %s %d\n", uuid
, status
);
894 cpy8to16(var
, wvar
, sizeof(wvar
));
895 err
= RS
->SetVariable(wvar
, &guid
,
896 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
897 strlen(val
) + 1, val
);
898 if (EFI_ERROR(err
)) {
899 printf("Failed to set variable: error %lu\n", EFI_ERROR_CODE(err
));
905 COMMAND_SET(efiunset
, "efi-unset", "delete / unset EFI variables", command_efi_unset
);
908 command_efi_unset(int argc
, char *argv
[])
917 printf("efi-unset uuid var\n");
922 uuid_from_string(uuid
, (uuid_t
*)&guid
, &status
);
923 if (status
!= uuid_s_ok
) {
924 printf("Invalid uuid %s\n", uuid
);
927 cpy8to16(var
, wvar
, sizeof(wvar
));
928 err
= RS
->SetVariable(wvar
, &guid
, 0, 0, NULL
);
929 if (EFI_ERROR(err
)) {
930 printf("Failed to unset variable: error %lu\n", EFI_ERROR_CODE(err
));