]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
OvmfPkg: Reproduce builds across source format changes
[mirror_edk2.git] / OvmfPkg / Library / PlatformBootManagerLib / BdsPlatform.c
index bd1a4396f1d39e3f16cdd1b88df03213dba909a5..186401296ae2382bb5d82c2824ec9c69cd191bb2 100644 (file)
@@ -1,21 +1,18 @@
 /** @file\r
   Platform BDS customizations.\r
 \r
-  Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "BdsPlatform.h"\r
-#include <Guid/XenInfo.h>\r
 #include <Guid/RootBridgesConnectedEventGroup.h>\r
+#include <Guid/SerialPortLibVendor.h>\r
 #include <Protocol/FirmwareVolume2.h>\r
+#include <Library/PlatformBmPrintScLib.h>\r
+#include <Library/Tcg2PhysicalPresenceLib.h>\r
+#include <Library/XenPlatformLib.h>\r
 \r
 \r
 //\r
@@ -26,7 +23,6 @@ VOID          *mEfiDevPathNotifyReg;
 EFI_EVENT     mEfiDevPathEvent;\r
 VOID          *mEmuVariableEventReg;\r
 EFI_EVENT     mEmuVariableEvent;\r
-BOOLEAN       mDetectVgaOnly;\r
 UINT16        mHostBridgeDevId;\r
 \r
 //\r
@@ -34,14 +30,12 @@ UINT16        mHostBridgeDevId;
 // (for configuring PCI Interrupt Line register)\r
 //\r
 CONST UINT8 PciHostIrqs[] = {\r
-  0x0a, 0x0a, 0x0b, 0x0b\r
+  0x0a, // LNKA, LNKE\r
+  0x0a, // LNKB, LNKF\r
+  0x0b, // LNKC, LNKG\r
+  0x0b  // LNKD, LNKH\r
 };\r
 \r
-//\r
-// Array Size macro\r
-//\r
-#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))\r
-\r
 //\r
 // Type definitions\r
 //\r
@@ -262,7 +256,7 @@ RemoveStaleFvFileOptions (
       DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,\r
                            FALSE, FALSE);\r
       DEBUG ((\r
-        EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE,\r
+        EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,\r
         "%a: removing stale Boot#%04x %s: %r\n",\r
         __FUNCTION__,\r
         (UINT32)BootOptions[Index].OptionNumber,\r
@@ -324,6 +318,15 @@ ConnectRootBridge (
   IN VOID        *Context\r
   );\r
 \r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectVirtioPciRng (\r
+  IN EFI_HANDLE Handle,\r
+  IN VOID       *Instance,\r
+  IN VOID       *Context\r
+  );\r
+\r
 STATIC\r
 VOID\r
 SaveS3BootScript (\r
@@ -333,30 +336,31 @@ SaveS3BootScript (
 //\r
 // BDS Platform Functions\r
 //\r
+/**\r
+  Do the platform init, can be customized by OEM/IBV\r
+\r
+  Possible things that can be done in PlatformBootManagerBeforeConsole:\r
+\r
+  > Update console variable: 1. include hot-plug devices;\r
+  >                          2. Clear ConIn and add SOL for AMT\r
+  > Register new Driver#### or Boot####\r
+  > Register new Key####: e.g.: F12\r
+  > Signal ReadyToLock event\r
+  > Authentication action: 1. connect Auth devices;\r
+  >                        2. Identify auto logon user.\r
+**/\r
 VOID\r
 EFIAPI\r
 PlatformBootManagerBeforeConsole (\r
   VOID\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Platform Bds init. Include the platform firmware vendor, revision\r
-  and so crc check.\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
-  None.\r
-\r
---*/\r
 {\r
-  EFI_HANDLE Handle;\r
-  EFI_STATUS Status;\r
+  EFI_HANDLE    Handle;\r
+  EFI_STATUS    Status;\r
+  UINT16        FrontPageTimeout;\r
+  RETURN_STATUS PcdStatus;\r
 \r
-  DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));\r
+  DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));\r
   InstallDevicePathCallback ();\r
 \r
   VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,\r
@@ -376,7 +380,7 @@ Returns:
   //\r
   EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
 \r
