X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FLibrary%2FPlatformBootManagerLib%2FBdsPlatform.c;h=98f6f07341ec27e54a7607d63f07bab742dd4d4d;hb=HEAD;hp=16618a8f57f08636ba62ce5f68cbb8d0d8219092;hpb=103b12cec526e4fa6f709840fefc1d554387a170;p=mirror_edk2.git
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
index 16618a8f57..98f6f07341 100644
--- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -1,49 +1,40 @@
/** @file
Platform BDS customizations.
- Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "BdsPlatform.h"
-#include
#include
+#include
#include
-
+#include
+#include
+#include
//
// Global data
//
-VOID *mEfiDevPathNotifyReg;
-EFI_EVENT mEfiDevPathEvent;
-VOID *mEmuVariableEventReg;
-EFI_EVENT mEmuVariableEvent;
-BOOLEAN mDetectVgaOnly;
-UINT16 mHostBridgeDevId;
+VOID *mEfiDevPathNotifyReg;
+EFI_EVENT mEfiDevPathEvent;
+VOID *mEmuVariableEventReg;
+EFI_EVENT mEmuVariableEvent;
+UINT16 mHostBridgeDevId;
//
// Table of host IRQs matching PCI IRQs A-D
// (for configuring PCI Interrupt Line register)
//
-CONST UINT8 PciHostIrqs[] = {
- 0x0a, 0x0a, 0x0b, 0x0b
+CONST UINT8 PciHostIrqs[] = {
+ 0x0a, // LNKA, LNKE
+ 0x0a, // LNKB, LNKF
+ 0x0b, // LNKC, LNKG
+ 0x0b // LNKD, LNKH
};
-//
-// Array Size macro
-//
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
-#endif
-
//
// Type definitions
//
@@ -69,7 +60,6 @@ EFI_STATUS
IN PCI_TYPE00 *Pci
);
-
//
// Function prototypes
//
@@ -83,7 +73,7 @@ VisitAllInstancesOfProtocol (
EFI_STATUS
VisitAllPciInstancesOfProtocol (
- IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
);
VOID
@@ -93,24 +83,24 @@ InstallDevicePathCallback (
VOID
PlatformRegisterFvBootOption (
- EFI_GUID *FileGuid,
- CHAR16 *Description,
- UINT32 Attributes
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ UINT32 Attributes
)
{
- EFI_STATUS Status;
- INTN OptionIndex;
- EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
- UINTN BootOptionCount;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+ INTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
Status = gBS->HandleProtocol (
gImageHandle,
&gEfiLoadedImageProtocolGuid,
- (VOID **) &LoadedImage
+ (VOID **)&LoadedImage
);
ASSERT_EFI_ERROR (Status);
@@ -119,7 +109,7 @@ PlatformRegisterFvBootOption (
ASSERT (DevicePath != NULL);
DevicePath = AppendDevicePathNode (
DevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
);
ASSERT (DevicePath != NULL);
@@ -137,17 +127,21 @@ PlatformRegisterFvBootOption (
FreePool (DevicePath);
BootOptions = EfiBootManagerGetLoadOptions (
- &BootOptionCount, LoadOptionTypeBoot
+ &BootOptionCount,
+ LoadOptionTypeBoot
);
OptionIndex = EfiBootManagerFindLoadOption (
- &NewOption, BootOptions, BootOptionCount
+ &NewOption,
+ BootOptions,
+ BootOptionCount
);
if (OptionIndex == -1) {
Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
ASSERT_EFI_ERROR (Status);
}
+
EfiBootManagerFreeLoadOption (&NewOption);
EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
}
@@ -171,27 +165,30 @@ RemoveStaleFvFileOptions (
VOID
)
{
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
- UINTN BootOptionCount;
- UINTN Index;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
- BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
- LoadOptionTypeBoot);
+ BootOptions = EfiBootManagerGetLoadOptions (
+ &BootOptionCount,
+ LoadOptionTypeBoot
+ );
for (Index = 0; Index < BootOptionCount; ++Index) {
- EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
- EFI_STATUS Status;
- EFI_HANDLE FvHandle;
+ EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+ EFI_STATUS Status;
+ EFI_HANDLE FvHandle;
//
// If the device path starts with neither MemoryMapped(...) nor Fv(...),
// then keep the boot option.
//
Node1 = BootOptions[Index].FilePath;
- if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
- DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
- !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
- DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+ if (!((DevicePathType (Node1) == HARDWARE_DEVICE_PATH) &&
+ (DevicePathSubType (Node1) == HW_MEMMAP_DP)) &&
+ !((DevicePathType (Node1) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)))
+ {
continue;
}
@@ -200,8 +197,9 @@ RemoveStaleFvFileOptions (
// option.
//
Node2 = NextDevicePathNode (Node1);
- if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
- DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+ if ((DevicePathType (Node2) != MEDIA_DEVICE_PATH) ||
+ (DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP))
+ {
continue;
}
@@ -212,23 +210,29 @@ RemoveStaleFvFileOptions (
// boot option.
//
SearchNode = Node1;
- Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
- &SearchNode, &FvHandle);
+ Status = gBS->LocateDevicePath (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ &SearchNode,
+ &FvHandle
+ );
if (!EFI_ERROR (Status)) {
//
// The firmware volume was found; now let's see if it contains the FvFile
// identified by GUID.
//
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
- UINTN BufferSize;
- EFI_FV_FILETYPE FoundType;
- EFI_FV_FILE_ATTRIBUTES FileAttributes;
- UINT32 AuthenticationStatus;
-
- Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
- (VOID **)&FvProtocol);
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+ UINTN BufferSize;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINT32 AuthenticationStatus;
+
+ Status = gBS->HandleProtocol (
+ FvHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **)&FvProtocol
+ );
ASSERT_EFI_ERROR (Status);
FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
@@ -257,24 +261,30 @@ RemoveStaleFvFileOptions (
// Delete the boot option.
//
Status = EfiBootManagerDeleteLoadOptionVariable (
- BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
- DEBUG_CODE (
- CHAR16 *DevicePathString;
+ BootOptions[Index].OptionNumber,
+ LoadOptionTypeBoot
+ );
+ DEBUG_CODE_BEGIN ();
+ CHAR16 *DevicePathString;
+
+ DevicePathString = ConvertDevicePathToText (
+ BootOptions[Index].FilePath,
+ FALSE,
+ FALSE
+ );
+ DEBUG ((
+ EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
+ "%a: removing stale Boot#%04x %s: %r\n",
+ __FUNCTION__,
+ (UINT32)BootOptions[Index].OptionNumber,
+ DevicePathString == NULL ? L"" : DevicePathString,
+ Status
+ ));
+ if (DevicePathString != NULL) {
+ FreePool (DevicePathString);
+ }
- DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
- FALSE, FALSE);
- DEBUG ((
- EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE,
- "%a: removing stale Boot#%04x %s: %r\n",
- __FUNCTION__,
- (UINT32)BootOptions[Index].OptionNumber,
- DevicePathString == NULL ? L"" : DevicePathString,
- Status
- ));
- if (DevicePathString != NULL) {
- FreePool (DevicePathString);
- }
- );
+ DEBUG_CODE_END ();
}
EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
@@ -285,18 +295,18 @@ PlatformRegisterOptionsAndKeys (
VOID
)
{
- EFI_STATUS Status;
- EFI_INPUT_KEY Enter;
- EFI_INPUT_KEY F2;
- EFI_INPUT_KEY Esc;
- EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Enter;
+ EFI_INPUT_KEY F2;
+ EFI_INPUT_KEY Esc;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
//
// Register ENTER as CONTINUE key
//
Enter.ScanCode = SCAN_NULL;
Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
- Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+ Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
ASSERT_EFI_ERROR (Status);
//
@@ -306,14 +316,22 @@ PlatformRegisterOptionsAndKeys (
F2.UnicodeChar = CHAR_NULL;
Esc.ScanCode = SCAN_ESC;
Esc.UnicodeChar = CHAR_NULL;
- Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
ASSERT_EFI_ERROR (Status);
Status = EfiBootManagerAddKeyOptionVariable (
- NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
+ NULL,
+ (UINT16)BootOption.OptionNumber,
+ 0,
+ &F2,
+ NULL
);
ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
Status = EfiBootManagerAddKeyOptionVariable (
- NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
+ NULL,
+ (UINT16)BootOption.OptionNumber,
+ 0,
+ &Esc,
+ NULL
);
ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
}
@@ -326,6 +344,15 @@ ConnectRootBridge (
IN VOID *Context
);
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
STATIC
VOID
SaveS3BootScript (
@@ -335,35 +362,39 @@ SaveS3BootScript (
//
// BDS Platform Functions
//
+
+/**
+ Do the platform init, can be customized by OEM/IBV
+
+ Possible things that can be done in PlatformBootManagerBeforeConsole:
+
+ > Update console variable: 1. include hot-plug devices;
+ > 2. Clear ConIn and add SOL for AMT
+ > Register new Driver#### or Boot####
+ > Register new Key####: e.g.: F12
+ > Signal ReadyToLock event
+ > Authentication action: 1. connect Auth devices;
+ > 2. Identify auto logon user.
+**/
VOID
EFIAPI
PlatformBootManagerBeforeConsole (
VOID
)
-/*++
-
-Routine Description:
-
- Platform Bds init. Include the platform firmware vendor, revision
- and so crc check.
-
-Arguments:
-
-Returns:
-
- None.
-
---*/
{
- EFI_HANDLE Handle;
- EFI_STATUS Status;
- RETURN_STATUS PcdStatus;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINT16 FrontPageTimeout;
+ RETURN_STATUS PcdStatus;
- DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));
InstallDevicePathCallback ();
- VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
- ConnectRootBridge, NULL);
+ VisitAllInstancesOfProtocol (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ ConnectRootBridge,
+ NULL
+ );
//
// Signal the ACPI platform driver that it can download QEMU ACPI tables.
@@ -379,7 +410,7 @@ Returns:
//
EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
- if (QemuFwCfgS3Enabled ()) {
+ if (PcdGetBool (PcdAcpiS3Enable)) {
//
// Save the boot script too. Note that this will require us to emit the
// DxeSmmReadyToLock event just below, which in turn locks down SMM.
@@ -387,23 +418,85 @@ Returns:
SaveS3BootScript ();
}
+ //
+ // We need to connect all trusted consoles for TCG PP. Here we treat all
+ // consoles in OVMF to be trusted consoles.
+ //
+ // Cloud Hypervisor doesn't emulate any LPC bridge, which is why it must
+ // rely on the serial I/O port to be connected as a console. It reuses the
+ // definition from Xen as it is very generic.
+ //
+ PlatformInitializeConsole (
+ (XenDetected () || PcdGet16 (PcdOvmfHostBridgePciDevId) == CLOUDHV_DEVICE_ID) ? gXenPlatformConsole : gPlatformConsole
+ );
+
+ //
+ // Process TPM PPI request; this may require keyboard input
+ //
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);
+
//
// Prevent further changes to LockBoxes or SMRAM.
+ // Any TPM 2 Physical Presence Interface opcode must be handled before.
//
Handle = NULL;
- Status = gBS->InstallProtocolInterface (&Handle,
- &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
- NULL);
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
ASSERT_EFI_ERROR (Status);
- PlatformInitializeConsole (gPlatformConsole);
- PcdStatus = PcdSet16S (PcdPlatformBootTimeOut,
- GetFrontPageTimeoutFromQemu ());
+ //
+ // Dispatch deferred images after EndOfDxe event and ReadyToLock
+ // installation.
+ //
+ EfiBootManagerDispatchDeferredImages ();
+
+ //
+ // GPU passthrough only allows Console enablement after ROM image load
+ //
+ PlatformInitializeConsole (
+ XenDetected () ? gXenPlatformConsole : gPlatformConsole
+ );
+
+ FrontPageTimeout = GetFrontPageTimeoutFromQemu ();
+ PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);
ASSERT_RETURN_ERROR (PcdStatus);
+ //
+ // Reflect the PCD in the standard Timeout variable.
+ //
+ Status = gRT->SetVariable (
+ EFI_TIME_OUT_VARIABLE_NAME,
+ &gEfiGlobalVariableGuid,
+ (EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS),
+ sizeof FrontPageTimeout,
+ &FrontPageTimeout
+ );
+ DEBUG ((
+ EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
+ "%a: SetVariable(%s, %u): %r\n",
+ __FUNCTION__,
+ EFI_TIME_OUT_VARIABLE_NAME,
+ FrontPageTimeout,
+ Status
+ ));
PlatformRegisterOptionsAndKeys ();
-}
+ //
+ // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
+ // instances on Virtio PCI RNG devices.
+ //
+ VisitAllInstancesOfProtocol (
+ &gEfiPciIoProtocolGuid,
+ ConnectVirtioPciRng,
+ NULL
+ );
+}
EFI_STATUS
EFIAPI
@@ -413,7 +506,7 @@ ConnectRootBridge (
IN VOID *Context
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
//
// Make the PCI bus driver connect the root bridge, non-recursively. This
@@ -429,29 +522,135 @@ ConnectRootBridge (
return Status;
}
-
+STATIC
EFI_STATUS
-PrepareLpcBridgeDevicePath (
- IN EFI_HANDLE DeviceHandle
+EFIAPI
+ConnectVirtioPciRng (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
)
-/*++
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT8 RevisionId;
+ BOOLEAN Virtio10;
+ UINT16 SubsystemId;
-Routine Description:
+ PciIo = Instance;
- Add IsaKeyboard to ConIn,
- add IsaSerial to ConOut, ConIn, ErrOut.
- LPC Bridge: 06 01 00
+ //
+ // Read and check VendorId.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VendorId
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
-Arguments:
+ if (VendorId != VIRTIO_VENDOR_ID) {
+ return EFI_SUCCESS;
+ }
- DeviceHandle - Handle of PCIIO protocol.
+ //
+ // Read DeviceId and RevisionId.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_DEVICE_ID_OFFSET,
+ 1,
+ &DeviceId
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
-Returns:
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_REVISION_ID_OFFSET,
+ 1,
+ &RevisionId
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
- EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
- EFI_STATUS - No LPC bridge is added.
+ //
+ // From DeviceId and RevisionId, determine whether the device is a
+ // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
+ // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
+ // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
+ // only be sanity-checked, and SubsystemId will decide.
+ //
+ if ((DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) &&
+ (RevisionId >= 0x01))
+ {
+ Virtio10 = TRUE;
+ } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {
+ Virtio10 = FALSE;
+ } else {
+ return EFI_SUCCESS;
+ }
---*/
+ //
+ // Read and check SubsystemId as dictated by Virtio10.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_SUBSYSTEM_ID_OFFSET,
+ 1,
+ &SubsystemId
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ if ((Virtio10 && (SubsystemId >= 0x40)) ||
+ (!Virtio10 && (SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)))
+ {
+ Status = gBS->ConnectController (
+ Handle, // ControllerHandle
+ NULL, // DriverImageHandle -- connect all drivers
+ NULL, // RemainingDevicePath -- produce all child handles
+ FALSE // Recursive -- don't follow child handles
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));
+ return Status;
+}
+
+/**
+ Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the LPC Bridge device.
+
+ @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
+ ConOut, ConIn, and ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
@@ -459,46 +658,59 @@ Returns:
CHAR16 *DevPathStr;
DevicePath = NULL;
- Status = gBS->HandleProtocol (
- DeviceHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID*)&DevicePath
- );
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *)&DevicePath
+ );
if (EFI_ERROR (Status)) {
return Status;
}
+
TempDevicePath = DevicePath;
//
// Register Keyboard
//
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode
+ );
EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
//
// Register COM1
//
- DevicePath = TempDevicePath;
+ DevicePath = TempDevicePath;
gPnp16550ComPortDeviceNode.UID = 0;
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode
+ );
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
+ );
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
+ );
//
// Print Device Path
//
DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
if (DevPathStr != NULL) {
- DEBUG((
- EFI_D_INFO,
+ DEBUG ((
+ DEBUG_INFO,
"BdsPlatform.c+%d: COM%d DevPath: %s\n",
- __LINE__,
+ DEBUG_LINE_NUMBER,
gPnp16550ComPortDeviceNode.UID + 1,
DevPathStr
));
- FreePool(DevPathStr);
+ FreePool (DevPathStr);
}
EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
@@ -508,26 +720,35 @@ Returns:
//
// Register COM2
//
- DevicePath = TempDevicePath;
+ DevicePath = TempDevicePath;
gPnp16550ComPortDeviceNode.UID = 1;
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode
+ );
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
+ );
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
+ );
//
// Print Device Path
//
DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
if (DevPathStr != NULL) {
- DEBUG((
- EFI_D_INFO,
+ DEBUG ((
+ DEBUG_INFO,
"BdsPlatform.c+%d: COM%d DevPath: %s\n",
- __LINE__,
+ DEBUG_LINE_NUMBER,
gPnp16550ComPortDeviceNode.UID + 1,
DevPathStr
));
- FreePool(DevPathStr);
+ FreePool (DevPathStr);
}
EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
@@ -537,21 +758,64 @@ Returns:
return EFI_SUCCESS;
}
+typedef struct {
+ VENDOR_DEVICE_PATH Guid;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SERIAL_DEVICE_PATH;
+
+SERIAL_DEVICE_PATH serialDevicePath = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 }
+ },
+ EDKII_SERIAL_PORT_LIB_VENDOR_GUID
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+};
+
+VOID
+PrepareMicrovmDevicePath (
+ VOID
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT16 HostBridgeDevId;
+
+ HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+ if (HostBridgeDevId != MICROVM_PSEUDO_DEVICE_ID) {
+ return;
+ }
+
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&serialDevicePath;
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
+ );
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
+ );
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+}
+
EFI_STATUS
GetGopDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
- OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
- )
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+ )
{
- UINTN Index;
- EFI_STATUS Status;
- EFI_HANDLE PciDeviceHandle;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
- UINTN GopHandleCount;
- EFI_HANDLE *GopHandleBuffer;
-
- if (PciDevicePath == NULL || GopDevicePath == NULL) {
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE PciDeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
+ UINTN GopHandleCount;
+ EFI_HANDLE *GopHandleBuffer;
+
+ if ((PciDevicePath == NULL) || (GopDevicePath == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -590,15 +854,21 @@ GetGopDevicePath (
// Add all the child handles as possible Console Device
//
for (Index = 0; Index < GopHandleCount; Index++) {
- Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
+ Status = gBS->HandleProtocol (
+ GopHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID *)&TempDevicePath
+ );
if (EFI_ERROR (Status)) {
continue;
}
+
if (CompareMem (
PciDevicePath,
TempDevicePath,
GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
- ) == 0) {
+ ) == 0)
+ {
//
// In current implementation, we only enable one of the child handles
// as console device, i.e. sotre one of the child handle's device
@@ -609,40 +879,34 @@ GetGopDevicePath (
*GopDevicePath = TempDevicePath;
//
- // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
- // Add the integrity GOP device path.
+ // Delete the PCI device's path that added by
+ // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
//
EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
}
}
+
gBS->FreePool (GopHandleBuffer);
}
return EFI_SUCCESS;
}
-EFI_STATUS
-PreparePciDisplayDevicePath (
- IN EFI_HANDLE DeviceHandle
- )
-/*++
-
-Routine Description:
-
- Add PCI VGA to ConOut.
- PCI VGA: 03 00 00
-
-Arguments:
-
- DeviceHandle - Handle of PCIIO protocol.
+/**
+ Add PCI display to ConOut.
-Returns:
+ @param[in] DeviceHandle Handle of the PCI display device.
- EFI_SUCCESS - PCI VGA is added to ConOut.
- EFI_STATUS - No PCI VGA device is added.
+ @retval EFI_SUCCESS The PCI display device has been added to ConOut.
---*/
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciDisplayDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
@@ -650,11 +914,11 @@ Returns:
DevicePath = NULL;
GopDevicePath = NULL;
- Status = gBS->HandleProtocol (
- DeviceHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID*)&DevicePath
- );
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *)&DevicePath
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -667,43 +931,43 @@ Returns:
return EFI_SUCCESS;
}
-EFI_STATUS
-PreparePciSerialDevicePath (
- IN EFI_HANDLE DeviceHandle
- )
-/*++
-
-Routine Description:
-
+/**
Add PCI Serial to ConOut, ConIn, ErrOut.
- PCI Serial: 07 00 02
-Arguments:
+ @param[in] DeviceHandle Handle of the PCI serial device.
- DeviceHandle - Handle of PCIIO protocol.
+ @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
+ ErrOut.
-Returns:
-
- EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
- EFI_STATUS - No PCI Serial device is added.
-
---*/
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
DevicePath = NULL;
- Status = gBS->HandleProtocol (
- DeviceHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID*)&DevicePath
- );
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *)&DevicePath
+ );
if (EFI_ERROR (Status)) {
return Status;
}
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode
+ );
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode
+ );
EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
@@ -719,24 +983,24 @@ VisitAllInstancesOfProtocol (
IN VOID *Context
)
{
- EFI_STATUS Status;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
- VOID *Instance;
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ VOID *Instance;
//
// Start to check all the PciIo to find all possible device
//
- HandleCount = 0;
+ HandleCount = 0;
HandleBuffer = NULL;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- Id,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Id,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -747,11 +1011,11 @@ VisitAllInstancesOfProtocol (
continue;
}
- Status = (*CallBackFunction) (
- HandleBuffer[Index],
- Instance,
- Context
- );
+ Status = (*CallBackFunction)(
+ HandleBuffer[Index],
+ Instance,
+ Context
+ );
}
gBS->FreePool (HandleBuffer);
@@ -759,7 +1023,6 @@ VisitAllInstancesOfProtocol (
return EFI_SUCCESS;
}
-
EFI_STATUS
EFIAPI
VisitingAPciInstance (
@@ -768,49 +1031,45 @@ VisitingAPciInstance (
IN VOID *Context
)
{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
- PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+ PciIo = (EFI_PCI_IO_PROTOCOL *)Instance;
//
// Check for all PCI device
//
Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- 0,
- sizeof (Pci) / sizeof (UINT32),
- &Pci
- );
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
if (EFI_ERROR (Status)) {
return Status;
}
- return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
- Handle,
- PciIo,
- &Pci
- );
-
+ return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN)Context)(
+ Handle,
+ PciIo,
+ &Pci
+ );
}
-
-
EFI_STATUS
VisitAllPciInstances (
- IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
)
{
return VisitAllInstancesOfProtocol (
&gEfiPciIoProtocolGuid,
VisitingAPciInstance,
- (VOID*)(UINTN) CallBackFunction
+ (VOID *)(UINTN)CallBackFunction
);
}
-
/**
Do platform specific PCI Device check and add them to
ConOut, ConIn, ErrOut.
@@ -819,7 +1078,8 @@ VisitAllPciInstances (
@param[in] PciIo - PCI IO protocol instance
@param[in] Pci - PCI Header register block
- @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+ @retval EFI_SUCCESS - PCI Device check and Console variable update
+ successfully.
@retval EFI_STATUS - PCI Device check or Console variable update fail.
**/
@@ -831,45 +1091,45 @@ DetectAndPreparePlatformPciDevicePath (
IN PCI_TYPE00 *Pci
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
Status = PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationEnable,
- EFI_PCI_DEVICE_ENABLE,
- NULL
- );
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
ASSERT_EFI_ERROR (Status);
- if (!mDetectVgaOnly) {
+ //
+ // Here we decide whether it is LPC Bridge
+ //
+ if ((IS_PCI_LPC (Pci)) ||
+ ((IS_PCI_ISA_PDECODE (Pci)) &&
+ (Pci->Hdr.VendorId == 0x8086) &&
+ (Pci->Hdr.DeviceId == 0x7000)
+ )
+ )
+ {
//
- // Here we decide whether it is LPC Bridge
+ // Add IsaKeyboard to ConIn,
+ // add IsaSerial to ConOut, ConIn, ErrOut
//
- if ((IS_PCI_LPC (Pci)) ||
- ((IS_PCI_ISA_PDECODE (Pci)) &&
- (Pci->Hdr.VendorId == 0x8086) &&
- (Pci->Hdr.DeviceId == 0x7000)
- )
- ) {
- //
- // Add IsaKeyboard to ConIn,
- // add IsaSerial to ConOut, ConIn, ErrOut
- //
- DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
- PrepareLpcBridgeDevicePath (Handle);
- return EFI_SUCCESS;
- }
+ DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
+ PrepareLpcBridgeDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Here we decide which Serial device to enable in PCI bus
+ //
+ if (IS_PCI_16550SERIAL (Pci)) {
//
- // Here we decide which Serial device to enable in PCI bus
+ // Add them to ConOut, ConIn, ErrOut.
//
- if (IS_PCI_16550SERIAL (Pci)) {
- //
- // Add them to ConOut, ConIn, ErrOut.
- //
- DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
- PreparePciSerialDevicePath (Handle);
- return EFI_SUCCESS;
- }
+ DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
+ PreparePciSerialDevicePath (Handle);
+ return EFI_SUCCESS;
}
//
@@ -879,7 +1139,7 @@ DetectAndPreparePlatformPciDevicePath (
//
// Add them to ConOut.
//
- DEBUG ((EFI_D_INFO, "Found PCI display device\n"));
+ DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
PreparePciDisplayDevicePath (Handle);
return EFI_SUCCESS;
}
@@ -887,86 +1147,63 @@ DetectAndPreparePlatformPciDevicePath (
return Status;
}
-
/**
- Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
-
- @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
+ Connect the predefined platform default console device.
- @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
- @retval EFI_STATUS - PCI Device check or Console variable update fail.
+ Always try to find and enable PCI display devices.
+ @param[in] PlatformConsole Predefined platform default console device array.
**/
-EFI_STATUS
-DetectAndPreparePlatformPciDevicePaths (
- BOOLEAN DetectVgaOnly
- )
-{
- mDetectVgaOnly = DetectVgaOnly;
- return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
-}
-
-
VOID
PlatformInitializeConsole (
- IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
)
-/*++
-
-Routine Description:
-
- Connect the predefined platform default console device. Always try to find
- and enable the vga device if have.
-
-Arguments:
-
- PlatformConsole - Predefined platform default console device array.
---*/
{
- UINTN Index;
- EFI_DEVICE_PATH_PROTOCOL *VarConout;
- EFI_DEVICE_PATH_PROTOCOL *VarConin;
+ UINTN Index;
//
- // Connect RootBridge
+ // Do platform specific PCI Device check and add them to ConOut, ConIn,
+ // ErrOut
//
- GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
- GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
+ VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
- if (VarConout == NULL || VarConin == NULL) {
- //
- // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
- //
- DetectAndPreparePlatformPciDevicePaths (FALSE);
+ PrepareMicrovmDevicePath ();
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimum device group
+ // the platform should support
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
//
- // Have chance to connect the platform default console,
- // the platform default console is the minimum device group
- // the platform should support
+ // Update the console variable with the connect type
//
- for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
- //
- // Update the console variable with the connect type
- //
- if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
- EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
- }
- if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
- EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
- }
- if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
- EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
- }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ EfiBootManagerUpdateConsoleVariable (
+ ConIn,
+ PlatformConsole[Index].DevicePath,
+ NULL
+ );
+ }
+
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ EfiBootManagerUpdateConsoleVariable (
+ ConOut,
+ PlatformConsole[Index].DevicePath,
+ NULL
+ );
+ }
+
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ EfiBootManagerUpdateConsoleVariable (
+ ErrOut,
+ PlatformConsole[Index].DevicePath,
+ NULL
+ );
}
- } else {
- //
- // Only detect VGA device and add them to ConOut
- //
- DetectAndPreparePlatformPciDevicePaths (TRUE);
}
}
-
/**
Configure PCI Interrupt Line register for applicable devices
Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
@@ -997,15 +1234,15 @@ SetPciIntLine (
Status = EFI_SUCCESS;
if (PciHdr->Device.InterruptPin != 0) {
-
DevPathNode = DevicePathFromHandle (Handle);
ASSERT (DevPathNode != NULL);
DevPath = DevPathNode;
RootBusNumber = 0;
- if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
- DevicePathSubType (DevPathNode) == ACPI_DP &&
- ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+ if ((DevicePathType (DevPathNode) == ACPI_DEVICE_PATH) &&
+ (DevicePathSubType (DevPathNode) == ACPI_DP) &&
+ (((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID (0x0A03)))
+ {
RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
}
@@ -1013,13 +1250,13 @@ SetPciIntLine (
// Compute index into PciHostIrqs[] table by walking
// the device path and adding up all device numbers
//
- Status = EFI_NOT_FOUND;
+ Status = EFI_NOT_FOUND;
RootSlot = 0;
- Idx = PciHdr->Device.InterruptPin - 1;
+ Idx = PciHdr->Device.InterruptPin - 1;
while (!IsDevicePathEnd (DevPathNode)) {
- if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
- DevicePathSubType (DevPathNode) == HW_PCI_DP) {
-
+ if ((DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH) &&
+ (DevicePathSubType (DevPathNode) == HW_PCI_DP))
+ {
Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
//
@@ -1030,19 +1267,21 @@ SetPciIntLine (
// Q35 cases with more than 24 slots on the root bus.
//
if (Status != EFI_SUCCESS) {
- Status = EFI_SUCCESS;
+ Status = EFI_SUCCESS;
RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
}
}
DevPathNode = NextDevicePathNode (DevPathNode);
}
+
if (EFI_ERROR (Status)) {
return Status;
}
- if (RootBusNumber == 0 && RootSlot == 0) {
- DEBUG((
- EFI_D_ERROR,
+
+ if ((RootBusNumber == 0) && (RootSlot == 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
"%a: PCI host bridge (00:00.0) should have no interrupts!\n",
__FUNCTION__
));
@@ -1073,29 +1312,39 @@ SetPciIntLine (
//
Idx -= RootSlot;
}
+
break;
default:
ASSERT (FALSE); // should never get here
}
- Idx %= ARRAY_SIZE (PciHostIrqs);
+
+ Idx %= ARRAY_SIZE (PciHostIrqs);
IrqLine = PciHostIrqs[Idx];
DEBUG_CODE_BEGIN ();
{
- CHAR16 *DevPathString;
- STATIC CHAR16 Fallback[] = L"";
- UINTN Segment, Bus, Device, Function;
+ CHAR16 *DevPathString;
+ STATIC CHAR16 Fallback[] = L"";
+ UINTN Segment, Bus, Device, Function;
DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
if (DevPathString == NULL) {
DevPathString = Fallback;
}
+
Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
ASSERT_EFI_ERROR (Status);
- DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
- (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
- IrqLine));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: [%02x:%02x.%x] %s -> 0x%02x\n",
+ __FUNCTION__,
+ (UINT32)Bus,
+ (UINT32)Device,
+ (UINT32)Function,
+ DevPathString,
+ IrqLine
+ ));
if (DevPathString != Fallback) {
FreePool (DevPathString);
@@ -1107,18 +1356,17 @@ SetPciIntLine (
// Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
//
Status = PciIo->Pci.Write (
- PciIo,
- EfiPciIoWidthUint8,
- PCI_INT_LINE_OFFSET,
- 1,
- &IrqLine
- );
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_INT_LINE_OFFSET,
+ 1,
+ &IrqLine
+ );
}
return Status;
}
-
VOID
PciAcpiInitialization (
)
@@ -1135,28 +1383,42 @@ PciAcpiInitialization (
//
// 00:01.0 ISA Bridge (PIIX4) LNK routing targets
//
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), PciHostIrqs[0]); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), PciHostIrqs[1]); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), PciHostIrqs[2]); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), PciHostIrqs[3]); // D
break;
case INTEL_Q35_MCH_DEVICE_ID:
Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
//
// 00:1f.0 LPC Bridge (Q35) LNK routing targets
//
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), PciHostIrqs[0]); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), PciHostIrqs[1]); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), PciHostIrqs[2]); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), PciHostIrqs[3]); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), PciHostIrqs[0]); // E
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), PciHostIrqs[1]); // F
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), PciHostIrqs[2]); // G
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), PciHostIrqs[3]); // H
break;
+ case MICROVM_PSEUDO_DEVICE_ID:
+ case CLOUDHV_DEVICE_ID:
+ return;
default:
- DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
- __FUNCTION__, mHostBridgeDevId));
+ if (XenDetected ()) {
+ //
+ // There is no PCI bus in this case.
+ //
+ return;
+ }
+
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__,
+ mHostBridgeDevId
+ ));
ASSERT (FALSE);
return;
}
@@ -1172,38 +1434,6 @@ PciAcpiInitialization (
IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
}
-/**
- This function detects if OVMF is running on Xen.
-
-**/
-STATIC
-BOOLEAN
-XenDetected (
- VOID
- )
-{
- EFI_HOB_GUID_TYPE *GuidHob;
- STATIC INTN FoundHob = -1;
-
- if (FoundHob == 0) {
- return FALSE;
- } else if (FoundHob == 1) {
- return TRUE;
- }
-
- //
- // See if a XenInfo HOB is available
- //
- GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
- if (GuidHob == NULL) {
- FoundHob = 0;
- return FALSE;
- }
-
- FoundHob = 1;
- return TRUE;
-}
-
EFI_STATUS
EFIAPI
ConnectRecursivelyIfPciMassStorage (
@@ -1220,13 +1450,14 @@ ConnectRecursivelyIfPciMassStorage (
// Recognize PCI Mass Storage, and Xen PCI devices
//
if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ||
- (XenDetected() && IS_CLASS2 (PciHeader, 0xFF, 0x80))) {
+ (XenDetected () && IS_CLASS2 (PciHeader, 0xFF, 0x80)))
+ {
DevicePath = NULL;
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiDevicePathProtocolGuid,
- (VOID*)&DevicePath
- );
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *)&DevicePath
+ );
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1236,26 +1467,27 @@ ConnectRecursivelyIfPciMassStorage (
//
DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
if (DevPathStr != NULL) {
- DEBUG((
- EFI_D_INFO,
+ DEBUG ((
+ DEBUG_INFO,
"Found %s device: %s\n",
- IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ? L"Mass Storage" : L"Xen",
+ (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ?
+ L"Mass Storage" :
+ L"Xen"
+ ),
DevPathStr
));
- FreePool(DevPathStr);
+ FreePool (DevPathStr);
}
Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
if (EFI_ERROR (Status)) {
return Status;
}
-
}
return EFI_SUCCESS;
}
-
/**
This notification function is invoked when the
EMU Variable FVB has been changed.
@@ -1267,15 +1499,14 @@ ConnectRecursivelyIfPciMassStorage (
VOID
EFIAPI
EmuVariablesUpdatedCallback (
- IN EFI_EVENT Event,
- IN VOID *Context
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
+ DEBUG ((DEBUG_INFO, "EmuVariablesUpdatedCallback\n"));
UpdateNvVarsOnFileSystem ();
}
-
EFI_STATUS
EFIAPI
VisitingFileSystemInstance (
@@ -1298,7 +1529,7 @@ VisitingFileSystemInstance (
}
ConnectedToFileSystem = TRUE;
- mEmuVariableEvent =
+ mEmuVariableEvent =
EfiCreateProtocolNotifyEvent (
&gEfiDevicePathProtocolGuid,
TPL_CALLBACK,
@@ -1306,14 +1537,15 @@ VisitingFileSystemInstance (
NULL,
&mEmuVariableEventReg
);
- PcdStatus = PcdSet64S (PcdEmuVariableEvent,
- (UINT64)(UINTN) mEmuVariableEvent);
+ PcdStatus = PcdSet64S (
+ PcdEmuVariableEvent,
+ (UINT64)(UINTN)mEmuVariableEvent
+ );
ASSERT_RETURN_ERROR (PcdStatus);
return EFI_SUCCESS;
}
-
VOID
PlatformBdsRestoreNvVarsFromHardDisk (
)
@@ -1324,33 +1556,22 @@ PlatformBdsRestoreNvVarsFromHardDisk (
VisitingFileSystemInstance,
NULL
);
-
}
+/**
+ Connect with predefined platform connect sequence.
+
+ The OEM/IBV can customize with their own connect sequence.
+**/
VOID
PlatformBdsConnectSequence (
VOID
)
-/*++
-
-Routine Description:
-
- Connect with predefined platform connect sequence,
- the OEM/IBV can customize with their own connect sequence.
-
-Arguments:
-
- None.
-
-Returns:
-
- None.
-
---*/
{
- UINTN Index;
+ UINTN Index;
+ RETURN_STATUS Status;
- DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
+ DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));
Index = 0;
@@ -1367,13 +1588,14 @@ Returns:
Index++;
}
- //
- // Just use the simple policy to connect all devices
- //
- DEBUG ((EFI_D_INFO, "EfiBootManagerConnectAll\n"));
- EfiBootManagerConnectAll ();
-
- PciAcpiInitialization ();
+ Status = ConnectDevicesFromQemu ();
+ if (RETURN_ERROR (Status)) {
+ //
+ // Just use the simple policy to connect all devices
+ //
+ DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
+ EfiBootManagerConnectAll ();
+ }
}
/**
@@ -1388,12 +1610,15 @@ SaveS3BootScript (
VOID
)
{
- EFI_STATUS Status;
- EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
- STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+ EFI_STATUS Status;
+ EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
+ STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
- Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
- (VOID **) &BootScript);
+ Status = gBS->LocateProtocol (
+ &gEfiS3SaveStateProtocolGuid,
+ NULL,
+ (VOID **)&BootScript
+ );
ASSERT_EFI_ERROR (Status);
//
@@ -1401,35 +1626,44 @@ SaveS3BootScript (
// implementation embeds a deep copy of the info in the boot script, rather
// than storing just a pointer to runtime or NVS storage.
//
- Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
- (UINT32) sizeof Info,
- (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
+ Status = BootScript->Write (
+ BootScript,
+ EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
+ (UINT32)sizeof Info,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)&Info
+ );
ASSERT_EFI_ERROR (Status);
}
+/**
+ Do the platform specific action after the console is ready
+
+ Possible things that can be done in PlatformBootManagerAfterConsole:
+ > Console post action:
+ > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
+ > Signal console ready platform customized event
+ > Run diagnostics like memory testing
+ > Connect certain devices
+ > Dispatch aditional option roms
+ > Special boot: e.g.: USB boot, enter UI
+**/
VOID
EFIAPI
PlatformBootManagerAfterConsole (
VOID
)
-/*++
-
-Routine Description:
-
- The function will execute with as the platform policy, current policy
- is driven by boot mode. IBV/OEM can customize this code for their specific
- policy action.
-
---*/
{
- EFI_BOOT_MODE BootMode;
+ EFI_BOOT_MODE BootMode;
- DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
- DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
- "from disk since flash variables appear to be supported.\n"));
+ DEBUG ((
+ DEBUG_INFO,
+ "PlatformBdsPolicyBehavior: not restoring NvVars "
+ "from disk since flash variables appear to be supported.\n"
+ ));
} else {
//
// Try to restore variables from the hard disk early so
@@ -1442,7 +1676,7 @@ Routine Description:
// Get current Boot Mode
//
BootMode = GetBootModeHob ();
- DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
+ DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));
//
// Go the different platform policy with different boot mode
@@ -1456,26 +1690,40 @@ Routine Description:
BootLogoEnableLogo ();
//
- // Perform some platform specific connect sequence
+ // Set PCI Interrupt Line registers and ACPI SCI_EN
//
- PlatformBdsConnectSequence ();
+ PciAcpiInitialization ();
+
+ //
+ // Write qemu bootorder to efi variables
+ //
+ StoreQemuBootOrder ();
//
// Process QEMU's -kernel command line option
//
TryRunningQemuKernel ();
+ //
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+
EfiBootManagerRefreshAllBootOption ();
//
// Register UEFI Shell
//
PlatformRegisterFvBootOption (
- PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
+ &gUefiShellFileGuid,
+ L"EFI Internal Shell",
+ LOAD_OPTION_ACTIVE
);
RemoveStaleFvFileOptions ();
SetBootOrderFromQemu ();
+
+ PlatformBmPrintScRegisterHandler ();
}
/**
@@ -1489,31 +1737,31 @@ Routine Description:
VOID
EFIAPI
NotifyDevPath (
- IN EFI_EVENT Event,
- IN VOID *Context
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- EFI_HANDLE Handle;
- EFI_STATUS Status;
- UINTN BufferSize;
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
- ATAPI_DEVICE_PATH *Atapi;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ ATAPI_DEVICE_PATH *Atapi;
//
// Examine all new handles
//
- for (;;) {
+ for ( ; ;) {
//
// Get the next handle
//
BufferSize = sizeof (Handle);
- Status = gBS->LocateHandle (
- ByRegisterNotify,
- NULL,
- mEfiDevPathNotifyReg,
- &BufferSize,
- &Handle
- );
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mEfiDevPathNotifyReg,
+ &BufferSize,
+ &Handle
+ );
//
// If not found, we're done
@@ -1529,7 +1777,11 @@ NotifyDevPath (
//
// Get the DevicePath protocol on that handle
//
- Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&DevPathNode
+ );
ASSERT_EFI_ERROR (Status);
while (!IsDevicePathEnd (DevPathNode)) {
@@ -1537,16 +1789,17 @@ NotifyDevPath (
// Find the handler to dump this device path node
//
if (
- (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
- ) {
- Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
+ (DevicePathType (DevPathNode) == MESSAGING_DEVICE_PATH) &&
+ (DevicePathSubType (DevPathNode) == MSG_ATAPI_DP)
+ )
+ {
+ Atapi = (ATAPI_DEVICE_PATH *)DevPathNode;
PciOr16 (
PCI_LIB_ADDRESS (
0,
1,
1,
- (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
+ (Atapi->PrimarySecondary == 1) ? 0x42 : 0x40
),
BIT15
);
@@ -1562,38 +1815,47 @@ NotifyDevPath (
return;
}
-
VOID
InstallDevicePathCallback (
VOID
)
{
- DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
+ DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
- &gEfiDevicePathProtocolGuid,
- TPL_CALLBACK,
- NotifyDevPath,
- NULL,
- &mEfiDevPathNotifyReg
- );
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ NotifyDevPath,
+ NULL,
+ &mEfiDevPathNotifyReg
+ );
}
/**
- This function is called each second during the boot manager waits the timeout.
+ This function is called each second during the boot manager waits the
+ timeout.
@param TimeoutRemain The remaining timeout.
**/
VOID
EFIAPI
PlatformBootManagerWaitCallback (
- UINT16 TimeoutRemain
+ UINT16 TimeoutRemain
)
{
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
- UINT16 Timeout;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
+ UINT16 TimeoutInitial;
- Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+ TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);
+
+ //
+ // If PcdPlatformBootTimeOut is set to zero, then we consider
+ // that no progress update should be enacted (since we'd only
+ // ever display a one-shot progress of either 0% or 100%).
+ //
+ if (TimeoutInitial == 0) {
+ return;
+ }
Black.Raw = 0x00000000;
White.Raw = 0x00FFFFFF;
@@ -1603,8 +1865,68 @@ PlatformBootManagerWaitCallback (
Black.Pixel,
L"Start boot option",
White.Pixel,
- (Timeout - TimeoutRemain) * 100 / Timeout,
+ (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,
0
);
}
+/**
+ The function is called when no boot option could be launched,
+ including platform recovery options and options pointing to applications
+ built into firmware volumes.
+
+ If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
+ UINTN Index;
+
+ //
+ // BootManagerMenu doesn't contain the correct information when return status
+ // is EFI_NOT_FOUND.
+ //
+ Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Normally BdsDxe does not print anything to the system console, but this is
+ // a last resort -- the end-user will likely not see any DEBUG messages
+ // logged in this situation.
+ //
+ // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
+ // here to see if it makes sense to request and wait for a keypress.
+ //
+ if (gST->ConIn != NULL) {
+ AsciiPrint (
+ "%a: No bootable option or device was found.\n"
+ "%a: Press any key to enter the Boot Manager Menu.\n",
+ gEfiCallerBaseName,
+ gEfiCallerBaseName
+ );
+ Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (Index == 0);
+
+ //
+ // Drain any queued keys.
+ //
+ while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
+ //
+ // just throw away Key
+ //
+ }
+ }
+
+ for ( ; ;) {
+ EfiBootManagerBoot (&BootManagerMenu);
+ }
+}