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>
32 #include <Guid/TtyTerm.h>
34 #include "PlatformBm.h"
36 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
38 #define VERSION_STRING_PREFIX L"RISC-V EDK2 firmware version "
42 VENDOR_DEVICE_PATH SerialDxe
;
43 UART_DEVICE_PATH Uart
;
44 VENDOR_DEFINED_DEVICE_PATH TermType
;
45 EFI_DEVICE_PATH_PROTOCOL End
;
46 } PLATFORM_SERIAL_CONSOLE
;
49 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
51 // VENDOR_DEVICE_PATH SerialDxe
54 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
55 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
59 // UART_DEVICE_PATH Uart
62 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
64 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
65 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
66 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
67 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
71 // VENDOR_DEFINED_DEVICE_PATH TermType
75 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
76 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
79 // Guid to be filled in dynamically
84 // EFI_DEVICE_PATH_PROTOCOL End
87 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
88 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
94 USB_CLASS_DEVICE_PATH Keyboard
;
95 EFI_DEVICE_PATH_PROTOCOL End
;
96 } PLATFORM_USB_KEYBOARD
;
99 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
101 // USB_CLASS_DEVICE_PATH Keyboard
105 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
106 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
108 0xFFFF, // VendorId: any
109 0xFFFF, // ProductId: any
110 3, // DeviceClass: HID
111 1, // DeviceSubClass: boot
112 1 // DeviceProtocol: keyboard
116 // EFI_DEVICE_PATH_PROTOCOL End
119 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
120 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
125 Check if the handle satisfies a particular condition.
127 @param[in] Handle The handle to check.
128 @param[in] ReportText A caller-allocated string passed in for reporting
129 purposes. It must never be NULL.
131 @retval TRUE The condition is satisfied.
132 @retval FALSE Otherwise. This includes the case when the condition could not
133 be fully evaluated due to an error.
137 (EFIAPI
*FILTER_FUNCTION
)(
138 IN EFI_HANDLE Handle
,
139 IN CONST CHAR16
*ReportText
145 @param[in] Handle The handle to process.
146 @param[in] ReportText A caller-allocated string passed in for reporting
147 purposes. It must never be NULL.
151 (EFIAPI
*CALLBACK_FUNCTION
)(
152 IN EFI_HANDLE Handle
,
153 IN CONST CHAR16
*ReportText
157 Locate all handles that carry the specified protocol, filter them with a
158 callback function, and pass each handle that passes the filter to another
161 @param[in] ProtocolGuid The protocol to look for.
163 @param[in] Filter The filter function to pass each handle to. If this
164 parameter is NULL, then all handles are processed.
166 @param[in] Process The callback function to pass each handle to that
172 IN EFI_GUID
*ProtocolGuid
,
173 IN FILTER_FUNCTION Filter OPTIONAL
,
174 IN CALLBACK_FUNCTION Process
182 Status
= gBS
->LocateHandleBuffer (
185 NULL
/* SearchKey */,
189 if (EFI_ERROR (Status
)) {
191 // This is not an error, just an informative condition.
203 ASSERT (NoHandles
> 0);
204 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
205 CHAR16
*DevicePathText
;
206 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
209 // The ConvertDevicePathToText() function handles NULL input transparently.
211 DevicePathText
= ConvertDevicePathToText (
212 DevicePathFromHandle (Handles
[Idx
]),
213 FALSE
, // DisplayOnly
214 FALSE
// AllowShortcuts
216 if (DevicePathText
== NULL
) {
217 DevicePathText
= Fallback
;
220 if ((Filter
== NULL
) || Filter (Handles
[Idx
], DevicePathText
)) {
221 Process (Handles
[Idx
], DevicePathText
);
224 if (DevicePathText
!= Fallback
) {
225 FreePool (DevicePathText
);
229 gBS
->FreePool (Handles
);
233 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
239 IN EFI_HANDLE Handle
,
240 IN CONST CHAR16
*ReportText
244 EFI_PCI_IO_PROTOCOL
*PciIo
;
247 Status
= gBS
->HandleProtocol (
249 &gEfiPciIoProtocolGuid
,
252 if (EFI_ERROR (Status
)) {
254 // This is not an error worth reporting.
259 Status
= PciIo
->Pci
.Read (
263 sizeof Pci
/ sizeof (UINT32
),
266 if (EFI_ERROR (Status
)) {
267 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
271 return IS_PCI_DISPLAY (&Pci
);
275 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
276 the VIRTIO_DEVICE_PROTOCOL level.
282 IN EFI_HANDLE Handle
,
283 IN CONST CHAR16
*ReportText
287 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
289 Status
= gBS
->HandleProtocol (
291 &gVirtioDeviceProtocolGuid
,
294 if (EFI_ERROR (Status
)) {
298 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
299 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
303 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
304 the EFI_PCI_IO_PROTOCOL level.
310 IN EFI_HANDLE Handle
,
311 IN CONST CHAR16
*ReportText
315 EFI_PCI_IO_PROTOCOL
*PciIo
;
322 Status
= gBS
->HandleProtocol (
324 &gEfiPciIoProtocolGuid
,
327 if (EFI_ERROR (Status
)) {
332 // Read and check VendorId.
334 Status
= PciIo
->Pci
.Read (
337 PCI_VENDOR_ID_OFFSET
,
341 if (EFI_ERROR (Status
)) {
345 if (VendorId
!= VIRTIO_VENDOR_ID
) {
350 // Read DeviceId and RevisionId.
352 Status
= PciIo
->Pci
.Read (
355 PCI_DEVICE_ID_OFFSET
,
359 if (EFI_ERROR (Status
)) {
363 Status
= PciIo
->Pci
.Read (
366 PCI_REVISION_ID_OFFSET
,
370 if (EFI_ERROR (Status
)) {
375 // From DeviceId and RevisionId, determine whether the device is a
376 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
377 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
378 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
379 // only be sanity-checked, and SubsystemId will decide.
381 if ((DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) &&
382 (RevisionId
>= 0x01))
385 } else if ((DeviceId
>= 0x1000) && (DeviceId
<= 0x103F) && (RevisionId
== 0x00)) {
392 // Read and check SubsystemId as dictated by Virtio10.
394 Status
= PciIo
->Pci
.Read (
397 PCI_SUBSYSTEM_ID_OFFSET
,
401 if (EFI_ERROR (Status
)) {
405 if (Virtio10
&& (SubsystemId
>= 0x40)) {
409 if (!Virtio10
&& (SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)) {
416 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
421 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
422 the matching driver to produce all first-level child handles.
428 IN EFI_HANDLE Handle
,
429 IN CONST CHAR16
*ReportText
434 Status
= gBS
->ConnectController (
435 Handle
, // ControllerHandle
436 NULL
, // DriverImageHandle
437 NULL
, // RemainingDevicePath -- produce all children
441 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
450 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
451 handle, and adds it to ConOut and ErrOut.
457 IN EFI_HANDLE Handle
,
458 IN CONST CHAR16
*ReportText
462 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
464 DevicePath
= DevicePathFromHandle (Handle
);
465 if (DevicePath
== NULL
) {
468 "%a: %s: handle %p: device path not found\n",
476 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
477 if (EFI_ERROR (Status
)) {
480 "%a: %s: adding to ConOut: %r\n",
488 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
489 if (EFI_ERROR (Status
)) {
492 "%a: %s: adding to ErrOut: %r\n",
502 "%a: %s: added to ConOut and ErrOut\n",
510 PlatformRegisterFvBootOption (
518 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
519 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
520 UINTN BootOptionCount
;
521 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
522 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
523 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
525 Status
= gBS
->HandleProtocol (
527 &gEfiLoadedImageProtocolGuid
,
528 (VOID
**)&LoadedImage
530 ASSERT_EFI_ERROR (Status
);
532 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
533 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
534 ASSERT (DevicePath
!= NULL
);
535 DevicePath
= AppendDevicePathNode (
537 (EFI_DEVICE_PATH_PROTOCOL
*)&FileNode
539 ASSERT (DevicePath
!= NULL
);
541 Status
= EfiBootManagerInitializeLoadOption (
543 LoadOptionNumberUnassigned
,
551 ASSERT_EFI_ERROR (Status
);
552 FreePool (DevicePath
);
554 BootOptions
= EfiBootManagerGetLoadOptions (
559 OptionIndex
= EfiBootManagerFindLoadOption (
565 if (OptionIndex
== -1) {
566 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
567 ASSERT_EFI_ERROR (Status
);
570 EfiBootManagerFreeLoadOption (&NewOption
);
571 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
575 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
576 whose device paths do not resolve exactly to an FvFile in the system.
578 This removes any boot options that point to binaries built into the firmware
579 and have become stale due to any of the following:
580 - FvMain's base address or size changed (historical),
581 - FvMain's FvNameGuid changed,
582 - the FILE_GUID of the pointed-to binary changed,
583 - the referenced binary is no longer built into the firmware.
585 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
586 avoids exact duplicates.
590 RemoveStaleFvFileOptions (
594 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
595 UINTN BootOptionCount
;
598 BootOptions
= EfiBootManagerGetLoadOptions (
603 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
604 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
609 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
610 // then keep the boot option.
612 Node1
= BootOptions
[Index
].FilePath
;
613 if (!((DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
) &&
614 (DevicePathSubType (Node1
) == HW_MEMMAP_DP
)) &&
615 !((DevicePathType (Node1
) == MEDIA_DEVICE_PATH
) &&
616 (DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)))
622 // If the second device path node is not FvFile(...), then keep the boot
625 Node2
= NextDevicePathNode (Node1
);
626 if ((DevicePathType (Node2
) != MEDIA_DEVICE_PATH
) ||
627 (DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
))
633 // Locate the Firmware Volume2 protocol instance that is denoted by the
634 // boot option. If this lookup fails (i.e., the boot option references a
635 // firmware volume that doesn't exist), then we'll proceed to delete the
639 Status
= gBS
->LocateDevicePath (
640 &gEfiFirmwareVolume2ProtocolGuid
,
645 if (!EFI_ERROR (Status
)) {
647 // The firmware volume was found; now let's see if it contains the FvFile
648 // identified by GUID.
650 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
651 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
653 EFI_FV_FILETYPE FoundType
;
654 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
655 UINT32 AuthenticationStatus
;
657 Status
= gBS
->HandleProtocol (
659 &gEfiFirmwareVolume2ProtocolGuid
,
662 ASSERT_EFI_ERROR (Status
);
664 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
666 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
669 Status
= FvProtocol
->ReadFile (
671 &FvFileNode
->FvFileName
, // NameGuid
676 &AuthenticationStatus
678 if (!EFI_ERROR (Status
)) {
680 // The FvFile was found. Keep the boot option.
687 // Delete the boot option.
689 Status
= EfiBootManagerDeleteLoadOptionVariable (
690 BootOptions
[Index
].OptionNumber
,
694 CHAR16
*DevicePathString
;
696 DevicePathString
= ConvertDevicePathToText (
697 BootOptions
[Index
].FilePath
,
702 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
703 "%a: removing stale Boot#%04x %s: %r\n",
705 (UINT32
)BootOptions
[Index
].OptionNumber
,
706 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
709 if (DevicePathString
!= NULL
) {
710 FreePool (DevicePathString
);
716 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
721 PlatformRegisterOptionsAndKeys (
729 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
732 // Register ENTER as CONTINUE key
734 Enter
.ScanCode
= SCAN_NULL
;
735 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
736 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
737 ASSERT_EFI_ERROR (Status
);
740 // Map F2 and ESC to Boot Manager Menu
742 F2
.ScanCode
= SCAN_F2
;
743 F2
.UnicodeChar
= CHAR_NULL
;
744 Esc
.ScanCode
= SCAN_ESC
;
745 Esc
.UnicodeChar
= CHAR_NULL
;
746 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
747 ASSERT_EFI_ERROR (Status
);
748 Status
= EfiBootManagerAddKeyOptionVariable (
750 (UINT16
)BootOption
.OptionNumber
,
755 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
756 Status
= EfiBootManagerAddKeyOptionVariable (
758 (UINT16
)BootOption
.OptionNumber
,
763 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
767 // BDS Platform Functions
771 Do the platform init, can be customized by OEM/IBV
772 Possible things that can be done in PlatformBootManagerBeforeConsole:
773 > Update console variable: 1. include hot-plug devices;
774 > 2. Clear ConIn and add SOL for AMT
775 > Register new Driver#### or Boot####
776 > Register new Key####: e.g.: F12
777 > Signal ReadyToLock event
778 > Authentication action: 1. connect Auth devices;
779 > 2. Identify auto logon user.
783 PlatformBootManagerBeforeConsole (
787 UINT16 FrontPageTimeout
;
788 RETURN_STATUS PcdStatus
;
792 // Signal EndOfDxe PI Event
794 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
797 // Disable the TPM 2 platform hierarchy
799 ConfigureTpmPlatformHierarchy ();
802 // Dispatch deferred images after EndOfDxe event.
804 EfiBootManagerDispatchDeferredImages ();
807 // Locate the PCI root bridges and make the PCI bus driver connect each,
808 // non-recursively. This will produce a number of child handles with PciIo on
811 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
814 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
816 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
819 // Find all display class PCI devices (using the handles from the previous
820 // step), and connect them non-recursively. This should produce a number of
821 // child handles with GOPs on them.
823 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
826 // Now add the device path of all handles with GOP on them to ConOut and
829 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
832 // Add the hardcoded short-form USB keyboard device path to ConIn.
834 EfiBootManagerUpdateConsoleVariable (
836 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
,
841 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
843 CopyGuid (&mSerialConsole
.TermType
.Guid
, &gEfiTtyTermGuid
);
845 EfiBootManagerUpdateConsoleVariable (
847 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
850 EfiBootManagerUpdateConsoleVariable (
852 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
855 EfiBootManagerUpdateConsoleVariable (
857 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
862 // Set the front page timeout from the QEMU configuration.
864 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
865 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
866 ASSERT_RETURN_ERROR (PcdStatus
);
868 // Reflect the PCD in the standard Timeout variable.
870 Status
= gRT
->SetVariable (
871 EFI_TIME_OUT_VARIABLE_NAME
,
872 &gEfiGlobalVariableGuid
,
873 (EFI_VARIABLE_NON_VOLATILE
|
874 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
875 EFI_VARIABLE_RUNTIME_ACCESS
),
876 sizeof FrontPageTimeout
,
880 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
881 "%a: SetVariable(%s, %u): %r\n",
883 EFI_TIME_OUT_VARIABLE_NAME
,
889 // Register platform-specific boot options and keyboard shortcuts.
891 PlatformRegisterOptionsAndKeys ();
894 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
895 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
897 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
900 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
901 // instances on Virtio PCI RNG devices.
903 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
907 Do the platform specific action after the console is ready
908 Possible things that can be done in PlatformBootManagerAfterConsole:
909 > Console post action:
910 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
911 > Signal console ready platform customized event
912 > Run diagnostics like memory testing
913 > Connect certain devices
914 > Dispatch additional option roms
915 > Special boot: e.g.: USB boot, enter UI
919 PlatformBootManagerAfterConsole (
923 RETURN_STATUS Status
;
924 UINTN FirmwareVerLength
;
926 FirmwareVerLength
= StrLen (PcdGetPtr (PcdFirmwareVersionString
));
928 // Show the splash screen.
930 BootLogoEnableLogo ();
932 if (FirmwareVerLength
> 0) {
934 VERSION_STRING_PREFIX L
"%s\n",
935 PcdGetPtr (PcdFirmwareVersionString
)
939 Print (L
"Press ESCAPE within 10 seconds for boot options ");
941 // Process QEMU's -kernel command line option. The kernel booted this way
942 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
943 // connected any and all PCI root bridges, and then signaled the ACPI
946 TryRunningQemuKernel ();
949 // Connect the purported boot devices.
951 Status
= ConnectDevicesFromQemu ();
952 if (RETURN_ERROR (Status
)) {
954 // Connect the rest of the devices.
956 EfiBootManagerConnectAll ();
960 // Enumerate all possible boot options, then filter and reorder them based on
961 // the QEMU configuration.
963 EfiBootManagerRefreshAllBootOption ();
966 // Register UEFI Shell
968 PlatformRegisterFvBootOption (
970 L
"EFI Internal Shell",
974 RemoveStaleFvFileOptions ();
975 SetBootOrderFromQemu ();
977 PlatformBmPrintScRegisterHandler ();
981 This function is called each second during the boot manager waits the
984 @param TimeoutRemain The remaining timeout.
988 PlatformBootManagerWaitCallback (
992 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
993 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
994 UINT16 TimeoutInitial
;
996 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
999 // If PcdPlatformBootTimeOut is set to zero, then we consider
1000 // that no progress update should be enacted.
1002 if (TimeoutInitial
== 0) {
1006 Black
.Raw
= 0x00000000;
1007 White
.Raw
= 0x00FFFFFF;
1009 BootLogoUpdateProgress (
1012 L
"Start boot option",
1014 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
1020 The function is called when no boot option could be launched,
1021 including platform recovery options and options pointing to applications
1022 built into firmware volumes.
1024 If this function returns, BDS attempts to enter an infinite loop.
1028 PlatformBootManagerUnableToBoot (
1034 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
1038 // BootManagerMenu doesn't contain the correct information when return status
1039 // is EFI_NOT_FOUND.
1041 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1042 if (EFI_ERROR (Status
)) {
1047 // Normally BdsDxe does not print anything to the system console, but this is
1048 // a last resort -- the end-user will likely not see any DEBUG messages
1049 // logged in this situation.
1051 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
1052 // here to see if it makes sense to request and wait for a keypress.
1054 if (gST
->ConIn
!= NULL
) {
1056 "%a: No bootable option or device was found.\n"
1057 "%a: Press any key to enter the Boot Manager Menu.\n",
1061 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1062 ASSERT_EFI_ERROR (Status
);
1063 ASSERT (Index
== 0);
1066 // Drain any queued keys.
1068 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
1070 // just throw away Key
1076 EfiBootManagerBoot (&BootManagerMenu
);