-  if (QemuFwCfgS3Enabled ()) {\r
+  if (PcdGetBool (PcdAcpiS3Enable)) {\r
     //\r
     // Save the boot script too. Note that this will require us to emit the\r
     // DxeSmmReadyToLock event just below, which in turn locks down SMM.\r
@@ -384,8 +388,19 @@ Returns:
     SaveS3BootScript ();\r
   }\r
 \r
+  // We need to connect all trusted consoles for TCG PP. Here we treat all\r
+  // consoles in OVMF to be trusted consoles.\r
+  PlatformInitializeConsole (\r
+    XenDetected() ? gXenPlatformConsole : gPlatformConsole);\r
+\r
+  //\r
+  // Process TPM PPI request; this may require keyboard input\r
+  //\r
+  Tcg2PhysicalPresenceLibProcessRequest (NULL);\r
+\r
   //\r
   // Prevent further changes to LockBoxes or SMRAM.\r
+  // Any TPM 2 Physical Presence Interface opcode must be handled before.\r
   //\r
   Handle = NULL;\r
   Status = gBS->InstallProtocolInterface (&Handle,\r
@@ -393,10 +408,44 @@ Returns:
                   NULL);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  PlatformInitializeConsole (gPlatformConsole);\r
-  PcdSet16 (PcdPlatformBootTimeOut, GetFrontPageTimeoutFromQemu ());\r
+  //\r
+  // Dispatch deferred images after EndOfDxe event and ReadyToLock\r
+  // installation.\r
+  //\r
+  EfiBootManagerDispatchDeferredImages ();\r
+\r
+  FrontPageTimeout = GetFrontPageTimeoutFromQemu ();\r
+  PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);\r
+  ASSERT_RETURN_ERROR (PcdStatus);\r
+  //\r
+  // Reflect the PCD in the standard Timeout variable.\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  EFI_TIME_OUT_VARIABLE_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  (EFI_VARIABLE_NON_VOLATILE |\r
+                   EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
+                   EFI_VARIABLE_RUNTIME_ACCESS),\r
+                  sizeof FrontPageTimeout,\r
+                  &FrontPageTimeout\r
+                  );\r
+  DEBUG ((\r
+    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
+    "%a: SetVariable(%s, %u): %r\n",\r
+    __FUNCTION__,\r
+    EFI_TIME_OUT_VARIABLE_NAME,\r
+    FrontPageTimeout,\r
+    Status\r
+    ));\r
 \r
   PlatformRegisterOptionsAndKeys ();\r
+\r
+  //\r
+  // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL\r
+  // instances on Virtio PCI RNG devices.\r
+  //\r
+  VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid, ConnectVirtioPciRng,\r
+    NULL);\r
 }\r
 \r
 \r
@@ -425,28 +474,110 @@ ConnectRootBridge (
 }\r
 \r
 \r
+STATIC\r
 EFI_STATUS\r
