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>
22 VOID
*mEfiDevPathNotifyReg
;
23 EFI_EVENT mEfiDevPathEvent
;
24 VOID
*mEmuVariableEventReg
;
25 EFI_EVENT mEmuVariableEvent
;
26 UINT16 mHostBridgeDevId
;
29 // Table of host IRQs matching PCI IRQs A-D
30 // (for configuring PCI Interrupt Line register)
32 CONST UINT8 PciHostIrqs
[] = {
45 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
52 @param[in] Handle - Handle of PCI device instance
53 @param[in] PciIo - PCI IO protocol instance
54 @param[in] Pci - PCI Header register block
58 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
60 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
66 // Function prototypes
70 VisitAllInstancesOfProtocol (
72 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
77 VisitAllPciInstancesOfProtocol (
78 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
82 InstallDevicePathCallback (
87 PlatformRegisterFvBootOption (
95 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
96 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
97 UINTN BootOptionCount
;
98 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
99 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
100 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
102 Status
= gBS
->HandleProtocol (
104 &gEfiLoadedImageProtocolGuid
,
105 (VOID
**) &LoadedImage
107 ASSERT_EFI_ERROR (Status
);
109 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
110 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
111 ASSERT (DevicePath
!= NULL
);
112 DevicePath
= AppendDevicePathNode (
114 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
116 ASSERT (DevicePath
!= NULL
);
118 Status
= EfiBootManagerInitializeLoadOption (
120 LoadOptionNumberUnassigned
,
128 ASSERT_EFI_ERROR (Status
);
129 FreePool (DevicePath
);
131 BootOptions
= EfiBootManagerGetLoadOptions (
132 &BootOptionCount
, LoadOptionTypeBoot
135 OptionIndex
= EfiBootManagerFindLoadOption (
136 &NewOption
, BootOptions
, BootOptionCount
139 if (OptionIndex
== -1) {
140 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
141 ASSERT_EFI_ERROR (Status
);
143 EfiBootManagerFreeLoadOption (&NewOption
);
144 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
148 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
149 whose device paths do not resolve exactly to an FvFile in the system.
151 This removes any boot options that point to binaries built into the firmware
152 and have become stale due to any of the following:
153 - DXEFV's base address or size changed (historical),
154 - DXEFV's FvNameGuid changed,
155 - the FILE_GUID of the pointed-to binary changed,
156 - the referenced binary is no longer built into the firmware.
158 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
159 avoids exact duplicates.
162 RemoveStaleFvFileOptions (
166 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
167 UINTN BootOptionCount
;
170 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
173 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
174 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
179 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
180 // then keep the boot option.
182 Node1
= BootOptions
[Index
].FilePath
;
183 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
184 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
185 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
186 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
191 // If the second device path node is not FvFile(...), then keep the boot
194 Node2
= NextDevicePathNode (Node1
);
195 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
196 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
201 // Locate the Firmware Volume2 protocol instance that is denoted by the
202 // boot option. If this lookup fails (i.e., the boot option references a
203 // firmware volume that doesn't exist), then we'll proceed to delete the
207 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
208 &SearchNode
, &FvHandle
);
210 if (!EFI_ERROR (Status
)) {
212 // The firmware volume was found; now let's see if it contains the FvFile
213 // identified by GUID.
215 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
216 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
218 EFI_FV_FILETYPE FoundType
;
219 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
220 UINT32 AuthenticationStatus
;
222 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
223 (VOID
**)&FvProtocol
);
224 ASSERT_EFI_ERROR (Status
);
226 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
228 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
231 Status
= FvProtocol
->ReadFile (
233 &FvFileNode
->FvFileName
, // NameGuid
238 &AuthenticationStatus
240 if (!EFI_ERROR (Status
)) {
242 // The FvFile was found. Keep the boot option.
249 // Delete the boot option.
251 Status
= EfiBootManagerDeleteLoadOptionVariable (
252 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
254 CHAR16
*DevicePathString
;
256 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
259 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
260 "%a: removing stale Boot#%04x %s: %r\n",
262 (UINT32
)BootOptions
[Index
].OptionNumber
,
263 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
266 if (DevicePathString
!= NULL
) {
267 FreePool (DevicePathString
);
272 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
276 PlatformRegisterOptionsAndKeys (
284 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
287 // Register ENTER as CONTINUE key
289 Enter
.ScanCode
= SCAN_NULL
;
290 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
291 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
292 ASSERT_EFI_ERROR (Status
);
295 // Map F2 to Boot Manager Menu
297 F2
.ScanCode
= SCAN_F2
;
298 F2
.UnicodeChar
= CHAR_NULL
;
299 Esc
.ScanCode
= SCAN_ESC
;
300 Esc
.UnicodeChar
= CHAR_NULL
;
301 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
302 ASSERT_EFI_ERROR (Status
);
303 Status
= EfiBootManagerAddKeyOptionVariable (
304 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
306 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
307 Status
= EfiBootManagerAddKeyOptionVariable (
308 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
310 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
316 IN EFI_HANDLE RootBridgeHandle
,
324 ConnectVirtioPciRng (
325 IN EFI_HANDLE Handle
,
337 // BDS Platform Functions
340 Do the platform init, can be customized by OEM/IBV
342 Possible things that can be done in PlatformBootManagerBeforeConsole:
344 > Update console variable: 1. include hot-plug devices;
345 > 2. Clear ConIn and add SOL for AMT
346 > Register new Driver#### or Boot####
347 > Register new Key####: e.g.: F12
348 > Signal ReadyToLock event
349 > Authentication action: 1. connect Auth devices;
350 > 2. Identify auto logon user.
354 PlatformBootManagerBeforeConsole (
360 UINT16 FrontPageTimeout
;
361 RETURN_STATUS PcdStatus
;
363 DEBUG ((DEBUG_INFO
, "PlatformBootManagerBeforeConsole\n"));
364 InstallDevicePathCallback ();
366 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
367 ConnectRootBridge
, NULL
);
370 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
372 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
375 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
376 // the preparation of S3 system information. That logic has a hard dependency
377 // on the presence of the FACS ACPI table. Since our ACPI tables are only
378 // installed after PCI enumeration completes, we must not trigger the S3 save
379 // earlier, hence we can't signal End-of-Dxe earlier.
381 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
383 if (PcdGetBool (PcdAcpiS3Enable
)) {
385 // Save the boot script too. Note that this will require us to emit the
386 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
391 // We need to connect all trusted consoles for TCG PP. Here we treat all
392 // consoles in OVMF to be trusted consoles.
393 PlatformInitializeConsole (
394 XenDetected() ? gXenPlatformConsole
: gPlatformConsole
);
397 // Process TPM PPI request; this may require keyboard input
399 Tcg2PhysicalPresenceLibProcessRequest (NULL
);
402 // Prevent further changes to LockBoxes or SMRAM.
403 // Any TPM 2 Physical Presence Interface opcode must be handled before.
406 Status
= gBS
->InstallProtocolInterface (&Handle
,
407 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
409 ASSERT_EFI_ERROR (Status
);
412 // Dispatch deferred images after EndOfDxe event and ReadyToLock
415 EfiBootManagerDispatchDeferredImages ();
417 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
418 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
419 ASSERT_RETURN_ERROR (PcdStatus
);
421 // Reflect the PCD in the standard Timeout variable.
423 Status
= gRT
->SetVariable (
424 EFI_TIME_OUT_VARIABLE_NAME
,
425 &gEfiGlobalVariableGuid
,
426 (EFI_VARIABLE_NON_VOLATILE
|
427 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
428 EFI_VARIABLE_RUNTIME_ACCESS
),
429 sizeof FrontPageTimeout
,
433 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
434 "%a: SetVariable(%s, %u): %r\n",
436 EFI_TIME_OUT_VARIABLE_NAME
,
441 PlatformRegisterOptionsAndKeys ();
444 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
445 // instances on Virtio PCI RNG devices.
447 VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid
, ConnectVirtioPciRng
,
455 IN EFI_HANDLE RootBridgeHandle
,
463 // Make the PCI bus driver connect the root bridge, non-recursively. This
464 // will produce a number of child handles with PciIo on them.
466 Status
= gBS
->ConnectController (
467 RootBridgeHandle
, // ControllerHandle
468 NULL
, // DriverImageHandle
469 NULL
, // RemainingDevicePath -- produce all
480 ConnectVirtioPciRng (
481 IN EFI_HANDLE Handle
,
486 EFI_PCI_IO_PROTOCOL
*PciIo
;
497 // Read and check VendorId.
499 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
501 if (EFI_ERROR (Status
)) {
504 if (VendorId
!= VIRTIO_VENDOR_ID
) {
509 // Read DeviceId and RevisionId.
511 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
513 if (EFI_ERROR (Status
)) {
516 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
518 if (EFI_ERROR (Status
)) {
523 // From DeviceId and RevisionId, determine whether the device is a
524 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
525 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
526 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
527 // only be sanity-checked, and SubsystemId will decide.
529 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
530 RevisionId
>= 0x01) {
532 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
539 // Read and check SubsystemId as dictated by Virtio10.
541 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
542 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
543 if (EFI_ERROR (Status
)) {
546 if ((Virtio10
&& SubsystemId
>= 0x40) ||
547 (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)) {
548 Status
= gBS
->ConnectController (
549 Handle
, // ControllerHandle
550 NULL
, // DriverImageHandle -- connect all drivers
551 NULL
, // RemainingDevicePath -- produce all child handles
552 FALSE
// Recursive -- don't follow child handles
554 if (EFI_ERROR (Status
)) {
561 DEBUG ((DEBUG_ERROR
, "%a: %r\n", __FUNCTION__
, Status
));
567 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
569 @param[in] DeviceHandle Handle of the LPC Bridge device.
571 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
572 ConOut, ConIn, and ErrOut.
574 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
578 PrepareLpcBridgeDevicePath (
579 IN EFI_HANDLE DeviceHandle
583 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
584 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
588 Status
= gBS
->HandleProtocol (
590 &gEfiDevicePathProtocolGuid
,
593 if (EFI_ERROR (Status
)) {
596 TempDevicePath
= DevicePath
;
601 DevicePath
= AppendDevicePathNode (DevicePath
,
602 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
604 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
609 DevicePath
= TempDevicePath
;
610 gPnp16550ComPortDeviceNode
.UID
= 0;
612 DevicePath
= AppendDevicePathNode (DevicePath
,
613 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
614 DevicePath
= AppendDevicePathNode (DevicePath
,
615 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
616 DevicePath
= AppendDevicePathNode (DevicePath
,
617 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
622 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
623 if (DevPathStr
!= NULL
) {
626 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
628 gPnp16550ComPortDeviceNode
.UID
+ 1,
631 FreePool(DevPathStr
);
634 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
635 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
636 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
641 DevicePath
= TempDevicePath
;
642 gPnp16550ComPortDeviceNode
.UID
= 1;
644 DevicePath
= AppendDevicePathNode (DevicePath
,
645 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
646 DevicePath
= AppendDevicePathNode (DevicePath
,
647 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
648 DevicePath
= AppendDevicePathNode (DevicePath
,
649 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
654 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
655 if (DevPathStr
!= NULL
) {
658 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
660 gPnp16550ComPortDeviceNode
.UID
+ 1,
663 FreePool(DevPathStr
);
666 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
667 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
668 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
674 VENDOR_DEVICE_PATH Guid
;
675 EFI_DEVICE_PATH_PROTOCOL End
;
676 } SERIAL_DEVICE_PATH
;
678 SERIAL_DEVICE_PATH serialDevicePath
= {
680 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, { sizeof (VENDOR_DEVICE_PATH
), 0} },
681 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
683 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 } }
687 PrepareMicrovmDevicePath (
691 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
692 UINT16 HostBridgeDevId
;
694 HostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
695 if (HostBridgeDevId
!= MICROVM_PSEUDO_DEVICE_ID
) {
699 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)&serialDevicePath
;
700 DevicePath
= AppendDevicePathNode (DevicePath
,
701 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
702 DevicePath
= AppendDevicePathNode (DevicePath
,
703 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
705 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
706 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
707 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
712 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
713 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
718 EFI_HANDLE PciDeviceHandle
;
719 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
720 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
721 UINTN GopHandleCount
;
722 EFI_HANDLE
*GopHandleBuffer
;
724 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
725 return EFI_INVALID_PARAMETER
;
729 // Initialize the GopDevicePath to be PciDevicePath
731 *GopDevicePath
= PciDevicePath
;
732 TempPciDevicePath
= PciDevicePath
;
734 Status
= gBS
->LocateDevicePath (
735 &gEfiDevicePathProtocolGuid
,
739 if (EFI_ERROR (Status
)) {
744 // Try to connect this handle, so that GOP driver could start on this
745 // device and create child handles with GraphicsOutput Protocol installed
746 // on them, then we get device paths of these child handles and select
747 // them as possible console device.
749 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
751 Status
= gBS
->LocateHandleBuffer (
753 &gEfiGraphicsOutputProtocolGuid
,
758 if (!EFI_ERROR (Status
)) {
760 // Add all the child handles as possible Console Device
762 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
763 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
],
764 &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
765 if (EFI_ERROR (Status
)) {
771 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
774 // In current implementation, we only enable one of the child handles
775 // as console device, i.e. sotre one of the child handle's device
776 // path to variable "ConOut"
777 // In future, we could select all child handles to be console device
780 *GopDevicePath
= TempDevicePath
;
783 // Delete the PCI device's path that added by
784 // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
786 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
787 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
790 gBS
->FreePool (GopHandleBuffer
);
797 Add PCI display to ConOut.
799 @param[in] DeviceHandle Handle of the PCI display device.
801 @retval EFI_SUCCESS The PCI display device has been added to ConOut.
803 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
807 PreparePciDisplayDevicePath (
808 IN EFI_HANDLE DeviceHandle
812 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
813 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
816 GopDevicePath
= NULL
;
817 Status
= gBS
->HandleProtocol (
819 &gEfiDevicePathProtocolGuid
,
822 if (EFI_ERROR (Status
)) {
826 GetGopDevicePath (DevicePath
, &GopDevicePath
);
827 DevicePath
= GopDevicePath
;
829 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
835 Add PCI Serial to ConOut, ConIn, ErrOut.
837 @param[in] DeviceHandle Handle of the PCI serial device.
839 @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
842 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
846 PreparePciSerialDevicePath (
847 IN EFI_HANDLE DeviceHandle
851 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
854 Status
= gBS
->HandleProtocol (
856 &gEfiDevicePathProtocolGuid
,
859 if (EFI_ERROR (Status
)) {
863 DevicePath
= AppendDevicePathNode (DevicePath
,
864 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
865 DevicePath
= AppendDevicePathNode (DevicePath
,
866 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
868 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
869 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
870 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
876 VisitAllInstancesOfProtocol (
878 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
884 EFI_HANDLE
*HandleBuffer
;
889 // Start to check all the PciIo to find all possible device
893 Status
= gBS
->LocateHandleBuffer (
900 if (EFI_ERROR (Status
)) {
904 for (Index
= 0; Index
< HandleCount
; Index
++) {
905 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
906 if (EFI_ERROR (Status
)) {
910 Status
= (*CallBackFunction
) (
917 gBS
->FreePool (HandleBuffer
);
925 VisitingAPciInstance (
926 IN EFI_HANDLE Handle
,
932 EFI_PCI_IO_PROTOCOL
*PciIo
;
935 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
938 // Check for all PCI device
940 Status
= PciIo
->Pci
.Read (
944 sizeof (Pci
) / sizeof (UINT32
),
947 if (EFI_ERROR (Status
)) {
951 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
962 VisitAllPciInstances (
963 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
966 return VisitAllInstancesOfProtocol (
967 &gEfiPciIoProtocolGuid
,
968 VisitingAPciInstance
,
969 (VOID
*)(UINTN
) CallBackFunction
975 Do platform specific PCI Device check and add them to
976 ConOut, ConIn, ErrOut.
978 @param[in] Handle - Handle of PCI device instance
979 @param[in] PciIo - PCI IO protocol instance
980 @param[in] Pci - PCI Header register block
982 @retval EFI_SUCCESS - PCI Device check and Console variable update
984 @retval EFI_STATUS - PCI Device check or Console variable update fail.
989 DetectAndPreparePlatformPciDevicePath (
990 IN EFI_HANDLE Handle
,
991 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
997 Status
= PciIo
->Attributes (
999 EfiPciIoAttributeOperationEnable
,
1000 EFI_PCI_DEVICE_ENABLE
,
1003 ASSERT_EFI_ERROR (Status
);
1006 // Here we decide whether it is LPC Bridge
1008 if ((IS_PCI_LPC (Pci
)) ||
1009 ((IS_PCI_ISA_PDECODE (Pci
)) &&
1010 (Pci
->Hdr
.VendorId
== 0x8086) &&
1011 (Pci
->Hdr
.DeviceId
== 0x7000)
1015 // Add IsaKeyboard to ConIn,
1016 // add IsaSerial to ConOut, ConIn, ErrOut
1018 DEBUG ((DEBUG_INFO
, "Found LPC Bridge device\n"));
1019 PrepareLpcBridgeDevicePath (Handle
);
1023 // Here we decide which Serial device to enable in PCI bus
1025 if (IS_PCI_16550SERIAL (Pci
)) {
1027 // Add them to ConOut, ConIn, ErrOut.
1029 DEBUG ((DEBUG_INFO
, "Found PCI 16550 SERIAL device\n"));
1030 PreparePciSerialDevicePath (Handle
);
1035 // Here we decide which display device to enable in PCI bus
1037 if (IS_PCI_DISPLAY (Pci
)) {
1039 // Add them to ConOut.
1041 DEBUG ((DEBUG_INFO
, "Found PCI display device\n"));
1042 PreparePciDisplayDevicePath (Handle
);
1051 Connect the predefined platform default console device.
1053 Always try to find and enable PCI display devices.
1055 @param[in] PlatformConsole Predefined platform default console device array.
1058 PlatformInitializeConsole (
1059 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
1065 // Do platform specific PCI Device check and add them to ConOut, ConIn,
1068 VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
1070 PrepareMicrovmDevicePath ();
1073 // Have chance to connect the platform default console,
1074 // the platform default console is the minimum device group
1075 // the platform should support
1077 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
1079 // Update the console variable with the connect type
1081 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
1082 EfiBootManagerUpdateConsoleVariable (ConIn
,
1083 PlatformConsole
[Index
].DevicePath
, NULL
);
1085 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
1086 EfiBootManagerUpdateConsoleVariable (ConOut
,
1087 PlatformConsole
[Index
].DevicePath
, NULL
);
1089 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
1090 EfiBootManagerUpdateConsoleVariable (ErrOut
,
1091 PlatformConsole
[Index
].DevicePath
, NULL
);
1098 Configure PCI Interrupt Line register for applicable devices
1099 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
1101 @param[in] Handle - Handle of PCI device instance
1102 @param[in] PciIo - PCI IO protocol instance
1103 @param[in] PciHdr - PCI Header register block
1105 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
1111 IN EFI_HANDLE Handle
,
1112 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1113 IN PCI_TYPE00
*PciHdr
1116 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1117 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1122 UINT32 RootBusNumber
;
1124 Status
= EFI_SUCCESS
;
1126 if (PciHdr
->Device
.InterruptPin
!= 0) {
1128 DevPathNode
= DevicePathFromHandle (Handle
);
1129 ASSERT (DevPathNode
!= NULL
);
1130 DevPath
= DevPathNode
;
1133 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
1134 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
1135 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
1136 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1140 // Compute index into PciHostIrqs[] table by walking
1141 // the device path and adding up all device numbers
1143 Status
= EFI_NOT_FOUND
;
1145 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1146 while (!IsDevicePathEnd (DevPathNode
)) {
1147 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
1148 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
1150 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1153 // Unlike SeaBIOS, which starts climbing from the leaf device
1154 // up toward the root, we traverse the device path starting at
1155 // the root moving toward the leaf node.
1156 // The slot number of the top-level parent bridge is needed for
1157 // Q35 cases with more than 24 slots on the root bus.
1159 if (Status
!= EFI_SUCCESS
) {
1160 Status
= EFI_SUCCESS
;
1161 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1165 DevPathNode
= NextDevicePathNode (DevPathNode
);
1167 if (EFI_ERROR (Status
)) {
1170 if (RootBusNumber
== 0 && RootSlot
== 0) {
1173 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1180 // Final PciHostIrqs[] index calculation depends on the platform
1181 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1183 switch (mHostBridgeDevId
) {
1184 case INTEL_82441_DEVICE_ID
:
1187 case INTEL_Q35_MCH_DEVICE_ID
:
1189 // SeaBIOS contains the following comment:
1190 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1191 // with a different starting index - see q35-acpi-dsdt.dsl.
1193 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1195 if (RootSlot
> 24) {
1197 // in this case, subtract back out RootSlot from Idx
1198 // (SeaBIOS never adds it to begin with, but that would make our
1199 // device path traversal loop above too awkward)
1205 ASSERT (FALSE
); // should never get here
1207 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1208 IrqLine
= PciHostIrqs
[Idx
];
1210 DEBUG_CODE_BEGIN ();
1212 CHAR16
*DevPathString
;
1213 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1214 UINTN Segment
, Bus
, Device
, Function
;
1216 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1217 if (DevPathString
== NULL
) {
1218 DevPathString
= Fallback
;
1220 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1221 ASSERT_EFI_ERROR (Status
);
1223 DEBUG ((DEBUG_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
1224 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
1227 if (DevPathString
!= Fallback
) {
1228 FreePool (DevPathString
);
1234 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1236 Status
= PciIo
->Pci
.Write (
1239 PCI_INT_LINE_OFFSET
,
1250 PciAcpiInitialization (
1256 // Query Host Bridge DID to determine platform type
1258 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1259 switch (mHostBridgeDevId
) {
1260 case INTEL_82441_DEVICE_ID
:
1261 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1263 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1265 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), PciHostIrqs
[0]); // A
1266 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), PciHostIrqs
[1]); // B
1267 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), PciHostIrqs
[2]); // C
1268 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), PciHostIrqs
[3]); // D
1270 case INTEL_Q35_MCH_DEVICE_ID
:
1271 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1273 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1275 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), PciHostIrqs
[0]); // A
1276 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), PciHostIrqs
[1]); // B
1277 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), PciHostIrqs
[2]); // C
1278 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), PciHostIrqs
[3]); // D
1279 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), PciHostIrqs
[0]); // E
1280 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), PciHostIrqs
[1]); // F
1281 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), PciHostIrqs
[2]); // G
1282 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), PciHostIrqs
[3]); // H
1284 case MICROVM_PSEUDO_DEVICE_ID
:
1287 if (XenDetected ()) {
1289 // There is no PCI bus in this case.
1293 DEBUG ((DEBUG_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1294 __FUNCTION__
, mHostBridgeDevId
));
1300 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1302 VisitAllPciInstances (SetPciIntLine
);
1305 // Set ACPI SCI_EN bit in PMCNTRL
1307 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1312 ConnectRecursivelyIfPciMassStorage (
1313 IN EFI_HANDLE Handle
,
1314 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1315 IN PCI_TYPE00
*PciHeader
1319 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1323 // Recognize PCI Mass Storage, and Xen PCI devices
1325 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ||
1326 (XenDetected() && IS_CLASS2 (PciHeader
, 0xFF, 0x80))) {
1328 Status
= gBS
->HandleProtocol (
1330 &gEfiDevicePathProtocolGuid
,
1333 if (EFI_ERROR (Status
)) {
1338 // Print Device Path
1340 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1341 if (DevPathStr
!= NULL
) {
1344 "Found %s device: %s\n",
1345 (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ?
1351 FreePool(DevPathStr
);
1354 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1355 if (EFI_ERROR (Status
)) {
1366 This notification function is invoked when the
1367 EMU Variable FVB has been changed.
1369 @param Event The event that occurred
1370 @param Context For EFI compatibility. Not used.
1375 EmuVariablesUpdatedCallback (
1380 DEBUG ((DEBUG_INFO
, "EmuVariablesUpdatedCallback\n"));
1381 UpdateNvVarsOnFileSystem ();
1387 VisitingFileSystemInstance (
1388 IN EFI_HANDLE Handle
,
1394 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1395 RETURN_STATUS PcdStatus
;
1397 if (ConnectedToFileSystem
) {
1398 return EFI_ALREADY_STARTED
;
1401 Status
= ConnectNvVarsToFileSystem (Handle
);
1402 if (EFI_ERROR (Status
)) {
1406 ConnectedToFileSystem
= TRUE
;
1408 EfiCreateProtocolNotifyEvent (
1409 &gEfiDevicePathProtocolGuid
,
1411 EmuVariablesUpdatedCallback
,
1413 &mEmuVariableEventReg
1415 PcdStatus
= PcdSet64S (PcdEmuVariableEvent
,
1416 (UINT64
)(UINTN
) mEmuVariableEvent
);
1417 ASSERT_RETURN_ERROR (PcdStatus
);
1424 PlatformBdsRestoreNvVarsFromHardDisk (
1427 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1428 VisitAllInstancesOfProtocol (
1429 &gEfiSimpleFileSystemProtocolGuid
,
1430 VisitingFileSystemInstance
,
1437 Connect with predefined platform connect sequence.
1439 The OEM/IBV can customize with their own connect sequence.
1442 PlatformBdsConnectSequence (
1447 RETURN_STATUS Status
;
1449 DEBUG ((DEBUG_INFO
, "PlatformBdsConnectSequence\n"));
1454 // Here we can get the customized platform connect sequence
1455 // Notes: we can connect with new variable which record the
1456 // last time boots connect device path sequence
1458 while (gPlatformConnectSequence
[Index
] != NULL
) {
1460 // Build the platform boot option
1462 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1466 Status
= ConnectDevicesFromQemu ();
1467 if (RETURN_ERROR (Status
)) {
1469 // Just use the simple policy to connect all devices
1471 DEBUG ((DEBUG_INFO
, "EfiBootManagerConnectAll\n"));
1472 EfiBootManagerConnectAll ();
1477 Save the S3 boot script.
1479 Note that DxeSmmReadyToLock must be signaled after this function returns;
1480 otherwise the script wouldn't be saved actually.
1489 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1490 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1492 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1493 (VOID
**) &BootScript
);
1494 ASSERT_EFI_ERROR (Status
);
1497 // Despite the opcode documentation in the PI spec, the protocol
1498 // implementation embeds a deep copy of the info in the boot script, rather
1499 // than storing just a pointer to runtime or NVS storage.
1501 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1502 (UINT32
) sizeof Info
,
1503 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1504 ASSERT_EFI_ERROR (Status
);
1509 Do the platform specific action after the console is ready
1511 Possible things that can be done in PlatformBootManagerAfterConsole:
1513 > Console post action:
1514 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1515 > Signal console ready platform customized event
1516 > Run diagnostics like memory testing
1517 > Connect certain devices
1518 > Dispatch aditional option roms
1519 > Special boot: e.g.: USB boot, enter UI
1523 PlatformBootManagerAfterConsole (
1527 EFI_BOOT_MODE BootMode
;
1529 DEBUG ((DEBUG_INFO
, "PlatformBootManagerAfterConsole\n"));
1531 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1532 DEBUG ((DEBUG_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1533 "from disk since flash variables appear to be supported.\n"));
1536 // Try to restore variables from the hard disk early so
1537 // they can be used for the other BDS connect operations.
1539 PlatformBdsRestoreNvVarsFromHardDisk ();
1543 // Get current Boot Mode
1545 BootMode
= GetBootModeHob ();
1546 DEBUG ((DEBUG_INFO
, "Boot Mode:%x\n", BootMode
));
1549 // Go the different platform policy with different boot mode
1550 // Notes: this part code can be change with the table policy
1552 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1557 BootLogoEnableLogo ();
1560 // Set PCI Interrupt Line registers and ACPI SCI_EN
1562 PciAcpiInitialization ();
1565 // Process QEMU's -kernel command line option
1567 TryRunningQemuKernel ();
1570 // Perform some platform specific connect sequence
1572 PlatformBdsConnectSequence ();
1574 EfiBootManagerRefreshAllBootOption ();
1577 // Register UEFI Shell
1579 PlatformRegisterFvBootOption (
1580 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
1583 RemoveStaleFvFileOptions ();
1584 SetBootOrderFromQemu ();
1586 PlatformBmPrintScRegisterHandler ();
1590 This notification function is invoked when an instance of the
1591 EFI_DEVICE_PATH_PROTOCOL is produced.
1593 @param Event The event that occurred
1594 @param Context For EFI compatibility. Not used.
1607 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1608 ATAPI_DEVICE_PATH
*Atapi
;
1611 // Examine all new handles
1615 // Get the next handle
1617 BufferSize
= sizeof (Handle
);
1618 Status
= gBS
->LocateHandle (
1621 mEfiDevPathNotifyReg
,
1627 // If not found, we're done
1629 if (EFI_NOT_FOUND
== Status
) {
1633 if (EFI_ERROR (Status
)) {
1638 // Get the DevicePath protocol on that handle
1640 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
,
1641 (VOID
**)&DevPathNode
);
1642 ASSERT_EFI_ERROR (Status
);
1644 while (!IsDevicePathEnd (DevPathNode
)) {
1646 // Find the handler to dump this device path node
1649 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1650 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1652 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1658 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1665 // Next device path node
1667 DevPathNode
= NextDevicePathNode (DevPathNode
);
1676 InstallDevicePathCallback (
1680 DEBUG ((DEBUG_INFO
, "Registered NotifyDevPath Event\n"));
1681 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1682 &gEfiDevicePathProtocolGuid
,
1686 &mEfiDevPathNotifyReg
1691 This function is called each second during the boot manager waits the
1694 @param TimeoutRemain The remaining timeout.
1698 PlatformBootManagerWaitCallback (
1699 UINT16 TimeoutRemain
1702 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1703 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1704 UINT16 TimeoutInitial
;
1706 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
1709 // If PcdPlatformBootTimeOut is set to zero, then we consider
1710 // that no progress update should be enacted (since we'd only
1711 // ever display a one-shot progress of either 0% or 100%).
1713 if (TimeoutInitial
== 0) {
1717 Black
.Raw
= 0x00000000;
1718 White
.Raw
= 0x00FFFFFF;
1720 BootLogoUpdateProgress (
1723 L
"Start boot option",
1725 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
1731 The function is called when no boot option could be launched,
1732 including platform recovery options and options pointing to applications
1733 built into firmware volumes.
1735 If this function returns, BDS attempts to enter an infinite loop.
1739 PlatformBootManagerUnableToBoot (
1745 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
1749 // BootManagerMenu doesn't contain the correct information when return status
1750 // is EFI_NOT_FOUND.
1752 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1753 if (EFI_ERROR (Status
)) {
1757 // Normally BdsDxe does not print anything to the system console, but this is
1758 // a last resort -- the end-user will likely not see any DEBUG messages
1759 // logged in this situation.
1761 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
1762 // here to see if it makes sense to request and wait for a keypress.
1764 if (gST
->ConIn
!= NULL
) {
1766 "%a: No bootable option or device was found.\n"
1767 "%a: Press any key to enter the Boot Manager Menu.\n",
1771 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
1772 ASSERT_EFI_ERROR (Status
);
1773 ASSERT (Index
== 0);
1776 // Drain any queued keys.
1778 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
1780 // just throw away Key
1786 EfiBootManagerBoot (&BootManagerMenu
);