2 Platform BDS customizations.
4 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "BdsPlatform.h"
10 #include <Guid/RootBridgesConnectedEventGroup.h>
11 #include <Guid/SerialPortLibVendor.h>
12 #include <Protocol/FirmwareVolume2.h>
13 #include <Library/PlatformBmPrintScLib.h>
14 #include <Library/Tcg2PhysicalPresenceLib.h>
15 #include <Library/XenPlatformLib.h>
21 VOID
*mEfiDevPathNotifyReg
;
22 EFI_EVENT mEfiDevPathEvent
;
23 VOID
*mEmuVariableEventReg
;
24 EFI_EVENT mEmuVariableEvent
;
25 UINT16 mHostBridgeDevId
;
28 // Table of host IRQs matching PCI IRQs A-D
29 // (for configuring PCI Interrupt Line register)
31 CONST UINT8 PciHostIrqs
[] = {
44 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
51 @param[in] Handle - Handle of PCI device instance
52 @param[in] PciIo - PCI IO protocol instance
53 @param[in] Pci - PCI Header register block
57 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
59 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
64 // Function prototypes
68 VisitAllInstancesOfProtocol (
70 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
75 VisitAllPciInstancesOfProtocol (
76 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
80 InstallDevicePathCallback (
85 PlatformRegisterFvBootOption (
93 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
94 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
95 UINTN BootOptionCount
;
96 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
97 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
98 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
100 Status
= gBS
->HandleProtocol (
102 &gEfiLoadedImageProtocolGuid
,
103 (VOID
**)&LoadedImage
105 ASSERT_EFI_ERROR (Status
);
107 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
108 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
109 ASSERT (DevicePath
!= NULL
);
110 DevicePath
= AppendDevicePathNode (
112 (EFI_DEVICE_PATH_PROTOCOL
*)&FileNode
114 ASSERT (DevicePath
!= NULL
);
116 Status
= EfiBootManagerInitializeLoadOption (
118 LoadOptionNumberUnassigned
,
126 ASSERT_EFI_ERROR (Status
);
127 FreePool (DevicePath
);
129 BootOptions
= EfiBootManagerGetLoadOptions (
134 OptionIndex
= EfiBootManagerFindLoadOption (
140 if (OptionIndex
== -1) {
141 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
142 ASSERT_EFI_ERROR (Status
);
145 EfiBootManagerFreeLoadOption (&NewOption
);
146 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
150 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
151 whose device paths do not resolve exactly to an FvFile in the system.
153 This removes any boot options that point to binaries built into the firmware
154 and have become stale due to any of the following:
155 - DXEFV's base address or size changed (historical),
156 - DXEFV's FvNameGuid changed,
157 - the FILE_GUID of the pointed-to binary changed,
158 - the referenced binary is no longer built into the firmware.
160 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
161 avoids exact duplicates.
164 RemoveStaleFvFileOptions (
168 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
169 UINTN BootOptionCount
;
172 BootOptions
= EfiBootManagerGetLoadOptions (
177 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
178 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
183 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
184 // then keep the boot option.
186 Node1
= BootOptions
[Index
].FilePath
;
187 if (!((DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
) &&
188 (DevicePathSubType (Node1
) == HW_MEMMAP_DP
)) &&
189 !((DevicePathType (Node1
) == MEDIA_DEVICE_PATH
) &&
190 (DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)))
196 // If the second device path node is not FvFile(...), then keep the boot
199 Node2
= NextDevicePathNode (Node1
);
200 if ((DevicePathType (Node2
) != MEDIA_DEVICE_PATH
) ||
201 (DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
))
207 // Locate the Firmware Volume2 protocol instance that is denoted by the
208 // boot option. If this lookup fails (i.e., the boot option references a
209 // firmware volume that doesn't exist), then we'll proceed to delete the
213 Status
= gBS
->LocateDevicePath (
214 &gEfiFirmwareVolume2ProtocolGuid
,
219 if (!EFI_ERROR (Status
)) {
221 // The firmware volume was found; now let's see if it contains the FvFile
222 // identified by GUID.
224 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
225 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
227 EFI_FV_FILETYPE FoundType
;
228 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
229 UINT32 AuthenticationStatus
;
231 Status
= gBS
->HandleProtocol (
233 &gEfiFirmwareVolume2ProtocolGuid
,
236 ASSERT_EFI_ERROR (Status
);
238 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
240 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
243 Status
= FvProtocol
->ReadFile (
245 &FvFileNode
->FvFileName
, // NameGuid
250 &AuthenticationStatus
252 if (!EFI_ERROR (Status
)) {
254 // The FvFile was found. Keep the boot option.
261 // Delete the boot option.
263 Status
= EfiBootManagerDeleteLoadOptionVariable (
264 BootOptions
[Index
].OptionNumber
,
268 CHAR16
*DevicePathString
;
270 DevicePathString
= ConvertDevicePathToText (
271 BootOptions
[Index
].FilePath
,
276 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
277 "%a: removing stale Boot#%04x %s: %r\n",
279 (UINT32
)BootOptions
[Index
].OptionNumber
,
280 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
283 if (DevicePathString
!= NULL
) {
284 FreePool (DevicePathString
);
290 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
294 PlatformRegisterOptionsAndKeys (
302 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
305 // Register ENTER as CONTINUE key
307 Enter
.ScanCode
= SCAN_NULL
;
308 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
309 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
310 ASSERT_EFI_ERROR (Status
);
313 // Map F2 to Boot Manager Menu
315 F2
.ScanCode
= SCAN_F2
;
316 F2
.UnicodeChar
= CHAR_NULL
;
317 Esc
.ScanCode
= SCAN_ESC
;
318 Esc
.UnicodeChar
= CHAR_NULL
;
319 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
320 ASSERT_EFI_ERROR (Status
);
321 Status
= EfiBootManagerAddKeyOptionVariable (
323 (UINT16
)BootOption
.OptionNumber
,
328 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
329 Status
= EfiBootManagerAddKeyOptionVariable (
331 (UINT16
)BootOption
.OptionNumber
,
336 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
342 IN EFI_HANDLE RootBridgeHandle
,
350 ConnectVirtioPciRng (
351 IN EFI_HANDLE Handle
,
363 // BDS Platform Functions
367 Do the platform init, can be customized by OEM/IBV
369 Possible things that can be done in PlatformBootManagerBeforeConsole:
371 > Update console variable: 1. include hot-plug devices;
372 > 2. Clear ConIn and add SOL for AMT
373 > Register new Driver#### or Boot####
374 > Register new Key####: e.g.: F12
375 > Signal ReadyToLock event
376 > Authentication action: 1. connect Auth devices;
377 > 2. Identify auto logon user.
381 PlatformBootManagerBeforeConsole (
387 UINT16 FrontPageTimeout
;
388 RETURN_STATUS PcdStatus
;
390 DEBUG ((DEBUG_INFO
, "PlatformBootManagerBeforeConsole\n"));
391 InstallDevicePathCallback ();
393 VisitAllInstancesOfProtocol (
394 &gEfiPciRootBridgeIoProtocolGuid
,
400 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
402 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
405 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
406 // the preparation of S3 system information. That logic has a hard dependency
407 // on the presence of the FACS ACPI table. Since our ACPI tables are only
408 // installed after PCI enumeration completes, we must not trigger the S3 save
409 // earlier, hence we can't signal End-of-Dxe earlier.
411 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
413 if (PcdGetBool (PcdAcpiS3Enable
)) {
415 // Save the boot script too. Note that this will require us to emit the
416 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
422 // We need to connect all trusted consoles for TCG PP. Here we treat all
423 // consoles in OVMF to be trusted consoles.
425 // Cloud Hypervisor doesn't emulate any LPC bridge, which is why it must
426 // rely on the serial I/O port to be connected as a console. It reuses the
427 // definition from Xen as it is very generic.
429 PlatformInitializeConsole (
430 (XenDetected () || PcdGet16 (PcdOvmfHostBridgePciDevId
) == CLOUDHV_DEVICE_ID
) ? gXenPlatformConsole
: gPlatformConsole
434 // Process TPM PPI request; this may require keyboard input
436 Tcg2PhysicalPresenceLibProcessRequest (NULL
);
439 // Prevent further changes to LockBoxes or SMRAM.
440 // Any TPM 2 Physical Presence Interface opcode must be handled before.
443 Status
= gBS
->InstallProtocolInterface (
445 &gEfiDxeSmmReadyToLockProtocolGuid
,
446 EFI_NATIVE_INTERFACE
,
449 ASSERT_EFI_ERROR (Status
);
452 // Dispatch deferred images after EndOfDxe event and ReadyToLock
455 EfiBootManagerDispatchDeferredImages ();
458 // GPU passthrough only allows Console enablement after ROM image load
460 PlatformInitializeConsole (
461 XenDetected () ? gXenPlatformConsole
: gPlatformConsole
464 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
465 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
466 ASSERT_RETURN_ERROR (PcdStatus
);
468 // Reflect the PCD in the standard Timeout variable.
470 Status
= gRT
->SetVariable (
471 EFI_TIME_OUT_VARIABLE_NAME
,
472 &gEfiGlobalVariableGuid
,
473 (EFI_VARIABLE_NON_VOLATILE
|
474 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
475 EFI_VARIABLE_RUNTIME_ACCESS
),
476 sizeof FrontPageTimeout
,
480 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
481 "%a: SetVariable(%s, %u): %r\n",
483 EFI_TIME_OUT_VARIABLE_NAME
,
488 PlatformRegisterOptionsAndKeys ();
491 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
492 // instances on Virtio PCI RNG devices.
494 VisitAllInstancesOfProtocol (
495 &gEfiPciIoProtocolGuid
,
504 IN EFI_HANDLE RootBridgeHandle
,
512 // Make the PCI bus driver connect the root bridge, non-recursively. This
513 // will produce a number of child handles with PciIo on them.
515 Status
= gBS
->ConnectController (
516 RootBridgeHandle
, // ControllerHandle
517 NULL
, // DriverImageHandle
518 NULL
, // RemainingDevicePath -- produce all
528 ConnectVirtioPciRng (
529 IN EFI_HANDLE Handle
,
534 EFI_PCI_IO_PROTOCOL
*PciIo
;
545 // Read and check VendorId.
547 Status
= PciIo
->Pci
.Read (
550 PCI_VENDOR_ID_OFFSET
,
554 if (EFI_ERROR (Status
)) {
558 if (VendorId
!= VIRTIO_VENDOR_ID
) {
563 // Read DeviceId and RevisionId.
565 Status
= PciIo
->Pci
.Read (
568 PCI_DEVICE_ID_OFFSET
,
572 if (EFI_ERROR (Status
)) {
576 Status
= PciIo
->Pci
.Read (
579 PCI_REVISION_ID_OFFSET
,
583 if (EFI_ERROR (Status
)) {
588 // From DeviceId and RevisionId, determine whether the device is a
589 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
590 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
591 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
592 // only be sanity-checked, and SubsystemId will decide.
594 if ((DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) &&
595 (RevisionId
>= 0x01))
598 } else if ((DeviceId
>= 0x1000) && (DeviceId
<= 0x103F) && (RevisionId
== 0x00)) {
605 // Read and check SubsystemId as dictated by Virtio10.
607 Status
= PciIo
->Pci
.Read (
610 PCI_SUBSYSTEM_ID_OFFSET
,
614 if (EFI_ERROR (Status
)) {
618 if ((Virtio10
&& (SubsystemId
>= 0x40)) ||
619 (!Virtio10
&& (SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)))
621 Status
= gBS
->ConnectController (
622 Handle
, // ControllerHandle
623 NULL
, // DriverImageHandle -- connect all drivers
624 NULL
, // RemainingDevicePath -- produce all child handles
625 FALSE
// Recursive -- don't follow child handles
627 if (EFI_ERROR (Status
)) {
635 DEBUG ((DEBUG_ERROR
, "%a: %r\n", __FUNCTION__
, Status
));
640 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
642 @param[in] DeviceHandle Handle of the LPC Bridge device.
644 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
645 ConOut, ConIn, and ErrOut.
647 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
651 PrepareLpcBridgeDevicePath (
652 IN EFI_HANDLE DeviceHandle
656 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
657 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
661 Status
= gBS
->HandleProtocol (
663 &gEfiDevicePathProtocolGuid
,
666 if (EFI_ERROR (Status
)) {
670 TempDevicePath
= DevicePath
;
675 DevicePath
= AppendDevicePathNode (
677 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
680 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
685 DevicePath
= TempDevicePath
;
686 gPnp16550ComPortDeviceNode
.UID
= 0;
688 DevicePath
= AppendDevicePathNode (
690 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
692 DevicePath
= AppendDevicePathNode (
694 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
696 DevicePath
= AppendDevicePathNode (
698 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
704 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
705 if (DevPathStr
!= NULL
) {
708 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
710 gPnp16550ComPortDeviceNode
.UID
+ 1,
713 FreePool (DevPathStr
);
716 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
717 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
718 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
723 DevicePath
= TempDevicePath
;
724 gPnp16550ComPortDeviceNode
.UID
= 1;
726 DevicePath
= AppendDevicePathNode (
728 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
730 DevicePath
= AppendDevicePathNode (
732 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
734 DevicePath
= AppendDevicePathNode (
736 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
742 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
743 if (DevPathStr
!= NULL
) {
746 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
748 gPnp16550ComPortDeviceNode
.UID
+ 1,
751 FreePool (DevPathStr
);
754 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
755 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
756 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
762 VENDOR_DEVICE_PATH Guid
;
763 EFI_DEVICE_PATH_PROTOCOL End
;
764 } SERIAL_DEVICE_PATH
;
766 SERIAL_DEVICE_PATH serialDevicePath
= {
768 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, { sizeof (VENDOR_DEVICE_PATH
), 0 }
770 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
772 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 }
777 PrepareMicrovmDevicePath (
781 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
782 UINT16 HostBridgeDevId
;
784 HostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
785 if (HostBridgeDevId
!= MICROVM_PSEUDO_DEVICE_ID
) {
789 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)&serialDevicePath
;
790 DevicePath
= AppendDevicePathNode (
792 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
794 DevicePath
= AppendDevicePathNode (
796 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
799 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
800 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
801 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
806 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
807 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
812 EFI_HANDLE PciDeviceHandle
;
813 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
814 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
815 UINTN GopHandleCount
;
816 EFI_HANDLE
*GopHandleBuffer
;
818 if ((PciDevicePath
== NULL
) || (GopDevicePath
== NULL
)) {
819 return EFI_INVALID_PARAMETER
;
823 // Initialize the GopDevicePath to be PciDevicePath
825 *GopDevicePath
= PciDevicePath
;
826 TempPciDevicePath
= PciDevicePath
;
828 Status
= gBS
->LocateDevicePath (
829 &gEfiDevicePathProtocolGuid
,
833 if (EFI_ERROR (Status
)) {
838 // Try to connect this handle, so that GOP driver could start on this
839 // device and create child handles with GraphicsOutput Protocol installed
840 // on them, then we get device paths of these child handles and select
841 // them as possible console device.
843 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
845 Status
= gBS
->LocateHandleBuffer (
847 &gEfiGraphicsOutputProtocolGuid
,
852 if (!EFI_ERROR (Status
)) {
854 // Add all the child handles as possible Console Device
856 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
857 Status
= gBS
->HandleProtocol (
858 GopHandleBuffer
[Index
],
859 &gEfiDevicePathProtocolGuid
,
860 (VOID
*)&TempDevicePath
862 if (EFI_ERROR (Status
)) {
869 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
873 // In current implementation, we only enable one of the child handles
874 // as console device, i.e. sotre one of the child handle's device
875 // path to variable "ConOut"
876 // In future, we could select all child handles to be console device
879 *GopDevicePath
= TempDevicePath
;
882 // Delete the PCI device's path that added by
883 // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
885 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
886 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
890 gBS
->FreePool (GopHandleBuffer
);
897 Add PCI display to ConOut.
899 @param[in] DeviceHandle Handle of the PCI display device.
901 @retval EFI_SUCCESS The PCI display device has been added to ConOut.
903 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
907 PreparePciDisplayDevicePath (
908 IN EFI_HANDLE DeviceHandle
912 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
913 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
916 GopDevicePath
= NULL
;
917 Status
= gBS
->HandleProtocol (
919 &gEfiDevicePathProtocolGuid
,
922 if (EFI_ERROR (Status
)) {
926 GetGopDevicePath (DevicePath
, &GopDevicePath
);
927 DevicePath
= GopDevicePath
;
929 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
935 Add PCI Serial to ConOut, ConIn, ErrOut.
937 @param[in] DeviceHandle Handle of the PCI serial device.
939 @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
942 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
946 PreparePciSerialDevicePath (
947 IN EFI_HANDLE DeviceHandle
951 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
954 Status
= gBS
->HandleProtocol (
956 &gEfiDevicePathProtocolGuid
,
959 if (EFI_ERROR (Status
)) {
963 DevicePath
= AppendDevicePathNode (
965 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
967 DevicePath
= AppendDevicePathNode (
969 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
972 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
973 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
974 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
980 VisitAllInstancesOfProtocol (
982 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
988 EFI_HANDLE
*HandleBuffer
;
993 // Start to check all the PciIo to find all possible device
997 Status
= gBS
->LocateHandleBuffer (
1004 if (EFI_ERROR (Status
)) {
1008 for (Index
= 0; Index
< HandleCount
; Index
++) {
1009 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
1010 if (EFI_ERROR (Status
)) {
1014 Status
= (*CallBackFunction
)(
1015 HandleBuffer
[Index
],
1021 gBS
->FreePool (HandleBuffer
);
1028 VisitingAPciInstance (
1029 IN EFI_HANDLE Handle
,
1035 EFI_PCI_IO_PROTOCOL
*PciIo
;
1038 PciIo
= (EFI_PCI_IO_PROTOCOL
*)Instance
;
1041 // Check for all PCI device
1043 Status
= PciIo
->Pci
.Read (
1045 EfiPciIoWidthUint32
,
1047 sizeof (Pci
) / sizeof (UINT32
),
1050 if (EFI_ERROR (Status
)) {
1054 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
)Context
)(
1062 VisitAllPciInstances (
1063 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
1066 return VisitAllInstancesOfProtocol (
1067 &gEfiPciIoProtocolGuid
,
1068 VisitingAPciInstance
,
1069 (VOID
*)(UINTN
)CallBackFunction
1074 Do platform specific PCI Device check and add them to
1075 ConOut, ConIn, ErrOut.
1077 @param[in] Handle - Handle of PCI device instance
1078 @param[in] PciIo - PCI IO protocol instance
1079 @param[in] Pci - PCI Header register block
1081 @retval EFI_SUCCESS - PCI Device check and Console variable update
1083 @retval EFI_STATUS - PCI Device check or Console variable update fail.
1088 DetectAndPreparePlatformPciDevicePath (
1089 IN EFI_HANDLE Handle
,
1090 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1096 Status
= PciIo
->Attributes (
1098 EfiPciIoAttributeOperationEnable
,
1099 EFI_PCI_DEVICE_ENABLE
,
1102 ASSERT_EFI_ERROR (Status
);
1105 // Here we decide whether it is LPC Bridge
1107 if ((IS_PCI_LPC (Pci
)) ||
1108 ((IS_PCI_ISA_PDECODE (Pci
)) &&
1109 (Pci
->Hdr
.VendorId
== 0x8086) &&
1110 (Pci
->Hdr
.DeviceId
== 0x7000)
1115 // Add IsaKeyboard to ConIn,
1116 // add IsaSerial to ConOut, ConIn, ErrOut
1118 DEBUG ((DEBUG_INFO
, "Found LPC Bridge device\n"));
1119 PrepareLpcBridgeDevicePath (Handle
);
1124 // Here we decide which Serial device to enable in PCI bus
1126 if (IS_PCI_16550SERIAL (Pci
)) {
1128 // Add them to ConOut, ConIn, ErrOut.
1130 DEBUG ((DEBUG_INFO
, "Found PCI 16550 SERIAL device\n"));
1131 PreparePciSerialDevicePath (Handle
);
1136 // Here we decide which display device to enable in PCI bus
1138 if (IS_PCI_DISPLAY (Pci
)) {
1140 // Add them to ConOut.
1142 DEBUG ((DEBUG_INFO
, "Found PCI display device\n"));
1143 PreparePciDisplayDevicePath (Handle
);
1151 Connect the predefined platform default console device.
1153 Always try to find and enable PCI display devices.
1155 @param[in] PlatformConsole Predefined platform default console device array.
1158 PlatformInitializeConsole (
1159 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
1165 // Do platform specific PCI Device check and add them to ConOut, ConIn,
1168 VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
1170 PrepareMicrovmDevicePath ();
1173 // Have chance to connect the platform default console,
1174 // the platform default console is the minimum device group
1175 // the platform should support
1177 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
1179 // Update the console variable with the connect type
1181 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
1182 EfiBootManagerUpdateConsoleVariable (
1184 PlatformConsole
[Index
].DevicePath
,
1189 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
1190 EfiBootManagerUpdateConsoleVariable (
1192 PlatformConsole
[Index
].DevicePath
,
1197 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
1198 EfiBootManagerUpdateConsoleVariable (
1200 PlatformConsole
[Index
].DevicePath
,
1208 Configure PCI Interrupt Line register for applicable devices
1209 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
1211 @param[in] Handle - Handle of PCI device instance
1212 @param[in] PciIo - PCI IO protocol instance
1213 @param[in] PciHdr - PCI Header register block
1215 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
1221 IN EFI_HANDLE Handle
,
1222 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1223 IN PCI_TYPE00
*PciHdr
1226 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1227 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1232 UINT32 RootBusNumber
;
1234 Status
= EFI_SUCCESS
;
1236 if (PciHdr
->Device
.InterruptPin
!= 0) {
1237 DevPathNode
= DevicePathFromHandle (Handle
);
1238 ASSERT (DevPathNode
!= NULL
);
1239 DevPath
= DevPathNode
;
1242 if ((DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
) &&
1243 (DevicePathSubType (DevPathNode
) == ACPI_DP
) &&
1244 (((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID (0x0A03)))
1246 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1250 // Compute index into PciHostIrqs[] table by walking
1251 // the device path and adding up all device numbers
1253 Status
= EFI_NOT_FOUND
;
1255 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1256 while (!IsDevicePathEnd (DevPathNode
)) {
1257 if ((DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
) &&
1258 (DevicePathSubType (DevPathNode
) == HW_PCI_DP
))
1260 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1263 // Unlike SeaBIOS, which starts climbing from the leaf device
1264 // up toward the root, we traverse the device path starting at
1265 // the root moving toward the leaf node.
1266 // The slot number of the top-level parent bridge is needed for
1267 // Q35 cases with more than 24 slots on the root bus.
1269 if (Status
!= EFI_SUCCESS
) {
1270 Status
= EFI_SUCCESS
;
1271 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1275 DevPathNode
= NextDevicePathNode (DevPathNode
);
1278 if (EFI_ERROR (Status
)) {
1282 if ((RootBusNumber
== 0) && (RootSlot
== 0)) {
1285 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1292 // Final PciHostIrqs[] index calculation depends on the platform
1293 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1295 switch (mHostBridgeDevId
) {
1296 case INTEL_82441_DEVICE_ID
:
1299 case INTEL_Q35_MCH_DEVICE_ID
:
1301 // SeaBIOS contains the following comment:
1302 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1303 // with a different starting index - see q35-acpi-dsdt.dsl.
1305 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1307 if (RootSlot
> 24) {
1309 // in this case, subtract back out RootSlot from Idx
1310 // (SeaBIOS never adds it to begin with, but that would make our
1311 // device path traversal loop above too awkward)
1318 ASSERT (FALSE
); // should never get here
1321 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1322 IrqLine
= PciHostIrqs
[Idx
];
1324 DEBUG_CODE_BEGIN ();
1326 CHAR16
*DevPathString
;
1327 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1328 UINTN Segment
, Bus
, Device
, Function
;
1330 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1331 if (DevPathString
== NULL
) {
1332 DevPathString
= Fallback
;
1335 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1336 ASSERT_EFI_ERROR (Status
);
1340 "%a: [%02x:%02x.%x] %s -> 0x%02x\n",
1349 if (DevPathString
!= Fallback
) {
1350 FreePool (DevPathString
);
1356 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1358 Status
= PciIo
->Pci
.Write (
1361 PCI_INT_LINE_OFFSET
,
1371 PciAcpiInitialization (
1377 // Query Host Bridge DID to determine platform type
1379 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1380 switch (mHostBridgeDevId
) {
1381 case INTEL_82441_DEVICE_ID
:
1382 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1384 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1386 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), PciHostIrqs
[0]); // A
1387 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), PciHostIrqs
[1]); // B
1388 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), PciHostIrqs
[2]); // C
1389 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), PciHostIrqs
[3]); // D
1391 case INTEL_Q35_MCH_DEVICE_ID
:
1392 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1394 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1396 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), PciHostIrqs
[0]); // A
1397 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), PciHostIrqs
[1]); // B
1398 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), PciHostIrqs
[2]); // C
1399 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), PciHostIrqs
[3]); // D
1400 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), PciHostIrqs
[0]); // E
1401 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), PciHostIrqs
[1]); // F
1402 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), PciHostIrqs
[2]); // G
1403 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), PciHostIrqs
[3]); // H
1405 case MICROVM_PSEUDO_DEVICE_ID
:
1406 case CLOUDHV_DEVICE_ID
:
1409 if (XenDetected ()) {
1411 // There is no PCI bus in this case.
1418 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1427 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1429 VisitAllPciInstances (SetPciIntLine
);
1432 // Set ACPI SCI_EN bit in PMCNTRL
1434 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1439 ConnectRecursivelyIfPciMassStorage (
1440 IN EFI_HANDLE Handle
,
1441 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1442 IN PCI_TYPE00
*PciHeader
1446 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1450 // Recognize PCI Mass Storage, and Xen PCI devices
1452 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ||
1453 (XenDetected () && IS_CLASS2 (PciHeader
, 0xFF, 0x80)))
1456 Status
= gBS
->HandleProtocol (
1458 &gEfiDevicePathProtocolGuid
,
1461 if (EFI_ERROR (Status
)) {
1466 // Print Device Path
1468 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1469 if (DevPathStr
!= NULL
) {
1472 "Found %s device: %s\n",
1473 (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ?
1479 FreePool (DevPathStr
);
1482 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1483 if (EFI_ERROR (Status
)) {
1492 This notification function is invoked when the
1493 EMU Variable FVB has been changed.
1495 @param Event The event that occurred
1496 @param Context For EFI compatibility. Not used.
1501 EmuVariablesUpdatedCallback (
1506 DEBUG ((DEBUG_INFO
, "EmuVariablesUpdatedCallback\n"));
1507 UpdateNvVarsOnFileSystem ();
1512 VisitingFileSystemInstance (
1513 IN EFI_HANDLE Handle
,
1519 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1520 RETURN_STATUS PcdStatus
;
1522 if (ConnectedToFileSystem
) {
1523 return EFI_ALREADY_STARTED
;
1526 Status
= ConnectNvVarsToFileSystem (Handle
);
1527 if (EFI_ERROR (Status
)) {
1531 ConnectedToFileSystem
= TRUE
;
1533 EfiCreateProtocolNotifyEvent (
1534 &gEfiDevicePathProtocolGuid
,
1536 EmuVariablesUpdatedCallback
,
1538 &mEmuVariableEventReg
1540 PcdStatus
= PcdSet64S (
1541 PcdEmuVariableEvent
,
1542 (UINT64
)(UINTN
)mEmuVariableEvent
1544 ASSERT_RETURN_ERROR (PcdStatus
);
1550 PlatformBdsRestoreNvVarsFromHardDisk (
1553 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1554 VisitAllInstancesOfProtocol (
1555 &gEfiSimpleFileSystemProtocolGuid
,
1556 VisitingFileSystemInstance
,
1562 Connect with predefined platform connect sequence.
1564 The OEM/IBV can customize with their own connect sequence.
1567 PlatformBdsConnectSequence (
1572 RETURN_STATUS Status
;
1574 DEBUG ((DEBUG_INFO
, "PlatformBdsConnectSequence\n"));
1579 // Here we can get the customized platform connect sequence
1580 // Notes: we can connect with new variable which record the
1581 // last time boots connect device path sequence
1583 while (gPlatformConnectSequence
[Index
] != NULL
) {
1585 // Build the platform boot option
1587 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1591 Status
= ConnectDevicesFromQemu ();
1592 if (RETURN_ERROR (Status
)) {
1594 // Just use the simple policy to connect all devices
1596 DEBUG ((DEBUG_INFO
, "EfiBootManagerConnectAll\n"));
1597 EfiBootManagerConnectAll ();
1602 Save the S3 boot script.
1604 Note that DxeSmmReadyToLock must be signaled after this function returns;
1605 otherwise the script wouldn't be saved actually.
1614 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1615 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1617 Status
= gBS
->LocateProtocol (
1618 &gEfiS3SaveStateProtocolGuid
,
1620 (VOID
**)&BootScript
1622 ASSERT_EFI_ERROR (Status
);
1625 // Despite the opcode documentation in the PI spec, the protocol
1626 // implementation embeds a deep copy of the info in the boot script, rather
1627 // than storing just a pointer to runtime or NVS storage.
1629 Status
= BootScript
->Write (
1631 EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1632 (UINT32
)sizeof Info
,
1633 (EFI_PHYSICAL_ADDRESS
)(UINTN
)&Info
1635 ASSERT_EFI_ERROR (Status
);
1639 Do the platform specific action after the console is ready
1641 Possible things that can be done in PlatformBootManagerAfterConsole:
1643 > Console post action:
1644 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1645 > Signal console ready platform customized event
1646 > Run diagnostics like memory testing
1647 > Connect certain devices
1648 > Dispatch aditional option roms
1649 > Special boot: e.g.: USB boot, enter UI
1653 PlatformBootManagerAfterConsole (
1657 EFI_BOOT_MODE BootMode
;
1659 DEBUG ((DEBUG_INFO
, "PlatformBootManagerAfterConsole\n"));
1661 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1664 "PlatformBdsPolicyBehavior: not restoring NvVars "
1665 "from disk since flash variables appear to be supported.\n"
1669 // Try to restore variables from the hard disk early so
1670 // they can be used for the other BDS connect operations.
1672 PlatformBdsRestoreNvVarsFromHardDisk ();
1676 // Get current Boot Mode
1678 BootMode
= GetBootModeHob ();
1679 DEBUG ((DEBUG_INFO
, "Boot Mode:%x\n", BootMode
));
1682 // Go the different platform policy with different boot mode
1683 // Notes: this part code can be change with the table policy
1685 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1690 BootLogoEnableLogo ();
1693 // Set PCI Interrupt Line registers and ACPI SCI_EN
1695 PciAcpiInitialization ();
1698 // Write qemu bootorder to efi variables
1700 StoreQemuBootOrder ();
1703 // Process QEMU's -kernel command line option
1705 TryRunningQemuKernel ();
1708 // Perform some platform specific connect sequence
1710 PlatformBdsConnectSequence ();
1712 EfiBootManagerRefreshAllBootOption ();
1715 // Register UEFI Shell
1717 PlatformRegisterFvBootOption (
1718 &gUefiShellFileGuid
,
1719 L
"EFI Internal Shell",
1723 RemoveStaleFvFileOptions ();
1724 SetBootOrderFromQemu ();
1726 PlatformBmPrintScRegisterHandler ();
1730 This notification function is invoked when an instance of the
1731 EFI_DEVICE_PATH_PROTOCOL is produced.
1733 @param Event The event that occurred
1734 @param Context For EFI compatibility. Not used.
1747 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1748 ATAPI_DEVICE_PATH
*Atapi
;
1751 // Examine all new handles
1755 // Get the next handle
1757 BufferSize
= sizeof (Handle
);
1758 Status
= gBS
->LocateHandle (
1761 mEfiDevPathNotifyReg
,
1767 // If not found, we're done
1769 if (EFI_NOT_FOUND
== Status
) {
1773 if (EFI_ERROR (Status
)) {
1778 // Get the DevicePath protocol on that handle
1780 Status
= gBS
->HandleProtocol (
1782 &gEfiDevicePathProtocolGuid
,
1783 (VOID
**)&DevPathNode
1785 ASSERT_EFI_ERROR (Status
);
1787 while (!IsDevicePathEnd (DevPathNode
)) {
1789 // Find the handler to dump this device path node
1792 (DevicePathType (DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1793 (DevicePathSubType (DevPathNode
) == MSG_ATAPI_DP
)
1796 Atapi
= (ATAPI_DEVICE_PATH
*)DevPathNode
;
1802 (Atapi
->PrimarySecondary
== 1) ? 0x42 : 0x40
1809 // Next device path node
1811 DevPathNode
= NextDevicePathNode (DevPathNode
);
1819 InstallDevicePathCallback (
1823 DEBUG ((DEBUG_INFO
, "Registered NotifyDevPath Event\n"));
1824 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1825 &gEfiDevicePathProtocolGuid
,
1829 &mEfiDevPathNotifyReg
1834 This function is called each second during the boot manager waits the
1837 @param TimeoutRemain The remaining timeout.
1841 PlatformBootManagerWaitCallback (
1842 UINT16 TimeoutRemain
1845 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1846 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1847 UINT16 TimeoutInitial
;
1849 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
1852 // If PcdPlatformBootTimeOut is set to zero, then we consider
1853 // that no progress update should be enacted (since we'd only
1854 // ever display a one-shot progress of either 0% or 100%).
1856 if (TimeoutInitial
== 0) {
1860 Black
.Raw
= 0x00000000;
1861 White
.Raw
= 0x00FFFFFF;
1863 BootLogoUpdateProgress (
1866 L
"Start boot option",
1868 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
1874 The function is called when no boot option could be launched,
1875 including platform recovery options and options pointing to applications
1876 built into firmware volumes.
1878 If this function returns, BDS attempts to enter an infinite loop.
1882 PlatformBootManagerUnableToBoot (
1888 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
1892 // BootManagerMenu doesn't contain the correct information when return status
1893 // is EFI_NOT_FOUND.
1895 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1896 if (EFI_ERROR (Status
)) {
1901 // Normally BdsDxe does not print anything to the system console, but this is
1902 // a last resort -- the end-user will likely not see any DEBUG messages
1903 // logged in this situation.
1905 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
1906 // here to see if it makes sense to request and wait for a keypress.
1908 if (gST
->ConIn
!= NULL
) {
1910 "%a: No bootable option or device was found.\n"
1911 "%a: Press any key to enter the Boot Manager Menu.\n",
1915 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1916 ASSERT_EFI_ERROR (Status
);
1917 ASSERT (Index
== 0);
1920 // Drain any queued keys.
1922 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
1924 // just throw away Key
1930 EfiBootManagerBoot (&BootManagerMenu
);