-PrepareLpcBridgeDevicePath (\r
-  IN EFI_HANDLE                DeviceHandle\r
+EFIAPI\r
+ConnectVirtioPciRng (\r
+  IN EFI_HANDLE Handle,\r
+  IN VOID       *Instance,\r
+  IN VOID       *Context\r
   )\r
-/*++\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  EFI_STATUS          Status;\r
+  UINT16              VendorId;\r
+  UINT16              DeviceId;\r
+  UINT8               RevisionId;\r
+  BOOLEAN             Virtio10;\r
+  UINT16              SubsystemId;\r
 \r
-Routine Description:\r
+  PciIo = Instance;\r
 \r
-  Add IsaKeyboard to ConIn,\r
-  add IsaSerial to ConOut, ConIn, ErrOut.\r
-  LPC Bridge: 06 01 00\r
+  //\r
+  // Read and check VendorId.\r
+  //\r
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET,\r
+                        1, &VendorId);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+  if (VendorId != VIRTIO_VENDOR_ID) {\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
-Arguments:\r
+  //\r
+  // Read DeviceId and RevisionId.\r
+  //\r
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET,\r
+                        1, &DeviceId);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_REVISION_ID_OFFSET,\r
+                        1, &RevisionId);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
 \r
-  DeviceHandle            - Handle of PCIIO protocol.\r
+  //\r
+  // From DeviceId and RevisionId, determine whether the device is a\r
+  // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can\r
+  // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and\r
+  // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can\r
+  // only be sanity-checked, and SubsystemId will decide.\r
+  //\r
+  if (DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE &&\r
+      RevisionId >= 0x01) {\r
+    Virtio10 = TRUE;\r
+  } else if (DeviceId >= 0x1000 && DeviceId <= 0x103F && RevisionId == 0x00) {\r
+    Virtio10 = FALSE;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
-Returns:\r
+  //\r
+  // Read and check SubsystemId as dictated by Virtio10.\r
+  //\r
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16,\r
+                        PCI_SUBSYSTEM_ID_OFFSET, 1, &SubsystemId);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+  if ((Virtio10 && SubsystemId >= 0x40) ||\r
+      (!Virtio10 && SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {\r
+    Status = gBS->ConnectController (\r
+                    Handle, // ControllerHandle\r
+                    NULL,   // DriverImageHandle -- connect all drivers\r
+                    NULL,   // RemainingDevicePath -- produce all child handles\r
+                    FALSE   // Recursive -- don't follow child handles\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+\r
+Error:\r
+  DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.\r
 \r
-  EFI_SUCCESS             - LPC bridge is added to ConOut, ConIn, and ErrOut.\r
-  EFI_STATUS              - No LPC bridge is added.\r
+  @param[in] DeviceHandle  Handle of the LPC Bridge device.\r
 \r
---*/\r
+  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added to\r
+                       ConOut, ConIn, and ErrOut.\r
+\r
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
+                       from DeviceHandle.\r
+**/\r
+EFI_STATUS\r
+PrepareLpcBridgeDevicePath (\r
+  IN EFI_HANDLE                DeviceHandle\r
+  )\r
 {\r
   EFI_STATUS                Status;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
@@ -467,7 +598,8 @@ Returns:
   //\r
   // Register Keyboard\r
   //\r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
 \r
   EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
 \r
@@ -477,9 +609,12 @@ Returns:
   DevicePath = TempDevicePath;\r
   gPnp16550ComPortDeviceNode.UID = 0;\r
 \r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
 \r
   //\r
   // Print Device Path\r
@@ -487,9 +622,9 @@ Returns:
   DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
   if (DevPathStr != NULL) {\r
     DEBUG((\r
-      EFI_D_INFO,\r
+      DEBUG_INFO,\r
       "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
-      __LINE__,\r
+      DEBUG_LINE_NUMBER,\r
       gPnp16550ComPortDeviceNode.UID + 1,\r
       DevPathStr\r
       ));\r
@@ -506,9 +641,12 @@ Returns:
   DevicePath = TempDevicePath;\r
   gPnp16550ComPortDeviceNode.UID = 1;\r
 \r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
 \r
   //\r
   // Print Device Path\r
@@ -516,9 +654,9 @@ Returns:
   DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
   if (DevPathStr != NULL) {\r
     DEBUG((\r
-      EFI_D_INFO,\r
+      DEBUG_INFO,\r
       "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
-      __LINE__,\r
+      DEBUG_LINE_NUMBER,\r
       gPnp16550ComPortDeviceNode.UID + 1,\r
       DevPathStr\r
       ));\r
@@ -532,6 +670,43 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+typedef struct {\r
+  VENDOR_DEVICE_PATH        Guid;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} SERIAL_DEVICE_PATH;\r
+\r
+SERIAL_DEVICE_PATH serialDevicePath = {\r
+  {\r
+    { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0} },\r
+    EDKII_SERIAL_PORT_LIB_VENDOR_GUID\r
+  },\r
+  { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }\r
+};\r
+\r
+VOID\r
+PrepareMicrovmDevicePath (\r
+  VOID\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINT16                    HostBridgeDevId;\r
+\r
+  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
+  if (HostBridgeDevId != MICROVM_PSEUDO_DEVICE_ID) {\r
+    return;\r
+  }\r
+\r
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL*)&serialDevicePath;\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
+}\r
+\r
 EFI_STATUS\r
 GetGopDevicePath (\r
    IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
@@ -585,7 +760,8 @@ GetGopDevicePath (
     // Add all the child handles as possible Console Device\r
     //\r
     for (Index = 0; Index < GopHandleCount; Index++) {\r
-      Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
+      Status = gBS->HandleProtocol (GopHandleBuffer[Index],\r
+                      &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
       if (EFI_ERROR (Status)) {\r
         continue;\r
       }\r
@@ -604,8 +780,8 @@ GetGopDevicePath (
         *GopDevicePath = TempDevicePath;\r
 \r
         //\r
-        // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
-        // Add the integrity GOP device path.\r
+        // Delete the PCI device's path that added by\r
+        // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.\r
         //\r
         EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);\r
         EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);\r
@@ -617,27 +793,20 @@ GetGopDevicePath (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Add PCI display to ConOut.\r
+\r
+  @param[in] DeviceHandle  Handle of the PCI display device.\r
+\r
+  @retval EFI_SUCCESS  The PCI display device has been added to ConOut.\r
+\r
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
+                       from DeviceHandle.\r
+**/\r
 EFI_STATUS\r
 PreparePciDisplayDevicePath (\r
   IN EFI_HANDLE                DeviceHandle\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Add PCI VGA to ConOut.\r
-  PCI VGA: 03 00 00\r
-\r
-Arguments:\r
-\r
-  DeviceHandle            - Handle of PCIIO protocol.\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS             - PCI VGA is added to ConOut.\r
-  EFI_STATUS              - No PCI VGA device is added.\r
-\r
---*/\r
 {\r
   EFI_STATUS                Status;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
@@ -662,27 +831,21 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_STATUS\r
-PreparePciSerialDevicePath (\r
-  IN EFI_HANDLE                DeviceHandle\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
+/**\r
   Add PCI Serial to ConOut, ConIn, ErrOut.\r
-  PCI Serial: 07 00 02\r
-\r
-Arguments:\r
 \r
-  DeviceHandle            - Handle of PCIIO protocol.\r
+  @param[in] DeviceHandle  Handle of the PCI serial device.\r
 \r
-Returns:\r
+  @retval EFI_SUCCESS  The PCI serial device has been added to ConOut, ConIn,\r
+                       ErrOut.\r
 \r
-  EFI_SUCCESS             - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
-  EFI_STATUS              - No PCI Serial device is added.\r
-\r
---*/\r
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
+                       from DeviceHandle.\r
+**/\r
+EFI_STATUS\r
+PreparePciSerialDevicePath (\r
+  IN EFI_HANDLE                DeviceHandle\r
+  )\r
 {\r
   EFI_STATUS                Status;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
@@ -697,8 +860,10 @@ Returns:
     return Status;\r
   }\r
 \r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
-  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
 \r
   EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
   EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
@@ -814,7 +979,8 @@ VisitAllPciInstances (
   @param[in]  PciIo - PCI IO protocol instance\r
   @param[in]  Pci - PCI Header register block\r
 \r
-  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
+  @retval EFI_SUCCESS - PCI Device check and Console variable update\r
+                        successfully.\r
   @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
 \r
 **/\r
@@ -836,35 +1002,33 @@ DetectAndPreparePlatformPciDevicePath (
     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  if (!mDetectVgaOnly) {\r
+  //\r
+  // Here we decide whether it is LPC Bridge\r
+  //\r
+  if ((IS_PCI_LPC (Pci)) ||\r
+      ((IS_PCI_ISA_PDECODE (Pci)) &&\r
+       (Pci->Hdr.VendorId == 0x8086) &&\r
+       (Pci->Hdr.DeviceId == 0x7000)\r
+      )\r
+     ) {\r
     //\r
-    // Here we decide whether it is LPC Bridge\r
+    // Add IsaKeyboard to ConIn,\r
+    // add IsaSerial to ConOut, ConIn, ErrOut\r
     //\r
-    if ((IS_PCI_LPC (Pci)) ||\r
-        ((IS_PCI_ISA_PDECODE (Pci)) &&\r
-         (Pci->Hdr.VendorId == 0x8086) &&\r
-         (Pci->Hdr.DeviceId == 0x7000)\r
-        )\r
-       ) {\r
-      //\r
-      // Add IsaKeyboard to ConIn,\r
-      // add IsaSerial to ConOut, ConIn, ErrOut\r
-      //\r
-      DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
-      PrepareLpcBridgeDevicePath (Handle);\r
-      return EFI_SUCCESS;\r
-    }\r
+    DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));\r
+    PrepareLpcBridgeDevicePath (Handle);\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Here we decide which Serial device to enable in PCI bus\r
+  //\r
+  if (IS_PCI_16550SERIAL (Pci)) {\r
     //\r
-    // Here we decide which Serial device to enable in PCI bus\r
+    // Add them to ConOut, ConIn, ErrOut.\r
     //\r
-    if (IS_PCI_16550SERIAL (Pci)) {\r
-      //\r
-      // Add them to ConOut, ConIn, ErrOut.\r
-      //\r
-      DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
-      PreparePciSerialDevicePath (Handle);\r
-      return EFI_SUCCESS;\r
-    }\r
+    DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));\r
+    PreparePciSerialDevicePath (Handle);\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   //\r
@@ -874,7 +1038,7 @@ DetectAndPreparePlatformPciDevicePath (
     //\r
     // Add them to ConOut.\r
     //\r
-    DEBUG ((EFI_D_INFO, "Found PCI display device\n"));\r
+    DEBUG ((DEBUG_INFO, "Found PCI display device\n"));\r
     PreparePciDisplayDevicePath (Handle);\r
     return EFI_SUCCESS;\r
   }\r
@@ -884,80 +1048,48 @@ DetectAndPreparePlatformPciDevicePath (
 \r
 \r
 /**\r
-  Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
+  Connect the predefined platform default console device.\r
 \r
-  @param[in]  DetectVgaOnly - Only detect VGA device if it's TRUE.\r
-\r
-  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
-  @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
+  Always try to find and enable PCI display devices.\r
 \r
+  @param[in] PlatformConsole  Predefined platform default console device array.\r
 **/\r
-EFI_STATUS\r
-DetectAndPreparePlatformPciDevicePaths (\r
-  BOOLEAN DetectVgaOnly\r
-  )\r
-{\r
-  mDetectVgaOnly = DetectVgaOnly;\r
-  return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
-}\r
-\r
-\r
 VOID\r
 PlatformInitializeConsole (\r
   IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Connect the predefined platform default console device. Always try to find\r
-  and enable the vga device if have.\r
-\r
-Arguments:\r
-\r
-  PlatformConsole         - Predefined platform default console device array.\r
---*/\r
 {\r
   UINTN                              Index;\r
-  EFI_DEVICE_PATH_PROTOCOL           *VarConout;\r
-  EFI_DEVICE_PATH_PROTOCOL           *VarConin;\r
 \r
   //\r
-  // Connect RootBridge\r
+  // Do platform specific PCI Device check and add them to ConOut, ConIn,\r
+  // ErrOut\r
   //\r
-  GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);\r
-  GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);\r
+  VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
 \r
-  if (VarConout == NULL || VarConin == NULL) {\r
-    //\r
-    // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
-    //\r
-    DetectAndPreparePlatformPciDevicePaths (FALSE);\r
+  PrepareMicrovmDevicePath ();\r
 \r
+  //\r
+  // Have chance to connect the platform default console,\r
+  // the platform default console is the minimum device group\r
+  // the platform should support\r
+  //\r
+  for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
     //\r
-    // Have chance to connect the platform default console,\r
-    // the platform default console is the minimum device group\r
-    // the platform should support\r
+    // Update the console variable with the connect type\r
     //\r
-    for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
-      //\r
-      // Update the console variable with the connect type\r
-      //\r
-      if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
-        EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);\r
-      }\r
-      if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
-        EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);\r
-      }\r
-      if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
-        EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);\r
-      }\r
+    if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
+      EfiBootManagerUpdateConsoleVariable (ConIn,\r
+        PlatformConsole[Index].DevicePath, NULL);\r
+    }\r
+    if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
+      EfiBootManagerUpdateConsoleVariable (ConOut,\r
+        PlatformConsole[Index].DevicePath, NULL);\r
+    }\r
+    if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
+      EfiBootManagerUpdateConsoleVariable (ErrOut,\r
+        PlatformConsole[Index].DevicePath, NULL);\r
     }\r
-  } else {\r
-    //\r
-    // Only detect VGA device and add them to ConOut\r
-    //\r
-    DetectAndPreparePlatformPciDevicePaths (TRUE);\r
   }\r
 }\r
 \r
@@ -1037,7 +1169,7 @@ SetPciIntLine (
     }\r
     if (RootBusNumber == 0 && RootSlot == 0) {\r
       DEBUG((\r
-        EFI_D_ERROR,\r
+        DEBUG_ERROR,\r
         "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
         __FUNCTION__\r
         ));\r
@@ -1088,7 +1220,7 @@ SetPciIntLine (
       Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
       ASSERT_EFI_ERROR (Status);\r
 \r
-      DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,\r
+      DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,\r
         (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,\r
         IrqLine));\r
 \r
@@ -1130,27 +1262,35 @@ PciAcpiInitialization (
       //\r
       // 00:01.0 ISA Bridge (PIIX4) LNK routing targets\r
       //\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), PciHostIrqs[0]); // A\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), PciHostIrqs[1]); // B\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), PciHostIrqs[2]); // C\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), PciHostIrqs[3]); // D\r
       break;\r
     case INTEL_Q35_MCH_DEVICE_ID:\r
       Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
       //\r
       // 00:1f.0 LPC Bridge (Q35) LNK routing targets\r
       //\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G\r
-      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), PciHostIrqs[0]); // A\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), PciHostIrqs[1]); // B\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), PciHostIrqs[2]); // C\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), PciHostIrqs[3]); // D\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), PciHostIrqs[0]); // E\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), PciHostIrqs[1]); // F\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), PciHostIrqs[2]); // G\r
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), PciHostIrqs[3]); // H\r
       break;\r
