2 * Copyright 2012-2013 Red Hat, Inc.
5 * See "COPYING" for license terms.
7 * Author(s): Peter Jones <pjones@redhat.com>
14 #include "variables.h"
16 EFI_LOADED_IMAGE
*this_image
= NULL
;
19 FindSubDevicePath(EFI_DEVICE_PATH
*In
, UINT8 Type
, UINT8 SubType
,
20 EFI_DEVICE_PATH
**Out
)
22 EFI_DEVICE_PATH
*dp
= In
;
24 return EFI_INVALID_PARAMETER
;
26 for (dp
= In
; !IsDevicePathEnd(dp
); dp
= NextDevicePathNode(dp
)) {
27 if (DevicePathType(dp
) == Type
&&
28 DevicePathSubType(dp
) == SubType
) {
29 *Out
= DuplicateDevicePath(dp
);
31 return EFI_OUT_OF_RESOURCES
;
40 get_file_size(EFI_FILE_HANDLE fh
, UINTN
*retsize
)
45 EFI_GUID finfo
= EFI_FILE_INFO_ID
;
47 /* The API here is "Call it once with bs=0, it fills in bs,
48 * then allocate a buffer and ask again to get it filled. */
49 rc
= uefi_call_wrapper(fh
->GetInfo
, 4, fh
, &finfo
, &bs
, NULL
);
50 if (rc
== EFI_BUFFER_TOO_SMALL
) {
51 buffer
= AllocateZeroPool(bs
);
53 Print(L
"Could not allocate memory\n");
54 return EFI_OUT_OF_RESOURCES
;
56 rc
= uefi_call_wrapper(fh
->GetInfo
, 4, fh
, &finfo
,
59 /* This checks *either* the error from the first GetInfo, if it isn't
60 * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call
63 Print(L
"Could not get file info: %d\n", rc
);
68 EFI_FILE_INFO
*fi
= buffer
;
69 *retsize
= fi
->FileSize
;
75 read_file(EFI_FILE_HANDLE fh
, CHAR16
*fullpath
, CHAR16
**buffer
, UINT64
*bs
)
78 EFI_STATUS rc
= uefi_call_wrapper(fh
->Open
, 5, fh
, &fh2
, fullpath
,
79 EFI_FILE_READ_ONLY
, 0);
81 Print(L
"Couldn't open \"%s\": %d\n", fullpath
, rc
);
87 rc
= get_file_size(fh2
, &len
);
89 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
93 b
= AllocateZeroPool(len
+ 2);
95 Print(L
"Could not allocate memory\n");
96 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
97 return EFI_OUT_OF_RESOURCES
;
100 rc
= uefi_call_wrapper(fh
->Read
, 3, fh
, &len
, b
);
103 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
104 Print(L
"Could not read file: %d\n", rc
);
109 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
114 make_full_path(CHAR16
*dirname
, CHAR16
*filename
, CHAR16
**out
, UINT64
*outlen
)
118 len
= StrLen(L
"\\EFI\\") + StrLen(dirname
)
119 + StrLen(L
"\\") + StrLen(filename
)
122 CHAR16
*fullpath
= AllocateZeroPool(len
*sizeof(CHAR16
));
124 Print(L
"Could not allocate memory\n");
125 return EFI_OUT_OF_RESOURCES
;
128 StrCat(fullpath
, L
"\\EFI\\");
129 StrCat(fullpath
, dirname
);
130 StrCat(fullpath
, L
"\\");
131 StrCat(fullpath
, filename
);
138 CHAR16
*bootorder
= NULL
;
141 EFI_DEVICE_PATH
*first_new_option
= NULL
;
142 VOID
*first_new_option_args
= NULL
;
143 UINTN first_new_option_size
= 0;
146 add_boot_option(EFI_DEVICE_PATH
*hddp
, EFI_DEVICE_PATH
*fulldp
,
147 CHAR16
*filename
, CHAR16
*label
, CHAR16
*arguments
)
150 CHAR16 varname
[] = L
"Boot0000";
151 CHAR16 hexmap
[] = L
"0123456789ABCDEF";
152 EFI_GUID global
= EFI_GLOBAL_VARIABLE
;
155 for(; i
<= 0xffff; i
++) {
156 varname
[4] = hexmap
[(i
& 0xf000) >> 12];
157 varname
[5] = hexmap
[(i
& 0x0f00) >> 8];
158 varname
[6] = hexmap
[(i
& 0x00f0) >> 4];
159 varname
[7] = hexmap
[(i
& 0x000f) >> 0];
161 void *var
= LibGetVariable(varname
, &global
);
163 int size
= sizeof(UINT32
) + sizeof (UINT16
) +
164 StrLen(label
)*2 + 2 + DevicePathSize(hddp
) +
165 StrLen(arguments
) * 2;
167 CHAR8
*data
= AllocateZeroPool(size
+ 2);
168 CHAR8
*cursor
= data
;
169 *(UINT32
*)cursor
= LOAD_OPTION_ACTIVE
;
170 cursor
+= sizeof (UINT32
);
171 *(UINT16
*)cursor
= DevicePathSize(hddp
);
172 cursor
+= sizeof (UINT16
);
173 StrCpy((CHAR16
*)cursor
, label
);
174 cursor
+= StrLen(label
)*2 + 2;
175 CopyMem(cursor
, hddp
, DevicePathSize(hddp
));
176 cursor
+= DevicePathSize(hddp
);
177 StrCpy((CHAR16
*)cursor
, arguments
);
179 Print(L
"Creating boot entry \"%s\" with label \"%s\" "
180 L
"for file \"%s\"\n",
181 varname
, label
, filename
);
183 if (!first_new_option
) {
184 first_new_option
= DuplicateDevicePath(fulldp
);
185 first_new_option_args
= arguments
;
186 first_new_option_size
= StrLen(arguments
) * sizeof (CHAR16
);
189 rc
= uefi_call_wrapper(RT
->SetVariable
, 5, varname
,
190 &global
, EFI_VARIABLE_NON_VOLATILE
|
191 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
192 EFI_VARIABLE_RUNTIME_ACCESS
,
198 Print(L
"Could not create variable: %d\n", rc
);
202 CHAR16
*newbootorder
= AllocateZeroPool(sizeof (CHAR16
)
205 return EFI_OUT_OF_RESOURCES
;
208 newbootorder
[0] = i
& 0xffff;
210 for (j
= 0; j
< nbootorder
; j
++)
211 newbootorder
[j
+1] = bootorder
[j
];
214 bootorder
= newbootorder
;
216 #ifdef DEBUG_FALLBACK
217 Print(L
"nbootorder: %d\nBootOrder: ", nbootorder
);
218 for (j
= 0 ; j
< nbootorder
; j
++)
219 Print(L
"%04x ", bootorder
[j
]);
226 return EFI_OUT_OF_RESOURCES
;
230 find_boot_option(EFI_DEVICE_PATH
*dp
, EFI_DEVICE_PATH
*fulldp
,
231 CHAR16
*filename
, CHAR16
*label
, CHAR16
*arguments
,
234 unsigned int size
= sizeof(UINT32
) + sizeof (UINT16
) +
235 StrLen(label
)*2 + 2 + DevicePathSize(dp
) +
236 StrLen(arguments
) * 2;
238 CHAR8
*data
= AllocateZeroPool(size
+ 2);
240 return EFI_OUT_OF_RESOURCES
;
241 CHAR8
*cursor
= data
;
242 *(UINT32
*)cursor
= LOAD_OPTION_ACTIVE
;
243 cursor
+= sizeof (UINT32
);
244 *(UINT16
*)cursor
= DevicePathSize(dp
);
245 cursor
+= sizeof (UINT16
);
246 StrCpy((CHAR16
*)cursor
, label
);
247 cursor
+= StrLen(label
)*2 + 2;
248 CopyMem(cursor
, dp
, DevicePathSize(dp
));
249 cursor
+= DevicePathSize(dp
);
250 StrCpy((CHAR16
*)cursor
, arguments
);
253 CHAR16 varname
[] = L
"Boot0000";
254 CHAR16 hexmap
[] = L
"0123456789ABCDEF";
255 EFI_GUID global
= EFI_GLOBAL_VARIABLE
;
258 CHAR8
*candidate
= AllocateZeroPool(size
);
261 return EFI_OUT_OF_RESOURCES
;
264 for(i
= 0; i
< nbootorder
&& i
< 0x10000; i
++) {
265 varname
[4] = hexmap
[(bootorder
[i
] & 0xf000) >> 12];
266 varname
[5] = hexmap
[(bootorder
[i
] & 0x0f00) >> 8];
267 varname
[6] = hexmap
[(bootorder
[i
] & 0x00f0) >> 4];
268 varname
[7] = hexmap
[(bootorder
[i
] & 0x000f) >> 0];
270 UINTN candidate_size
= size
;
271 rc
= uefi_call_wrapper(RT
->GetVariable
, 5, varname
, &global
,
272 NULL
, &candidate_size
, candidate
);
276 if (candidate_size
!= size
)
279 if (CompareMem(candidate
, data
, size
))
282 /* at this point, we have duplicate data. */
283 if (!first_new_option
) {
284 first_new_option
= DuplicateDevicePath(fulldp
);
285 first_new_option_args
= arguments
;
286 first_new_option_size
= StrLen(arguments
) * sizeof (CHAR16
);
296 return EFI_NOT_FOUND
;
302 CHAR16
*oldbootorder
;
304 EFI_GUID global
= EFI_GLOBAL_VARIABLE
;
306 oldbootorder
= LibGetVariableAndSize(L
"BootOrder", &global
, &size
);
308 nbootorder
= size
/ sizeof (CHAR16
);
309 bootorder
= oldbootorder
;
316 update_boot_order(void)
320 EFI_GUID global
= EFI_GLOBAL_VARIABLE
;
321 CHAR16
*newbootorder
= NULL
;
324 size
= nbootorder
* sizeof(CHAR16
);
325 newbootorder
= AllocateZeroPool(size
);
327 return EFI_OUT_OF_RESOURCES
;
328 CopyMem(newbootorder
, bootorder
, size
);
330 #ifdef DEBUG_FALLBACK
331 Print(L
"nbootorder: %d\nBootOrder: ", size
/ sizeof (CHAR16
));
333 for (j
= 0 ; j
< size
/ sizeof (CHAR16
); j
++)
334 Print(L
"%04x ", newbootorder
[j
]);
337 rc
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"BootOrder", &global
,
339 if (rc
== EFI_BUFFER_TOO_SMALL
)
340 LibDeleteVariable(L
"BootOrder", &global
);
342 rc
= uefi_call_wrapper(RT
->SetVariable
, 5, L
"BootOrder", &global
,
343 EFI_VARIABLE_NON_VOLATILE
|
344 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
345 EFI_VARIABLE_RUNTIME_ACCESS
,
347 FreePool(newbootorder
);
352 add_to_boot_list(EFI_FILE_HANDLE fh
, CHAR16
*dirname
, CHAR16
*filename
, CHAR16
*label
, CHAR16
*arguments
)
354 CHAR16
*fullpath
= NULL
;
356 EFI_STATUS rc
= EFI_SUCCESS
;
358 rc
= make_full_path(dirname
, filename
, &fullpath
, &pathlen
);
362 EFI_DEVICE_PATH
*dph
= NULL
;
363 EFI_DEVICE_PATH
*file
= NULL
;
364 EFI_DEVICE_PATH
*full_device_path
= NULL
;
365 EFI_DEVICE_PATH
*dp
= NULL
;
367 dph
= DevicePathFromHandle(this_image
->DeviceHandle
);
369 rc
= EFI_OUT_OF_RESOURCES
;
373 file
= FileDevicePath(fh
, fullpath
);
375 rc
= EFI_OUT_OF_RESOURCES
;
379 full_device_path
= AppendDevicePath(dph
, file
);
380 if (!full_device_path
) {
381 rc
= EFI_OUT_OF_RESOURCES
;
385 rc
= FindSubDevicePath(full_device_path
,
386 MEDIA_DEVICE_PATH
, MEDIA_HARDDRIVE_DP
, &dp
);
388 if (rc
== EFI_NOT_FOUND
) {
389 dp
= full_device_path
;
391 rc
= EFI_OUT_OF_RESOURCES
;
396 #ifdef DEBUG_FALLBACK
398 UINTN s
= DevicePathSize(dp
);
400 UINT8
*dpv
= (void *)dp
;
401 for (i
= 0; i
< s
; i
++) {
402 if (i
> 0 && i
% 16 == 0)
404 Print(L
"%02x ", dpv
[i
]);
408 CHAR16
*dps
= DevicePathToStr(dp
);
409 Print(L
"device path: \"%s\"\n", dps
);
414 rc
= find_boot_option(dp
, full_device_path
, fullpath
, label
, arguments
, &option
);
416 add_boot_option(dp
, full_device_path
, fullpath
, label
, arguments
);
417 } else if (option
!= 0) {
418 CHAR16
*newbootorder
;
419 newbootorder
= AllocateZeroPool(sizeof (CHAR16
) * nbootorder
);
421 return EFI_OUT_OF_RESOURCES
;
423 newbootorder
[0] = bootorder
[option
];
424 CopyMem(newbootorder
+ 1, bootorder
, sizeof (CHAR16
) * option
);
425 CopyMem(newbootorder
+ option
+ 1, bootorder
+ option
+ 1,
426 sizeof (CHAR16
) * (nbootorder
- option
- 1));
428 bootorder
= newbootorder
;
434 if (full_device_path
)
435 FreePool(full_device_path
);
444 populate_stanza(EFI_FILE_HANDLE fh
, CHAR16
*dirname
, CHAR16
*filename
, CHAR16
*csv
)
446 #ifdef DEBUG_FALLBACK
447 Print(L
"CSV data: \"%s\"\n", csv
);
451 UINTN comma0
= StrCSpn(csv
, L
",");
453 return EFI_INVALID_PARAMETER
;
454 file
[comma0
] = L
'\0';
455 #ifdef DEBUG_FALLBACK
456 Print(L
"filename: \"%s\"\n", file
);
459 CHAR16
*label
= csv
+ comma0
+ 1;
460 UINTN comma1
= StrCSpn(label
, L
",");
462 return EFI_INVALID_PARAMETER
;
463 label
[comma1
] = L
'\0';
464 #ifdef DEBUG_FALLBACK
465 Print(L
"label: \"%s\"\n", label
);
468 CHAR16
*arguments
= csv
+ comma0
+1 + comma1
+1;
469 UINTN comma2
= StrCSpn(arguments
, L
",");
470 arguments
[comma2
] = L
'\0';
471 /* This one is optional, so don't check if comma2 is 0 */
472 #ifdef DEBUG_FALLBACK
473 Print(L
"arguments: \"%s\"\n", arguments
);
476 add_to_boot_list(fh
, dirname
, file
, label
, arguments
);
482 try_boot_csv(EFI_FILE_HANDLE fh
, CHAR16
*dirname
, CHAR16
*filename
)
484 CHAR16
*fullpath
= NULL
;
488 rc
= make_full_path(dirname
, filename
, &fullpath
, &pathlen
);
492 #ifdef DEBUG_FALLBACK
493 Print(L
"Found file \"%s\"\n", fullpath
);
498 rc
= read_file(fh
, fullpath
, &buffer
, &bs
);
500 Print(L
"Could not read file \"%s\": %d\n", fullpath
, rc
);
506 #ifdef DEBUG_FALLBACK
507 Print(L
"File looks like:\n%s\n", buffer
);
510 CHAR16
*start
= buffer
;
511 /* The file may or may not start with the Unicode byte order marker.
512 * Sadness ensues. Since UEFI is defined as LE, I'm going to decree
513 * that these files must also be LE.
517 * But if we find the LE byte order marker, just skip it.
519 if (*start
== 0xfeff)
522 while (*start
== L
'\r' || *start
== L
'\n')
524 UINTN l
= StrCSpn(start
, L
"\r\n");
526 if (start
[l
] == L
'\0')
534 populate_stanza(fh
, dirname
, filename
, start
);
545 find_boot_csv(EFI_FILE_HANDLE fh
, CHAR16
*dirname
)
550 EFI_GUID finfo
= EFI_FILE_INFO_ID
;
552 /* The API here is "Call it once with bs=0, it fills in bs,
553 * then allocate a buffer and ask again to get it filled. */
554 rc
= uefi_call_wrapper(fh
->GetInfo
, 4, fh
, &finfo
, &bs
, NULL
);
555 if (rc
== EFI_BUFFER_TOO_SMALL
) {
556 buffer
= AllocateZeroPool(bs
);
558 Print(L
"Could not allocate memory\n");
559 return EFI_OUT_OF_RESOURCES
;
561 rc
= uefi_call_wrapper(fh
->GetInfo
, 4, fh
, &finfo
,
564 /* This checks *either* the error from the first GetInfo, if it isn't
565 * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call
568 Print(L
"Could not get info for \"%s\": %d\n", dirname
, rc
);
574 EFI_FILE_INFO
*fi
= buffer
;
575 if (!(fi
->Attribute
& EFI_FILE_DIRECTORY
)) {
582 CHAR16
*bootcsv
=NULL
, *bootarchcsv
=NULL
;
587 rc
= uefi_call_wrapper(fh
->Read
, 3, fh
, &bs
, NULL
);
588 if (EFI_ERROR(rc
) && rc
!= EFI_BUFFER_TOO_SMALL
) {
589 Print(L
"Could not read \\EFI\\%s\\: %d\n", dirname
, rc
);
594 /* If there's no data to read, don't try to allocate 0 bytes
595 * and read the data... */
599 buffer
= AllocateZeroPool(bs
);
601 Print(L
"Could not allocate memory\n");
602 return EFI_OUT_OF_RESOURCES
;
605 rc
= uefi_call_wrapper(fh
->Read
, 3, fh
, &bs
, buffer
);
607 Print(L
"Could not read \\EFI\\%s\\: %d\n", dirname
, rc
);
617 if (!bootcsv
&& !StrCaseCmp(fi
->FileName
, L
"boot.csv"))
618 bootcsv
= StrDuplicate(fi
->FileName
);
621 !StrCaseCmp(fi
->FileName
, L
"boot" EFI_ARCH L
".csv"))
622 bootarchcsv
= StrDuplicate(fi
->FileName
);
631 rc
= uefi_call_wrapper(fh
->Open
, 5, fh
, &fh2
,
632 bootarchcsv
, EFI_FILE_READ_ONLY
, 0);
633 if (EFI_ERROR(rc
) || fh2
== NULL
) {
634 Print(L
"Couldn't open \\EFI\\%s\\%s: %d\n",
635 dirname
, bootarchcsv
, rc
);
637 rc
= try_boot_csv(fh2
, dirname
, bootarchcsv
);
638 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
641 if ((EFI_ERROR(rc
) || !bootarchcsv
) && bootcsv
) {
643 rc
= uefi_call_wrapper(fh
->Open
, 5, fh
, &fh2
,
644 bootcsv
, EFI_FILE_READ_ONLY
, 0);
645 if (EFI_ERROR(rc
) || fh2
== NULL
) {
646 Print(L
"Couldn't open \\EFI\\%s\\%s: %d\n",
647 dirname
, bootcsv
, rc
);
649 rc
= try_boot_csv(fh2
, dirname
, bootcsv
);
650 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
659 find_boot_options(EFI_HANDLE device
)
661 EFI_STATUS rc
= EFI_SUCCESS
;
663 EFI_FILE_IO_INTERFACE
*fio
= NULL
;
664 rc
= uefi_call_wrapper(BS
->HandleProtocol
, 3, device
,
665 &FileSystemProtocol
, (void **)&fio
);
667 Print(L
"Couldn't find file system: %d\n", rc
);
671 /* EFI_FILE_HANDLE is a pointer to an EFI_FILE, and I have
672 * *no idea* what frees the memory allocated here. Hopefully
674 EFI_FILE_HANDLE fh
= NULL
;
675 rc
= uefi_call_wrapper(fio
->OpenVolume
, 2, fio
, &fh
);
676 if (EFI_ERROR(rc
) || fh
== NULL
) {
677 Print(L
"Couldn't open file system: %d\n", rc
);
681 EFI_FILE_HANDLE fh2
= NULL
;
682 rc
= uefi_call_wrapper(fh
->Open
, 5, fh
, &fh2
, L
"EFI",
683 EFI_FILE_READ_ONLY
, 0);
684 if (EFI_ERROR(rc
) || fh2
== NULL
) {
685 Print(L
"Couldn't open EFI: %d\n", rc
);
686 uefi_call_wrapper(fh
->Close
, 1, fh
);
689 rc
= uefi_call_wrapper(fh2
->SetPosition
, 2, fh2
, 0);
691 Print(L
"Couldn't set file position: %d\n", rc
);
692 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
693 uefi_call_wrapper(fh
->Close
, 1, fh
);
701 rc
= uefi_call_wrapper(fh2
->Read
, 3, fh2
, &bs
, NULL
);
702 if (rc
== EFI_BUFFER_TOO_SMALL
||
703 (rc
== EFI_SUCCESS
&& bs
!= 0)) {
704 buffer
= AllocateZeroPool(bs
);
706 Print(L
"Could not allocate memory\n");
707 /* sure, this might work, why not? */
708 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
709 uefi_call_wrapper(fh
->Close
, 1, fh
);
710 return EFI_OUT_OF_RESOURCES
;
713 rc
= uefi_call_wrapper(fh2
->Read
, 3, fh2
, &bs
, buffer
);
719 Print(L
"Could not read \\EFI\\: %d\n", rc
);
724 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
725 uefi_call_wrapper(fh
->Close
, 1, fh
);
728 EFI_FILE_INFO
*fi
= buffer
;
730 if (!(fi
->Attribute
& EFI_FILE_DIRECTORY
)) {
735 if (!StrCmp(fi
->FileName
, L
".") ||
736 !StrCmp(fi
->FileName
, L
"..") ||
737 !StrCaseCmp(fi
->FileName
, L
"BOOT")) {
742 #ifdef DEBUG_FALLBACK
743 Print(L
"Found directory named \"%s\"\n", fi
->FileName
);
747 rc
= uefi_call_wrapper(fh
->Open
, 5, fh2
, &fh3
, fi
->FileName
,
748 EFI_FILE_READ_ONLY
, 0);
750 Print(L
"%d Couldn't open %s: %d\n", __LINE__
, fi
->FileName
, rc
);
756 rc
= find_boot_csv(fh3
, fi
->FileName
);
759 if (rc
== EFI_OUT_OF_RESOURCES
)
764 if (rc
== EFI_SUCCESS
&& nbootorder
> 0)
765 rc
= update_boot_order();
767 uefi_call_wrapper(fh2
->Close
, 1, fh2
);
768 uefi_call_wrapper(fh
->Close
, 1, fh
);
773 try_start_first_option(EFI_HANDLE parent_image_handle
)
776 EFI_HANDLE image_handle
;
778 if (!first_new_option
) {
782 rc
= uefi_call_wrapper(BS
->LoadImage
, 6, 0, parent_image_handle
,
783 first_new_option
, NULL
, 0,
786 CHAR16
*dps
= DevicePathToStr(first_new_option
);
787 UINTN s
= DevicePathSize(first_new_option
);
789 UINT8
*dpv
= (void *)first_new_option
;
790 Print(L
"LoadImage failed: %d\nDevice path: \"%s\"\n", rc
, dps
);
791 for (i
= 0; i
< s
; i
++) {
792 if (i
> 0 && i
% 16 == 0)
794 Print(L
"%02x ", dpv
[i
]);
798 uefi_call_wrapper(BS
->Stall
, 1, 500000000);
802 EFI_LOADED_IMAGE
*image
;
803 rc
= uefi_call_wrapper(BS
->HandleProtocol
, 3, image_handle
, &LoadedImageProtocol
, (void *)&image
);
804 if (!EFI_ERROR(rc
)) {
805 image
->LoadOptions
= first_new_option_args
;
806 image
->LoadOptionsSize
= first_new_option_size
;
809 rc
= uefi_call_wrapper(BS
->StartImage
, 3, image_handle
, NULL
, NULL
);
811 Print(L
"StartImage failed: %d\n", rc
);
812 uefi_call_wrapper(BS
->Stall
, 1, 500000000);
817 EFI_GUID SHIM_LOCK_GUID
= { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
819 efi_main(EFI_HANDLE image
, EFI_SYSTEM_TABLE
*systab
);
822 __attribute__((__optimize__("0")))
825 EFI_GUID guid
= SHIM_LOCK_GUID
;
828 EFI_STATUS efi_status
;
829 volatile register int x
= 0;
830 extern char _etext
, _edata
;
832 efi_status
= get_variable(L
"SHIM_DEBUG", &data
, &dataSize
, guid
);
833 if (EFI_ERROR(efi_status
)) {
841 Print(L
"add-symbol-file "DEBUGDIR
842 L
"fb" EFI_ARCH L
".efi.debug %p -s .data %p\n", &_etext
,
847 efi_main(EFI_HANDLE image
, EFI_SYSTEM_TABLE
*systab
)
851 InitializeLib(image
, systab
);
854 * if SHIM_DEBUG is set, wait for a debugger to attach.
858 rc
= uefi_call_wrapper(BS
->HandleProtocol
, 3, image
, &LoadedImageProtocol
, (void *)&this_image
);
860 Print(L
"Error: could not find loaded image: %d\n", rc
);
864 Print(L
"System BootOrder not found. Initializing defaults.\n");
868 rc
= find_boot_options(this_image
->DeviceHandle
);
870 Print(L
"Error: could not find boot options: %d\n", rc
);
874 try_start_first_option(image
);
876 Print(L
"Reset System\n");
877 uefi_call_wrapper(RT
->ResetSystem
, 4, EfiResetCold
,
878 EFI_SUCCESS
, 0, NULL
);