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.
421 // We need to connect all trusted consoles for TCG PP. Here we treat all
422 // consoles in OVMF to be trusted consoles.
423 PlatformInitializeConsole (
424 XenDetected () ? gXenPlatformConsole
: gPlatformConsole
428 // Process TPM PPI request; this may require keyboard input
430 Tcg2PhysicalPresenceLibProcessRequest (NULL
);
433 // Prevent further changes to LockBoxes or SMRAM.
434 // Any TPM 2 Physical Presence Interface opcode must be handled before.
437 Status
= gBS
->InstallProtocolInterface (
439 &gEfiDxeSmmReadyToLockProtocolGuid
,
440 EFI_NATIVE_INTERFACE
,
443 ASSERT_EFI_ERROR (Status
);
446 // Dispatch deferred images after EndOfDxe event and ReadyToLock
449 EfiBootManagerDispatchDeferredImages ();
452 // GPU passthrough only allows Console enablement after ROM image load
454 PlatformInitializeConsole (
455 XenDetected () ? gXenPlatformConsole
: gPlatformConsole
458 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
459 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
460 ASSERT_RETURN_ERROR (PcdStatus
);
462 // Reflect the PCD in the standard Timeout variable.
464 Status
= gRT
->SetVariable (
465 EFI_TIME_OUT_VARIABLE_NAME
,
466 &gEfiGlobalVariableGuid
,
467 (EFI_VARIABLE_NON_VOLATILE
|
468 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
469 EFI_VARIABLE_RUNTIME_ACCESS
),
470 sizeof FrontPageTimeout
,
474 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
475 "%a: SetVariable(%s, %u): %r\n",
477 EFI_TIME_OUT_VARIABLE_NAME
,
482 PlatformRegisterOptionsAndKeys ();
485 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
486 // instances on Virtio PCI RNG devices.
488 VisitAllInstancesOfProtocol (
489 &gEfiPciIoProtocolGuid
,
498 IN EFI_HANDLE RootBridgeHandle
,
506 // Make the PCI bus driver connect the root bridge, non-recursively. This
507 // will produce a number of child handles with PciIo on them.
509 Status
= gBS
->ConnectController (
510 RootBridgeHandle
, // ControllerHandle
511 NULL
, // DriverImageHandle
512 NULL
, // RemainingDevicePath -- produce all
522 ConnectVirtioPciRng (
523 IN EFI_HANDLE Handle
,
528 EFI_PCI_IO_PROTOCOL
*PciIo
;
539 // Read and check VendorId.
541 Status
= PciIo
->Pci
.Read (
544 PCI_VENDOR_ID_OFFSET
,
548 if (EFI_ERROR (Status
)) {
552 if (VendorId
!= VIRTIO_VENDOR_ID
) {
557 // Read DeviceId and RevisionId.
559 Status
= PciIo
->Pci
.Read (
562 PCI_DEVICE_ID_OFFSET
,
566 if (EFI_ERROR (Status
)) {
570 Status
= PciIo
->Pci
.Read (
573 PCI_REVISION_ID_OFFSET
,
577 if (EFI_ERROR (Status
)) {
582 // From DeviceId and RevisionId, determine whether the device is a
583 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
584 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
585 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
586 // only be sanity-checked, and SubsystemId will decide.
588 if ((DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) &&
589 (RevisionId
>= 0x01))
592 } else if ((DeviceId
>= 0x1000) && (DeviceId
<= 0x103F) && (RevisionId
== 0x00)) {
599 // Read and check SubsystemId as dictated by Virtio10.
601 Status
= PciIo
->Pci
.Read (
604 PCI_SUBSYSTEM_ID_OFFSET
,
608 if (EFI_ERROR (Status
)) {
612 if ((Virtio10
&& (SubsystemId
>= 0x40)) ||
613 (!Virtio10
&& (SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)))
615 Status
= gBS
->ConnectController (
616 Handle
, // ControllerHandle
617 NULL
, // DriverImageHandle -- connect all drivers
618 NULL
, // RemainingDevicePath -- produce all child handles
619 FALSE
// Recursive -- don't follow child handles
621 if (EFI_ERROR (Status
)) {
629 DEBUG ((DEBUG_ERROR
, "%a: %r\n", __FUNCTION__
, Status
));
634 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
636 @param[in] DeviceHandle Handle of the LPC Bridge device.
638 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
639 ConOut, ConIn, and ErrOut.
641 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
645 PrepareLpcBridgeDevicePath (
646 IN EFI_HANDLE DeviceHandle
650 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
651 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
655 Status
= gBS
->HandleProtocol (
657 &gEfiDevicePathProtocolGuid
,
660 if (EFI_ERROR (Status
)) {
664 TempDevicePath
= DevicePath
;
669 DevicePath
= AppendDevicePathNode (
671 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
674 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
679 DevicePath
= TempDevicePath
;
680 gPnp16550ComPortDeviceNode
.UID
= 0;
682 DevicePath
= AppendDevicePathNode (
684 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
686 DevicePath
= AppendDevicePathNode (
688 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
690 DevicePath
= AppendDevicePathNode (
692 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
698 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
699 if (DevPathStr
!= NULL
) {
702 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
704 gPnp16550ComPortDeviceNode
.UID
+ 1,
707 FreePool (DevPathStr
);
710 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
711 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
712 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
717 DevicePath
= TempDevicePath
;
718 gPnp16550ComPortDeviceNode
.UID
= 1;
720 DevicePath
= AppendDevicePathNode (
722 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
724 DevicePath
= AppendDevicePathNode (
726 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
728 DevicePath
= AppendDevicePathNode (
730 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
736 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
737 if (DevPathStr
!= NULL
) {
740 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
742 gPnp16550ComPortDeviceNode
.UID
+ 1,
745 FreePool (DevPathStr
);
748 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
749 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
750 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
756 VENDOR_DEVICE_PATH Guid
;
757 EFI_DEVICE_PATH_PROTOCOL End
;
758 } SERIAL_DEVICE_PATH
;
760 SERIAL_DEVICE_PATH serialDevicePath
= {
762 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, { sizeof (VENDOR_DEVICE_PATH
), 0 }
764 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
766 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 }
771 PrepareMicrovmDevicePath (
775 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
776 UINT16 HostBridgeDevId
;
778 HostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
779 if (HostBridgeDevId
!= MICROVM_PSEUDO_DEVICE_ID
) {
783 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)&serialDevicePath
;
784 DevicePath
= AppendDevicePathNode (
786 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
788 DevicePath
= AppendDevicePathNode (
790 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
793 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
794 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
795 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
800 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
801 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
806 EFI_HANDLE PciDeviceHandle
;
807 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
808 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
809 UINTN GopHandleCount
;
810 EFI_HANDLE
*GopHandleBuffer
;
812 if ((PciDevicePath
== NULL
) || (GopDevicePath
== NULL
)) {
813 return EFI_INVALID_PARAMETER
;
817 // Initialize the GopDevicePath to be PciDevicePath
819 *GopDevicePath
= PciDevicePath
;
820 TempPciDevicePath
= PciDevicePath
;
822 Status
= gBS
->LocateDevicePath (
823 &gEfiDevicePathProtocolGuid
,
827 if (EFI_ERROR (Status
)) {
832 // Try to connect this handle, so that GOP driver could start on this
833 // device and create child handles with GraphicsOutput Protocol installed
834 // on them, then we get device paths of these child handles and select
835 // them as possible console device.
837 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
839 Status
= gBS
->LocateHandleBuffer (
841 &gEfiGraphicsOutputProtocolGuid
,
846 if (!EFI_ERROR (Status
)) {
848 // Add all the child handles as possible Console Device
850 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
851 Status
= gBS
->HandleProtocol (
852 GopHandleBuffer
[Index
],
853 &gEfiDevicePathProtocolGuid
,
854 (VOID
*)&TempDevicePath
856 if (EFI_ERROR (Status
)) {
863 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
867 // In current implementation, we only enable one of the child handles
868 // as console device, i.e. sotre one of the child handle's device
869 // path to variable "ConOut"
870 // In future, we could select all child handles to be console device
873 *GopDevicePath
= TempDevicePath
;
876 // Delete the PCI device's path that added by
877 // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
879 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
880 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
884 gBS
->FreePool (GopHandleBuffer
);
891 Add PCI display to ConOut.
893 @param[in] DeviceHandle Handle of the PCI display device.
895 @retval EFI_SUCCESS The PCI display device has been added to ConOut.
897 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
901 PreparePciDisplayDevicePath (
902 IN EFI_HANDLE DeviceHandle
906 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
907 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
910 GopDevicePath
= NULL
;
911 Status
= gBS
->HandleProtocol (
913 &gEfiDevicePathProtocolGuid
,
916 if (EFI_ERROR (Status
)) {
920 GetGopDevicePath (DevicePath
, &GopDevicePath
);
921 DevicePath
= GopDevicePath
;
923 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
929 Add PCI Serial to ConOut, ConIn, ErrOut.
931 @param[in] DeviceHandle Handle of the PCI serial device.
933 @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
936 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
940 PreparePciSerialDevicePath (
941 IN EFI_HANDLE DeviceHandle
945 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
948 Status
= gBS
->HandleProtocol (
950 &gEfiDevicePathProtocolGuid
,
953 if (EFI_ERROR (Status
)) {
957 DevicePath
= AppendDevicePathNode (
959 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
961 DevicePath
= AppendDevicePathNode (
963 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
966 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
967 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
968 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
974 VisitAllInstancesOfProtocol (
976 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
982 EFI_HANDLE
*HandleBuffer
;
987 // Start to check all the PciIo to find all possible device
991 Status
= gBS
->LocateHandleBuffer (
998 if (EFI_ERROR (Status
)) {
1002 for (Index
= 0; Index
< HandleCount
; Index
++) {
1003 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
1004 if (EFI_ERROR (Status
)) {
1008 Status
= (*CallBackFunction
)(
1009 HandleBuffer
[Index
],
1015 gBS
->FreePool (HandleBuffer
);
1022 VisitingAPciInstance (
1023 IN EFI_HANDLE Handle
,
1029 EFI_PCI_IO_PROTOCOL
*PciIo
;
1032 PciIo
= (EFI_PCI_IO_PROTOCOL
*)Instance
;
1035 // Check for all PCI device
1037 Status
= PciIo
->Pci
.Read (
1039 EfiPciIoWidthUint32
,
1041 sizeof (Pci
) / sizeof (UINT32
),
1044 if (EFI_ERROR (Status
)) {
1048 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
)Context
)(
1056 VisitAllPciInstances (
1057 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
1060 return VisitAllInstancesOfProtocol (
1061 &gEfiPciIoProtocolGuid
,
1062 VisitingAPciInstance
,
1063 (VOID
*)(UINTN
)CallBackFunction
1068 Do platform specific PCI Device check and add them to
1069 ConOut, ConIn, ErrOut.
1071 @param[in] Handle - Handle of PCI device instance
1072 @param[in] PciIo - PCI IO protocol instance
1073 @param[in] Pci - PCI Header register block
1075 @retval EFI_SUCCESS - PCI Device check and Console variable update
1077 @retval EFI_STATUS - PCI Device check or Console variable update fail.
1082 DetectAndPreparePlatformPciDevicePath (
1083 IN EFI_HANDLE Handle
,
1084 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1090 Status
= PciIo
->Attributes (
1092 EfiPciIoAttributeOperationEnable
,
1093 EFI_PCI_DEVICE_ENABLE
,
1096 ASSERT_EFI_ERROR (Status
);
1099 // Here we decide whether it is LPC Bridge
1101 if ((IS_PCI_LPC (Pci
)) ||
1102 ((IS_PCI_ISA_PDECODE (Pci
)) &&
1103 (Pci
->Hdr
.VendorId
== 0x8086) &&
1104 (Pci
->Hdr
.DeviceId
== 0x7000)
1109 // Add IsaKeyboard to ConIn,
1110 // add IsaSerial to ConOut, ConIn, ErrOut
1112 DEBUG ((DEBUG_INFO
, "Found LPC Bridge device\n"));
1113 PrepareLpcBridgeDevicePath (Handle
);
1118 // Here we decide which Serial device to enable in PCI bus
1120 if (IS_PCI_16550SERIAL (Pci
)) {
1122 // Add them to ConOut, ConIn, ErrOut.
1124 DEBUG ((DEBUG_INFO
, "Found PCI 16550 SERIAL device\n"));
1125 PreparePciSerialDevicePath (Handle
);
1130 // Here we decide which display device to enable in PCI bus
1132 if (IS_PCI_DISPLAY (Pci
)) {
1134 // Add them to ConOut.
1136 DEBUG ((DEBUG_INFO
, "Found PCI display device\n"));
1137 PreparePciDisplayDevicePath (Handle
);
1145 Connect the predefined platform default console device.
1147 Always try to find and enable PCI display devices.
1149 @param[in] PlatformConsole Predefined platform default console device array.
1152 PlatformInitializeConsole (
1153 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
1159 // Do platform specific PCI Device check and add them to ConOut, ConIn,
1162 VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
1164 PrepareMicrovmDevicePath ();
1167 // Have chance to connect the platform default console,
1168 // the platform default console is the minimum device group
1169 // the platform should support
1171 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
1173 // Update the console variable with the connect type
1175 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
1176 EfiBootManagerUpdateConsoleVariable (
1178 PlatformConsole
[Index
].DevicePath
,
1183 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
1184 EfiBootManagerUpdateConsoleVariable (
1186 PlatformConsole
[Index
].DevicePath
,
1191 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
1192 EfiBootManagerUpdateConsoleVariable (
1194 PlatformConsole
[Index
].DevicePath
,
1202 Configure PCI Interrupt Line register for applicable devices
1203 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
1205 @param[in] Handle - Handle of PCI device instance
1206 @param[in] PciIo - PCI IO protocol instance
1207 @param[in] PciHdr - PCI Header register block
1209 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
1215 IN EFI_HANDLE Handle
,
1216 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1217 IN PCI_TYPE00
*PciHdr
1220 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1221 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1226 UINT32 RootBusNumber
;
1228 Status
= EFI_SUCCESS
;
1230 if (PciHdr
->Device
.InterruptPin
!= 0) {
1231 DevPathNode
= DevicePathFromHandle (Handle
);
1232 ASSERT (DevPathNode
!= NULL
);
1233 DevPath
= DevPathNode
;
1236 if ((DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
) &&
1237 (DevicePathSubType (DevPathNode
) == ACPI_DP
) &&
1238 (((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID (0x0A03)))
1240 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1244 // Compute index into PciHostIrqs[] table by walking
1245 // the device path and adding up all device numbers
1247 Status
= EFI_NOT_FOUND
;
1249 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1250 while (!IsDevicePathEnd (DevPathNode
)) {
1251 if ((DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
) &&
1252 (DevicePathSubType (DevPathNode
) == HW_PCI_DP
))
1254 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1257 // Unlike SeaBIOS, which starts climbing from the leaf device
1258 // up toward the root, we traverse the device path starting at
1259 // the root moving toward the leaf node.
1260 // The slot number of the top-level parent bridge is needed for
1261 // Q35 cases with more than 24 slots on the root bus.
1263 if (Status
!= EFI_SUCCESS
) {
1264 Status
= EFI_SUCCESS
;
1265 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1269 DevPathNode
= NextDevicePathNode (DevPathNode
);
1272 if (EFI_ERROR (Status
)) {
1276 if ((RootBusNumber
== 0) && (RootSlot
== 0)) {
1279 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1286 // Final PciHostIrqs[] index calculation depends on the platform
1287 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1289 switch (mHostBridgeDevId
) {
1290 case INTEL_82441_DEVICE_ID
:
1293 case INTEL_Q35_MCH_DEVICE_ID
:
1295 // SeaBIOS contains the following comment:
1296 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1297 // with a different starting index - see q35-acpi-dsdt.dsl.
1299 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1301 if (RootSlot
> 24) {
1303 // in this case, subtract back out RootSlot from Idx
1304 // (SeaBIOS never adds it to begin with, but that would make our
1305 // device path traversal loop above too awkward)
1312 ASSERT (FALSE
); // should never get here
1315 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1316 IrqLine
= PciHostIrqs
[Idx
];
1318 DEBUG_CODE_BEGIN ();
1320 CHAR16
*DevPathString
;
1321 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1322 UINTN Segment
, Bus
, Device
, Function
;
1324 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1325 if (DevPathString
== NULL
) {
1326 DevPathString
= Fallback
;
1329 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1330 ASSERT_EFI_ERROR (Status
);
1334 "%a: [%02x:%02x.%x] %s -> 0x%02x\n",
1343 if (DevPathString
!= Fallback
) {
1344 FreePool (DevPathString
);
1350 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1352 Status
= PciIo
->Pci
.Write (
1355 PCI_INT_LINE_OFFSET
,
1365 PciAcpiInitialization (
1371 // Query Host Bridge DID to determine platform type
1373 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1374 switch (mHostBridgeDevId
) {
1375 case INTEL_82441_DEVICE_ID
:
1376 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1378 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1380 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), PciHostIrqs
[0]); // A
1381 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), PciHostIrqs
[1]); // B
1382 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), PciHostIrqs
[2]); // C
1383 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), PciHostIrqs
[3]); // D
1385 case INTEL_Q35_MCH_DEVICE_ID
:
1386 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1388 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1390 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), PciHostIrqs
[0]); // A
1391 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), PciHostIrqs
[1]); // B
1392 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), PciHostIrqs
[2]); // C
1393 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), PciHostIrqs
[3]); // D
1394 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), PciHostIrqs
[0]); // E
1395 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), PciHostIrqs
[1]); // F
1396 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), PciHostIrqs
[2]); // G
1397 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), PciHostIrqs
[3]); // H
1399 case MICROVM_PSEUDO_DEVICE_ID
:
1400 case CLOUDHV_DEVICE_ID
:
1403 if (XenDetected ()) {
1405 // There is no PCI bus in this case.
1412 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1421 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1423 VisitAllPciInstances (SetPciIntLine
);
1426 // Set ACPI SCI_EN bit in PMCNTRL
1428 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1433 ConnectRecursivelyIfPciMassStorage (
1434 IN EFI_HANDLE Handle
,
1435 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1436 IN PCI_TYPE00
*PciHeader
1440 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1444 // Recognize PCI Mass Storage, and Xen PCI devices
1446 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ||
1447 (XenDetected () && IS_CLASS2 (PciHeader
, 0xFF, 0x80)))
1450 Status
= gBS
->HandleProtocol (
1452 &gEfiDevicePathProtocolGuid
,
1455 if (EFI_ERROR (Status
)) {
1460 // Print Device Path
1462 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1463 if (DevPathStr
!= NULL
) {
1466 "Found %s device: %s\n",
1467 (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ?
1473 FreePool (DevPathStr
);
1476 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1477 if (EFI_ERROR (Status
)) {
1486 This notification function is invoked when the
1487 EMU Variable FVB has been changed.
1489 @param Event The event that occurred
1490 @param Context For EFI compatibility. Not used.
1495 EmuVariablesUpdatedCallback (
1500 DEBUG ((DEBUG_INFO
, "EmuVariablesUpdatedCallback\n"));
1501 UpdateNvVarsOnFileSystem ();
1506 VisitingFileSystemInstance (
1507 IN EFI_HANDLE Handle
,
1513 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1514 RETURN_STATUS PcdStatus
;
1516 if (ConnectedToFileSystem
) {
1517 return EFI_ALREADY_STARTED
;
1520 Status
= ConnectNvVarsToFileSystem (Handle
);
1521 if (EFI_ERROR (Status
)) {
1525 ConnectedToFileSystem
= TRUE
;
1527 EfiCreateProtocolNotifyEvent (
1528 &gEfiDevicePathProtocolGuid
,
1530 EmuVariablesUpdatedCallback
,
1532 &mEmuVariableEventReg
1534 PcdStatus
= PcdSet64S (
1535 PcdEmuVariableEvent
,
1536 (UINT64
)(UINTN
)mEmuVariableEvent
1538 ASSERT_RETURN_ERROR (PcdStatus
);
1544 PlatformBdsRestoreNvVarsFromHardDisk (
1547 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1548 VisitAllInstancesOfProtocol (
1549 &gEfiSimpleFileSystemProtocolGuid
,
1550 VisitingFileSystemInstance
,
1556 Connect with predefined platform connect sequence.
1558 The OEM/IBV can customize with their own connect sequence.
1561 PlatformBdsConnectSequence (
1566 RETURN_STATUS Status
;
1568 DEBUG ((DEBUG_INFO
, "PlatformBdsConnectSequence\n"));
1573 // Here we can get the customized platform connect sequence
1574 // Notes: we can connect with new variable which record the
1575 // last time boots connect device path sequence
1577 while (gPlatformConnectSequence
[Index
] != NULL
) {
1579 // Build the platform boot option
1581 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1585 Status
= ConnectDevicesFromQemu ();
1586 if (RETURN_ERROR (Status
)) {
1588 // Just use the simple policy to connect all devices
1590 DEBUG ((DEBUG_INFO
, "EfiBootManagerConnectAll\n"));
1591 EfiBootManagerConnectAll ();
1596 Save the S3 boot script.
1598 Note that DxeSmmReadyToLock must be signaled after this function returns;
1599 otherwise the script wouldn't be saved actually.
1608 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1609 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1611 Status
= gBS
->LocateProtocol (
1612 &gEfiS3SaveStateProtocolGuid
,
1614 (VOID
**)&BootScript
1616 ASSERT_EFI_ERROR (Status
);
1619 // Despite the opcode documentation in the PI spec, the protocol
1620 // implementation embeds a deep copy of the info in the boot script, rather
1621 // than storing just a pointer to runtime or NVS storage.
1623 Status
= BootScript
->Write (
1625 EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1626 (UINT32
)sizeof Info
,
1627 (EFI_PHYSICAL_ADDRESS
)(UINTN
)&Info
1629 ASSERT_EFI_ERROR (Status
);
1633 Do the platform specific action after the console is ready
1635 Possible things that can be done in PlatformBootManagerAfterConsole:
1637 > Console post action:
1638 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1639 > Signal console ready platform customized event
1640 > Run diagnostics like memory testing
1641 > Connect certain devices
1642 > Dispatch aditional option roms
1643 > Special boot: e.g.: USB boot, enter UI
1647 PlatformBootManagerAfterConsole (
1651 EFI_BOOT_MODE BootMode
;
1653 DEBUG ((DEBUG_INFO
, "PlatformBootManagerAfterConsole\n"));
1655 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1658 "PlatformBdsPolicyBehavior: not restoring NvVars "
1659 "from disk since flash variables appear to be supported.\n"
1663 // Try to restore variables from the hard disk early so
1664 // they can be used for the other BDS connect operations.
1666 PlatformBdsRestoreNvVarsFromHardDisk ();
1670 // Get current Boot Mode
1672 BootMode
= GetBootModeHob ();
1673 DEBUG ((DEBUG_INFO
, "Boot Mode:%x\n", BootMode
));
1676 // Go the different platform policy with different boot mode
1677 // Notes: this part code can be change with the table policy
1679 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1684 BootLogoEnableLogo ();
1687 // Set PCI Interrupt Line registers and ACPI SCI_EN
1689 PciAcpiInitialization ();
1692 // Process QEMU's -kernel command line option
1694 TryRunningQemuKernel ();
1697 // Perform some platform specific connect sequence
1699 PlatformBdsConnectSequence ();
1701 EfiBootManagerRefreshAllBootOption ();
1704 // Register UEFI Shell
1706 PlatformRegisterFvBootOption (
1707 &gUefiShellFileGuid
,
1708 L
"EFI Internal Shell",
1712 RemoveStaleFvFileOptions ();
1713 SetBootOrderFromQemu ();
1715 PlatformBmPrintScRegisterHandler ();
1719 This notification function is invoked when an instance of the
1720 EFI_DEVICE_PATH_PROTOCOL is produced.
1722 @param Event The event that occurred
1723 @param Context For EFI compatibility. Not used.
1736 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1737 ATAPI_DEVICE_PATH
*Atapi
;
1740 // Examine all new handles
1744 // Get the next handle
1746 BufferSize
= sizeof (Handle
);
1747 Status
= gBS
->LocateHandle (
1750 mEfiDevPathNotifyReg
,
1756 // If not found, we're done
1758 if (EFI_NOT_FOUND
== Status
) {
1762 if (EFI_ERROR (Status
)) {
1767 // Get the DevicePath protocol on that handle
1769 Status
= gBS
->HandleProtocol (
1771 &gEfiDevicePathProtocolGuid
,
1772 (VOID
**)&DevPathNode
1774 ASSERT_EFI_ERROR (Status
);
1776 while (!IsDevicePathEnd (DevPathNode
)) {
1778 // Find the handler to dump this device path node
1781 (DevicePathType (DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1782 (DevicePathSubType (DevPathNode
) == MSG_ATAPI_DP
)
1785 Atapi
= (ATAPI_DEVICE_PATH
*)DevPathNode
;
1791 (Atapi
->PrimarySecondary
== 1) ? 0x42 : 0x40
1798 // Next device path node
1800 DevPathNode
= NextDevicePathNode (DevPathNode
);
1808 InstallDevicePathCallback (
1812 DEBUG ((DEBUG_INFO
, "Registered NotifyDevPath Event\n"));
1813 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1814 &gEfiDevicePathProtocolGuid
,
1818 &mEfiDevPathNotifyReg
1823 This function is called each second during the boot manager waits the
1826 @param TimeoutRemain The remaining timeout.
1830 PlatformBootManagerWaitCallback (
1831 UINT16 TimeoutRemain
1834 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1835 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1836 UINT16 TimeoutInitial
;
1838 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
1841 // If PcdPlatformBootTimeOut is set to zero, then we consider
1842 // that no progress update should be enacted (since we'd only
1843 // ever display a one-shot progress of either 0% or 100%).
1845 if (TimeoutInitial
== 0) {
1849 Black
.Raw
= 0x00000000;
1850 White
.Raw
= 0x00FFFFFF;
1852 BootLogoUpdateProgress (
1855 L
"Start boot option",
1857 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
1863 The function is called when no boot option could be launched,
1864 including platform recovery options and options pointing to applications
1865 built into firmware volumes.
1867 If this function returns, BDS attempts to enter an infinite loop.
1871 PlatformBootManagerUnableToBoot (
1877 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
1881 // BootManagerMenu doesn't contain the correct information when return status
1882 // is EFI_NOT_FOUND.
1884 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1885 if (EFI_ERROR (Status
)) {
1890 // Normally BdsDxe does not print anything to the system console, but this is
1891 // a last resort -- the end-user will likely not see any DEBUG messages
1892 // logged in this situation.
1894 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
1895 // here to see if it makes sense to request and wait for a keypress.
1897 if (gST
->ConIn
!= NULL
) {
1899 "%a: No bootable option or device was found.\n"
1900 "%a: Press any key to enter the Boot Manager Menu.\n",
1904 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1905 ASSERT_EFI_ERROR (Status
);
1906 ASSERT (Index
== 0);
1909 // Drain any queued keys.
1911 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
1913 // just throw away Key
1919 EfiBootManagerBoot (&BootManagerMenu
);