+    case MICROVM_PSEUDO_DEVICE_ID:\r
+      return;\r
     default:\r
-      DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
+      if (XenDetected ()) {\r
+        //\r
+        // There is no PCI bus in this case.\r
+        //\r
+        return;\r
+      }\r
+      DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
         __FUNCTION__, mHostBridgeDevId));\r
       ASSERT (FALSE);\r
       return;\r
@@ -1167,38 +1307,6 @@ PciAcpiInitialization (
   IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
 }\r
 \r
-/**\r
-  This function detects if OVMF is running on Xen.\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-XenDetected (\r
-  VOID\r
-  )\r
-{\r
-  EFI_HOB_GUID_TYPE         *GuidHob;\r
-  STATIC INTN               FoundHob = -1;\r
-\r
-  if (FoundHob == 0) {\r
-    return FALSE;\r
-  } else if (FoundHob == 1) {\r
-    return TRUE;\r
-  }\r
-\r
-  //\r
-  // See if a XenInfo HOB is available\r
-  //\r
-  GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);\r
-  if (GuidHob == NULL) {\r
-    FoundHob = 0;\r
-    return FALSE;\r
-  }\r
-\r
-  FoundHob = 1;\r
-  return TRUE;\r
-}\r
-\r
 EFI_STATUS\r
 EFIAPI\r
 ConnectRecursivelyIfPciMassStorage (\r
@@ -1232,9 +1340,12 @@ ConnectRecursivelyIfPciMassStorage (
     DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
     if (DevPathStr != NULL) {\r
       DEBUG((\r
-        EFI_D_INFO,\r
+        DEBUG_INFO,\r
         "Found %s device: %s\n",\r
-        IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ? L"Mass Storage" : L"Xen",\r
+        (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ?\r
+         L"Mass Storage" :\r
+         L"Xen"\r
+         ),\r
         DevPathStr\r
         ));\r
       FreePool(DevPathStr);\r
@@ -1266,7 +1377,7 @@ EmuVariablesUpdatedCallback (
   IN  VOID      *Context\r
   )\r
 {\r
-  DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));\r
+  DEBUG ((DEBUG_INFO, "EmuVariablesUpdatedCallback\n"));\r
   UpdateNvVarsOnFileSystem ();\r
 }\r
 \r
@@ -1281,6 +1392,7 @@ VisitingFileSystemInstance (
 {\r
   EFI_STATUS      Status;\r
   STATIC BOOLEAN  ConnectedToFileSystem = FALSE;\r
+  RETURN_STATUS   PcdStatus;\r
 \r
   if (ConnectedToFileSystem) {\r
     return EFI_ALREADY_STARTED;\r
@@ -1300,7 +1412,9 @@ VisitingFileSystemInstance (
       NULL,\r
       &mEmuVariableEventReg\r
       );\r
-  PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);\r
+  PcdStatus = PcdSet64S (PcdEmuVariableEvent,\r
+                (UINT64)(UINTN) mEmuVariableEvent);\r
+  ASSERT_RETURN_ERROR (PcdStatus);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1319,30 +1433,20 @@ PlatformBdsRestoreNvVarsFromHardDisk (
 \r
 }\r
 \r
+/**\r
+  Connect with predefined platform connect sequence.\r
+\r
+  The OEM/IBV can customize with their own connect sequence.\r
+**/\r
 VOID\r
 PlatformBdsConnectSequence (\r
   VOID\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Connect with predefined platform connect sequence,\r
-  the OEM/IBV can customize with their own connect sequence.\r
-\r
-Arguments:\r
-\r
-  None.\r
-\r
-Returns:\r
-\r
-  None.\r
-\r
---*/\r
 {\r
-  UINTN Index;\r
+  UINTN         Index;\r
+  RETURN_STATUS Status;\r
 \r
-  DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r
+  DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));\r
 \r
   Index = 0;\r
 \r
