2 Implementation for PlatformBootManagerLib library class interfaces.
4 Copyright (C) 2015-2016, Red Hat, Inc.
5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IndustryStandard/Pci22.h>
13 #include <IndustryStandard/Virtio095.h>
14 #include <Library/BootLogoLib.h>
15 #include <Library/DevicePathLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/PlatformBmPrintScLib.h>
18 #include <Library/QemuBootOrderLib.h>
19 #include <Library/TpmPlatformHierarchyLib.h>
20 #include <Library/UefiBootManagerLib.h>
21 #include <Protocol/DevicePath.h>
22 #include <Protocol/FirmwareVolume2.h>
23 #include <Protocol/GraphicsOutput.h>
24 #include <Protocol/LoadedImage.h>
25 #include <Protocol/PciIo.h>
26 #include <Protocol/PciRootBridgeIo.h>
27 #include <Protocol/VirtioDevice.h>
28 #include <Guid/EventGroup.h>
29 #include <Guid/GlobalVariable.h>
30 #include <Guid/RootBridgesConnectedEventGroup.h>
31 #include <Guid/SerialPortLibVendor.h>
33 #include "PlatformBm.h"
35 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
39 VENDOR_DEVICE_PATH SerialDxe
;
40 UART_DEVICE_PATH Uart
;
41 VENDOR_DEFINED_DEVICE_PATH TermType
;
42 EFI_DEVICE_PATH_PROTOCOL End
;
43 } PLATFORM_SERIAL_CONSOLE
;
46 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
48 // VENDOR_DEVICE_PATH SerialDxe
51 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
52 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
56 // UART_DEVICE_PATH Uart
59 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
61 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
62 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
63 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
64 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
68 // VENDOR_DEFINED_DEVICE_PATH TermType
72 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
73 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
76 // Guid to be filled in dynamically
81 // EFI_DEVICE_PATH_PROTOCOL End
84 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
85 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
91 USB_CLASS_DEVICE_PATH Keyboard
;
92 EFI_DEVICE_PATH_PROTOCOL End
;
93 } PLATFORM_USB_KEYBOARD
;
96 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
98 // USB_CLASS_DEVICE_PATH Keyboard
102 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
103 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
105 0xFFFF, // VendorId: any
106 0xFFFF, // ProductId: any
107 3, // DeviceClass: HID
108 1, // DeviceSubClass: boot
109 1 // DeviceProtocol: keyboard
113 // EFI_DEVICE_PATH_PROTOCOL End
116 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
117 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
122 Check if the handle satisfies a particular condition.
124 @param[in] Handle The handle to check.
125 @param[in] ReportText A caller-allocated string passed in for reporting
126 purposes. It must never be NULL.
128 @retval TRUE The condition is satisfied.
129 @retval FALSE Otherwise. This includes the case when the condition could not
130 be fully evaluated due to an error.
134 (EFIAPI
*FILTER_FUNCTION
)(
135 IN EFI_HANDLE Handle
,
136 IN CONST CHAR16
*ReportText
142 @param[in] Handle The handle to process.
143 @param[in] ReportText A caller-allocated string passed in for reporting
144 purposes. It must never be NULL.
148 (EFIAPI
*CALLBACK_FUNCTION
)(
149 IN EFI_HANDLE Handle
,
150 IN CONST CHAR16
*ReportText
154 Locate all handles that carry the specified protocol, filter them with a
155 callback function, and pass each handle that passes the filter to another
158 @param[in] ProtocolGuid The protocol to look for.
160 @param[in] Filter The filter function to pass each handle to. If this
161 parameter is NULL, then all handles are processed.
163 @param[in] Process The callback function to pass each handle to that
169 IN EFI_GUID
*ProtocolGuid
,
170 IN FILTER_FUNCTION Filter OPTIONAL
,
171 IN CALLBACK_FUNCTION Process
179 Status
= gBS
->LocateHandleBuffer (
182 NULL
/* SearchKey */,
186 if (EFI_ERROR (Status
)) {
188 // This is not an error, just an informative condition.
200 ASSERT (NoHandles
> 0);
201 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
202 CHAR16
*DevicePathText
;
203 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
206 // The ConvertDevicePathToText() function handles NULL input transparently.
208 DevicePathText
= ConvertDevicePathToText (
209 DevicePathFromHandle (Handles
[Idx
]),
210 FALSE
, // DisplayOnly
211 FALSE
// AllowShortcuts
213 if (DevicePathText
== NULL
) {
214 DevicePathText
= Fallback
;
217 if ((Filter
== NULL
) || Filter (Handles
[Idx
], DevicePathText
)) {
218 Process (Handles
[Idx
], DevicePathText
);
221 if (DevicePathText
!= Fallback
) {
222 FreePool (DevicePathText
);
226 gBS
->FreePool (Handles
);
230 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
236 IN EFI_HANDLE Handle
,
237 IN CONST CHAR16
*ReportText
241 EFI_PCI_IO_PROTOCOL
*PciIo
;
244 Status
= gBS
->HandleProtocol (
246 &gEfiPciIoProtocolGuid
,
249 if (EFI_ERROR (Status
)) {
251 // This is not an error worth reporting.
256 Status
= PciIo
->Pci
.Read (
260 sizeof Pci
/ sizeof (UINT32
),
263 if (EFI_ERROR (Status
)) {
264 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
268 return IS_PCI_DISPLAY (&Pci
);
272 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
273 the VIRTIO_DEVICE_PROTOCOL level.
279 IN EFI_HANDLE Handle
,
280 IN CONST CHAR16
*ReportText
284 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
286 Status
= gBS
->HandleProtocol (
288 &gVirtioDeviceProtocolGuid
,
291 if (EFI_ERROR (Status
)) {
295 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
296 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
300 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
301 the EFI_PCI_IO_PROTOCOL level.
307 IN EFI_HANDLE Handle
,
308 IN CONST CHAR16
*ReportText
312 EFI_PCI_IO_PROTOCOL
*PciIo
;
319 Status
= gBS
->HandleProtocol (
321 &gEfiPciIoProtocolGuid
,
324 if (EFI_ERROR (Status
)) {
329 // Read and check VendorId.
331 Status
= PciIo
->Pci
.Read (
334 PCI_VENDOR_ID_OFFSET
,
338 if (EFI_ERROR (Status
)) {
342 if (VendorId
!= VIRTIO_VENDOR_ID
) {
347 // Read DeviceId and RevisionId.
349 Status
= PciIo
->Pci
.Read (
352 PCI_DEVICE_ID_OFFSET
,
356 if (EFI_ERROR (Status
)) {
360 Status
= PciIo
->Pci
.Read (
363 PCI_REVISION_ID_OFFSET
,
367 if (EFI_ERROR (Status
)) {
372 // From DeviceId and RevisionId, determine whether the device is a
373 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
374 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
375 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
376 // only be sanity-checked, and SubsystemId will decide.
378 if ((DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) &&
379 (RevisionId
>= 0x01))
382 } else if ((DeviceId
>= 0x1000) && (DeviceId
<= 0x103F) && (RevisionId
== 0x00)) {
389 // Read and check SubsystemId as dictated by Virtio10.
391 Status
= PciIo
->Pci
.Read (
394 PCI_SUBSYSTEM_ID_OFFSET
,
398 if (EFI_ERROR (Status
)) {
402 if (Virtio10
&& (SubsystemId
>= 0x40)) {
406 if (!Virtio10
&& (SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)) {
413 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
418 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
419 the matching driver to produce all first-level child handles.
425 IN EFI_HANDLE Handle
,
426 IN CONST CHAR16
*ReportText
431 Status
= gBS
->ConnectController (
432 Handle
, // ControllerHandle
433 NULL
, // DriverImageHandle
434 NULL
, // RemainingDevicePath -- produce all children
438 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
447 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
448 handle, and adds it to ConOut and ErrOut.
454 IN EFI_HANDLE Handle
,
455 IN CONST CHAR16
*ReportText
459 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
461 DevicePath
= DevicePathFromHandle (Handle
);
462 if (DevicePath
== NULL
) {
465 "%a: %s: handle %p: device path not found\n",
473 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
474 if (EFI_ERROR (Status
)) {
477 "%a: %s: adding to ConOut: %r\n",
485 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
486 if (EFI_ERROR (Status
)) {
489 "%a: %s: adding to ErrOut: %r\n",
499 "%a: %s: added to ConOut and ErrOut\n",
507 PlatformRegisterFvBootOption (
515 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
516 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
517 UINTN BootOptionCount
;
518 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
519 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
520 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
522 Status
= gBS
->HandleProtocol (
524 &gEfiLoadedImageProtocolGuid
,
525 (VOID
**)&LoadedImage
527 ASSERT_EFI_ERROR (Status
);
529 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
530 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
531 ASSERT (DevicePath
!= NULL
);
532 DevicePath
= AppendDevicePathNode (
534 (EFI_DEVICE_PATH_PROTOCOL
*)&FileNode
536 ASSERT (DevicePath
!= NULL
);
538 Status
= EfiBootManagerInitializeLoadOption (
540 LoadOptionNumberUnassigned
,
548 ASSERT_EFI_ERROR (Status
);
549 FreePool (DevicePath
);
551 BootOptions
= EfiBootManagerGetLoadOptions (
556 OptionIndex
= EfiBootManagerFindLoadOption (
562 if (OptionIndex
== -1) {
563 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
564 ASSERT_EFI_ERROR (Status
);
567 EfiBootManagerFreeLoadOption (&NewOption
);
568 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
572 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
573 whose device paths do not resolve exactly to an FvFile in the system.
575 This removes any boot options that point to binaries built into the firmware
576 and have become stale due to any of the following:
577 - FvMain's base address or size changed (historical),
578 - FvMain's FvNameGuid changed,
579 - the FILE_GUID of the pointed-to binary changed,
580 - the referenced binary is no longer built into the firmware.
582 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
583 avoids exact duplicates.
587 RemoveStaleFvFileOptions (
591 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
592 UINTN BootOptionCount
;
595 BootOptions
= EfiBootManagerGetLoadOptions (
600 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
601 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
606 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
607 // then keep the boot option.
609 Node1
= BootOptions
[Index
].FilePath
;
610 if (!((DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
) &&
611 (DevicePathSubType (Node1
) == HW_MEMMAP_DP
)) &&
612 !((DevicePathType (Node1
) == MEDIA_DEVICE_PATH
) &&
613 (DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)))
619 // If the second device path node is not FvFile(...), then keep the boot
622 Node2
= NextDevicePathNode (Node1
);
623 if ((DevicePathType (Node2
) != MEDIA_DEVICE_PATH
) ||
624 (DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
))
630 // Locate the Firmware Volume2 protocol instance that is denoted by the
631 // boot option. If this lookup fails (i.e., the boot option references a
632 // firmware volume that doesn't exist), then we'll proceed to delete the
636 Status
= gBS
->LocateDevicePath (
637 &gEfiFirmwareVolume2ProtocolGuid
,
642 if (!EFI_ERROR (Status
)) {
644 // The firmware volume was found; now let's see if it contains the FvFile
645 // identified by GUID.
647 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
648 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
650 EFI_FV_FILETYPE FoundType
;
651 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
652 UINT32 AuthenticationStatus
;
654 Status
= gBS
->HandleProtocol (
656 &gEfiFirmwareVolume2ProtocolGuid
,
659 ASSERT_EFI_ERROR (Status
);
661 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
663 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
666 Status
= FvProtocol
->ReadFile (
668 &FvFileNode
->FvFileName
, // NameGuid
673 &AuthenticationStatus
675 if (!EFI_ERROR (Status
)) {
677 // The FvFile was found. Keep the boot option.
684 // Delete the boot option.
686 Status
= EfiBootManagerDeleteLoadOptionVariable (
687 BootOptions
[Index
].OptionNumber
,
691 CHAR16
*DevicePathString
;
693 DevicePathString
= ConvertDevicePathToText (
694 BootOptions
[Index
].FilePath
,
699 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
700 "%a: removing stale Boot#%04x %s: %r\n",
702 (UINT32
)BootOptions
[Index
].OptionNumber
,
703 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
706 if (DevicePathString
!= NULL
) {
707 FreePool (DevicePathString
);
713 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
718 PlatformRegisterOptionsAndKeys (
726 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
729 // Register ENTER as CONTINUE key
731 Enter
.ScanCode
= SCAN_NULL
;
732 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
733 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
734 ASSERT_EFI_ERROR (Status
);
737 // Map F2 and ESC to Boot Manager Menu
739 F2
.ScanCode
= SCAN_F2
;
740 F2
.UnicodeChar
= CHAR_NULL
;
741 Esc
.ScanCode
= SCAN_ESC
;
742 Esc
.UnicodeChar
= CHAR_NULL
;
743 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
744 ASSERT_EFI_ERROR (Status
);
745 Status
= EfiBootManagerAddKeyOptionVariable (
747 (UINT16
)BootOption
.OptionNumber
,
752 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
753 Status
= EfiBootManagerAddKeyOptionVariable (
755 (UINT16
)BootOption
.OptionNumber
,
760 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
764 // BDS Platform Functions
768 Do the platform init, can be customized by OEM/IBV
769 Possible things that can be done in PlatformBootManagerBeforeConsole:
770 > Update console variable: 1. include hot-plug devices;
771 > 2. Clear ConIn and add SOL for AMT
772 > Register new Driver#### or Boot####
773 > Register new Key####: e.g.: F12
774 > Signal ReadyToLock event
775 > Authentication action: 1. connect Auth devices;
776 > 2. Identify auto logon user.
780 PlatformBootManagerBeforeConsole (
784 UINT16 FrontPageTimeout
;
785 RETURN_STATUS PcdStatus
;
789 // Signal EndOfDxe PI Event
791 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
794 // Disable the TPM 2 platform hierarchy
796 ConfigureTpmPlatformHierarchy ();
799 // Dispatch deferred images after EndOfDxe event.
801 EfiBootManagerDispatchDeferredImages ();
804 // Locate the PCI root bridges and make the PCI bus driver connect each,
805 // non-recursively. This will produce a number of child handles with PciIo on
808 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
811 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
813 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
816 // Find all display class PCI devices (using the handles from the previous
817 // step), and connect them non-recursively. This should produce a number of
818 // child handles with GOPs on them.
820 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
823 // Now add the device path of all handles with GOP on them to ConOut and
826 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
829 // Add the hardcoded short-form USB keyboard device path to ConIn.
831 EfiBootManagerUpdateConsoleVariable (
833 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
,
838 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
841 &mSerialConsole
.TermType
.Guid
,
842 PcdGetPtr (PcdTerminalTypeGuidBuffer
)
844 EfiBootManagerUpdateConsoleVariable (
846 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
849 EfiBootManagerUpdateConsoleVariable (
851 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
854 EfiBootManagerUpdateConsoleVariable (
856 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
861 // Set the front page timeout from the QEMU configuration.
863 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
864 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
865 ASSERT_RETURN_ERROR (PcdStatus
);
867 // Reflect the PCD in the standard Timeout variable.
869 Status
= gRT
->SetVariable (
870 EFI_TIME_OUT_VARIABLE_NAME
,
871 &gEfiGlobalVariableGuid
,
872 (EFI_VARIABLE_NON_VOLATILE
|
873 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
874 EFI_VARIABLE_RUNTIME_ACCESS
),
875 sizeof FrontPageTimeout
,
879 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
880 "%a: SetVariable(%s, %u): %r\n",
882 EFI_TIME_OUT_VARIABLE_NAME
,
888 // Register platform-specific boot options and keyboard shortcuts.
890 PlatformRegisterOptionsAndKeys ();
893 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
894 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
896 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
899 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
900 // instances on Virtio PCI RNG devices.
902 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
906 Do the platform specific action after the console is ready
907 Possible things that can be done in PlatformBootManagerAfterConsole:
908 > Console post action:
909 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
910 > Signal console ready platform customized event
911 > Run diagnostics like memory testing
912 > Connect certain devices
913 > Dispatch additional option roms
914 > Special boot: e.g.: USB boot, enter UI
918 PlatformBootManagerAfterConsole (
922 RETURN_STATUS Status
;
925 // Show the splash screen.
927 BootLogoEnableLogo ();
930 // Process QEMU's -kernel command line option. The kernel booted this way
931 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
932 // connected any and all PCI root bridges, and then signaled the ACPI
935 TryRunningQemuKernel ();
938 // Connect the purported boot devices.
940 Status
= ConnectDevicesFromQemu ();
941 if (RETURN_ERROR (Status
)) {
943 // Connect the rest of the devices.
945 EfiBootManagerConnectAll ();
949 // Enumerate all possible boot options, then filter and reorder them based on
950 // the QEMU configuration.
952 EfiBootManagerRefreshAllBootOption ();
955 // Register UEFI Shell
957 PlatformRegisterFvBootOption (
959 L
"EFI Internal Shell",
963 RemoveStaleFvFileOptions ();
964 SetBootOrderFromQemu ();
966 PlatformBmPrintScRegisterHandler ();
970 This function is called each second during the boot manager waits the
973 @param TimeoutRemain The remaining timeout.
977 PlatformBootManagerWaitCallback (
981 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
982 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
983 UINT16 TimeoutInitial
;
985 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
988 // If PcdPlatformBootTimeOut is set to zero, then we consider
989 // that no progress update should be enacted.
991 if (TimeoutInitial
== 0) {
995 Black
.Raw
= 0x00000000;
996 White
.Raw
= 0x00FFFFFF;
998 BootLogoUpdateProgress (
1001 L
"Start boot option",
1003 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
1009 The function is called when no boot option could be launched,
1010 including platform recovery options and options pointing to applications
1011 built into firmware volumes.
1013 If this function returns, BDS attempts to enter an infinite loop.
1017 PlatformBootManagerUnableToBoot (
1023 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
1027 // BootManagerMenu doesn't contain the correct information when return status
1028 // is EFI_NOT_FOUND.
1030 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1031 if (EFI_ERROR (Status
)) {
1036 // Normally BdsDxe does not print anything to the system console, but this is
1037 // a last resort -- the end-user will likely not see any DEBUG messages
1038 // logged in this situation.
1040 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
1041 // here to see if it makes sense to request and wait for a keypress.
1043 if (gST
->ConIn
!= NULL
) {
1045 "%a: No bootable option or device was found.\n"
1046 "%a: Press any key to enter the Boot Manager Menu.\n",
1050 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1051 ASSERT_EFI_ERROR (Status
);
1052 ASSERT (Index
== 0);
1055 // Drain any queued keys.
1057 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
1059 // just throw away Key
1065 EfiBootManagerBoot (&BootManagerMenu
);