@@ -1359,13 +1463,14 @@ Returns:
     Index++;\r
   }\r
 \r
-  //\r
-  // Just use the simple policy to connect all devices\r
-  //\r
-  DEBUG ((EFI_D_INFO, "EfiBootManagerConnectAll\n"));\r
-  EfiBootManagerConnectAll ();\r
-\r
-  PciAcpiInitialization ();\r
+  Status = ConnectDevicesFromQemu ();\r
+  if (RETURN_ERROR (Status)) {\r
+    //\r
+    // Just use the simple policy to connect all devices\r
+    //\r
+    DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));\r
+    EfiBootManagerConnectAll ();\r
+  }\r
 }\r
 \r
 /**\r
@@ -1400,27 +1505,31 @@ SaveS3BootScript (
 }\r
 \r
 \r
+/**\r
+  Do the platform specific action after the console is ready\r
+\r
+  Possible things that can be done in PlatformBootManagerAfterConsole:\r
+\r
+  > Console post action:\r
+    > Dynamically switch output mode from 100x31 to 80x25 for certain senarino\r
+    > Signal console ready platform customized event\r
+  > Run diagnostics like memory testing\r
+  > Connect certain devices\r
+  > Dispatch aditional option roms\r
+  > Special boot: e.g.: USB boot, enter UI\r
+**/\r
 VOID\r
 EFIAPI\r
 PlatformBootManagerAfterConsole (\r
   VOID\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  The function will execute with as the platform policy, current policy\r
-  is driven by boot mode. IBV/OEM can customize this code for their specific\r
-  policy action.\r
-\r
---*/\r
 {\r
   EFI_BOOT_MODE                      BootMode;\r
 \r
-  DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));\r
+  DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));\r
 \r
   if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {\r
-    DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
+    DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
       "from disk since flash variables appear to be supported.\n"));\r
   } else {\r
     //\r
@@ -1434,7 +1543,7 @@ Routine Description:
   // Get current Boot Mode\r
   //\r
   BootMode = GetBootModeHob ();\r
-  DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));\r
+  DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));\r
 \r
   //\r
   // Go the different platform policy with different boot mode\r
@@ -1448,26 +1557,33 @@ Routine Description:
   BootLogoEnableLogo ();\r
 \r
   //\r
-  // Perform some platform specific connect sequence\r
+  // Set PCI Interrupt Line registers and ACPI SCI_EN\r
   //\r
-  PlatformBdsConnectSequence ();\r
+  PciAcpiInitialization ();\r
 \r
   //\r
   // Process QEMU's -kernel command line option\r
   //\r
   TryRunningQemuKernel ();\r
 \r
+  //\r
+  // Perform some platform specific connect sequence\r
+  //\r
+  PlatformBdsConnectSequence ();\r
+\r
   EfiBootManagerRefreshAllBootOption ();\r
 \r
   //\r
   // Register UEFI Shell\r
   //\r
   PlatformRegisterFvBootOption (\r
-    PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE\r
+    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE\r
     );\r
 \r
   RemoveStaleFvFileOptions ();\r
   SetBootOrderFromQemu ();\r
+\r
+  PlatformBmPrintScRegisterHandler ();\r
 }\r
 \r
 /**\r
@@ -1521,7 +1637,8 @@ NotifyDevPath (
     //\r
     // Get the DevicePath protocol on that handle\r
     //\r
-    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
+    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,\r
+                    (VOID **)&DevPathNode);\r
     ASSERT_EFI_ERROR (Status);\r
 \r
     while (!IsDevicePathEnd (DevPathNode)) {\r
@@ -1560,7 +1677,7 @@ InstallDevicePathCallback (
   VOID\r
   )\r
 {\r
-  DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
+  DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));\r
   mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
                           &gEfiDevicePathProtocolGuid,\r
                           TPL_CALLBACK,\r
@@ -1571,7 +1688,8 @@ InstallDevicePathCallback (
 }\r
 \r
 /**\r
-  This function is called each second during the boot manager waits the timeout.\r
+  This function is called each second during the boot manager waits the\r
+  timeout.\r
 \r
   @param TimeoutRemain  The remaining timeout.\r
 **/\r
@@ -1583,9 +1701,18 @@ PlatformBootManagerWaitCallback (
 {\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
-  UINT16                              Timeout;\r
+  UINT16                              TimeoutInitial;\r
 \r
-  Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
+  TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);\r
+\r
+  //\r
+  // If PcdPlatformBootTimeOut is set to zero, then we consider\r
+  // that no progress update should be enacted (since we'd only\r
+  // ever display a one-shot progress of either 0% or 100%).\r
+  //\r
+  if (TimeoutInitial == 0) {\r
+    return;\r
+  }\r
 \r
   Black.Raw = 0x00000000;\r
   White.Raw = 0x00FFFFFF;\r
@@ -1595,8 +1722,67 @@ PlatformBootManagerWaitCallback (
     Black.Pixel,\r
     L"Start boot option",\r
     White.Pixel,\r
-    (Timeout - TimeoutRemain) * 100 / Timeout,\r
+    (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,\r
     0\r
     );\r
 }\r
 \r
+/**\r
+  The function is called when no boot option could be launched,\r
+  including platform recovery options and options pointing to applications\r
+  built into firmware volumes.\r
+\r
+  If this function returns, BDS attempts to enter an infinite loop.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerUnableToBoot (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_INPUT_KEY                Key;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;\r
+  UINTN                        Index;\r
+\r
+  //\r
+  // BootManagerMenu doesn't contain the correct information when return status\r
+  // is EFI_NOT_FOUND.\r
+  //\r
+  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+  //\r
+  // Normally BdsDxe does not print anything to the system console, but this is\r
+  // a last resort -- the end-user will likely not see any DEBUG messages\r
+  // logged in this situation.\r
+  //\r
+  // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn\r
+  // here to see if it makes sense to request and wait for a keypress.\r
+  //\r
+  if (gST->ConIn != NULL) {\r
+    AsciiPrint (\r
+      "%a: No bootable option or device was found.\n"\r
+      "%a: Press any key to enter the Boot Manager Menu.\n",\r
+      gEfiCallerBaseName,\r
+      gEfiCallerBaseName\r
+      );\r
+    Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
+    ASSERT_EFI_ERROR (Status);\r
+    ASSERT (Index == 0);\r
+\r
+    //\r
+    // Drain any queued keys.\r
+    //\r
+    while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {\r
+      //\r
+      // just throw away Key\r
+      //\r
+    }\r
+  }\r
+\r
+  for (;;) {\r
+    EfiBootManagerBoot (&BootManagerMenu);\r
+  }\r
+}\r