]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Duplicate PlatformBdsLib to PlatformBootManagerLib
authorRuiyu Ni <ruiyu.ni@intel.com>
Mon, 3 Aug 2015 05:26:01 +0000 (13:26 +0800)
committerRuiyu Ni <ruiyu.ni@intel.com>
Wed, 4 May 2016 00:47:36 +0000 (08:47 +0800)
It will be changed to build with MdeModulePkg/BDS.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLib/PlatformBdsLib.inf [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLib/PlatformData.c [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLib/QemuKernel.c [new file with mode: 0644]

diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
new file mode 100644 (file)
index 0000000..8354f31
--- /dev/null
@@ -0,0 +1,1592 @@
+/** @file\r
+  Platform BDS customizations.\r
+\r
+  Copyright (c) 2004 - 2014, 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
+\r
+**/\r
+\r
+#include "BdsPlatform.h"\r
+#include <Guid/RootBridgesConnectedEventGroup.h>\r
+#include <Library/QemuBootOrderLib.h>\r
+\r
+\r
+//\r
+// Global data\r
+//\r
+\r
+VOID          *mEfiDevPathNotifyReg;\r
+EFI_EVENT     mEfiDevPathEvent;\r
+VOID          *mEmuVariableEventReg;\r
+EFI_EVENT     mEmuVariableEvent;\r
+BOOLEAN       mDetectVgaOnly;\r
+UINT16        mHostBridgeDevId;\r
+\r
+//\r
+// Table of host IRQs matching PCI IRQs A-D\r
+// (for configuring PCI Interrupt Line register)\r
+//\r
+CONST UINT8 PciHostIrqs[] = {\r
+  0x0a, 0x0a, 0x0b, 0x0b\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
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(\r
+  IN EFI_HANDLE           Handle,\r
+  IN VOID                 *Instance,\r
+  IN VOID                 *Context\r
+  );\r
+\r
+/**\r
+  @param[in]  Handle - Handle of PCI device instance\r
+  @param[in]  PciIo - PCI IO protocol instance\r
+  @param[in]  Pci - PCI Header register block\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(\r
+  IN EFI_HANDLE           Handle,\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN PCI_TYPE00           *Pci\r
+  );\r
+\r
+\r
+//\r
+// Function prototypes\r
+//\r
+\r
+EFI_STATUS\r
+VisitAllInstancesOfProtocol (\r
+  IN EFI_GUID                    *Id,\r
+  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,\r
+  IN VOID                        *Context\r
+  );\r
+\r
+EFI_STATUS\r
+VisitAllPciInstancesOfProtocol (\r
+  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
+  );\r
+\r
+VOID\r
+InstallDevicePathCallback (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectRootBridge (\r
+  IN EFI_HANDLE  RootBridgeHandle,\r
+  IN VOID        *Instance,\r
+  IN VOID        *Context\r
+  );\r
+\r
+STATIC\r
+VOID\r
+SaveS3BootScript (\r
+  VOID\r
+  );\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+VOID\r
+EFIAPI\r
+PlatformBdsInit (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Platform Bds init. Incude 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
+\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));\r
+  InstallDevicePathCallback ();\r
+\r
+  VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,\r
+    ConnectRootBridge, NULL);\r
+\r
+  //\r
+  // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
+  //\r
+  EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
+\r
+  //\r
+  // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers\r
+  // the preparation of S3 system information. That logic has a hard dependency\r
+  // on the presence of the FACS ACPI table. Since our ACPI tables are only\r
+  // installed after PCI enumeration completes, we must not trigger the S3 save\r
+  // earlier, hence we can't signal End-of-Dxe earlier.\r
+  //\r
+  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
+\r
+  if (QemuFwCfgS3Enabled ()) {\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
+    //\r
+    SaveS3BootScript ();\r
+  }\r
+\r
+  //\r
+  // Prevent further changes to LockBoxes or SMRAM.\r
+  //\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (&Handle,\r
+                  &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,\r
+                  NULL);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectRootBridge (\r
+  IN EFI_HANDLE  RootBridgeHandle,\r
+  IN VOID        *Instance,\r
+  IN VOID        *Context\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // Make the PCI bus driver connect the root bridge, non-recursively. This\r
+  // will produce a number of child handles with PciIo on them.\r
+  //\r
+  Status = gBS->ConnectController (\r
+                  RootBridgeHandle, // ControllerHandle\r
+                  NULL,             // DriverImageHandle\r
+                  NULL,             // RemainingDevicePath -- produce all\r
+                                    //   children\r
+                  FALSE             // Recursive\r
+                  );\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PrepareLpcBridgeDevicePath (\r
+  IN EFI_HANDLE                DeviceHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add IsaKeyboard to ConIn,\r
+  add IsaSerial to ConOut, ConIn, ErrOut.\r
+  LPC Bridge: 06 01 00\r
+\r
+Arguments:\r
+\r
+  DeviceHandle            - Handle of PCIIO protocol.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             - LPC bridge is added to ConOut, ConIn, and ErrOut.\r
+  EFI_STATUS              - No LPC bridge is added.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
+  CHAR16                    *DevPathStr;\r
+\r
+  DevicePath = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID*)&DevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  TempDevicePath = DevicePath;\r
+\r
+  //\r
+  // Register Keyboard\r
+  //\r
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
+\r
+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+\r
+  //\r
+  // Register COM1\r
+  //\r
+  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
+\r
+  //\r
+  // Print Device Path\r
+  //\r
+  DevPathStr = DevicePathToStr(DevicePath);\r
+  if (DevPathStr != NULL) {\r
+    DEBUG((\r
+      EFI_D_INFO,\r
+      "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
+      __LINE__,\r
+      gPnp16550ComPortDeviceNode.UID + 1,\r
+      DevPathStr\r
+      ));\r
+    FreePool(DevPathStr);\r
+  }\r
+\r
+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+  BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
+\r
+  //\r
+  // Register COM2\r
+  //\r
+  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
+\r
+  //\r
+  // Print Device Path\r
+  //\r
+  DevPathStr = DevicePathToStr(DevicePath);\r
+  if (DevPathStr != NULL) {\r
+    DEBUG((\r
+      EFI_D_INFO,\r
+      "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
+      __LINE__,\r
+      gPnp16550ComPortDeviceNode.UID + 1,\r
+      DevPathStr\r
+      ));\r
+    FreePool(DevPathStr);\r
+  }\r
+\r
+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+  BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetGopDevicePath (\r
+   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
+   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
+   )\r
+{\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  EFI_HANDLE                      PciDeviceHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;\r
+  UINTN                           GopHandleCount;\r
+  EFI_HANDLE                      *GopHandleBuffer;\r
+\r
+  if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Initialize the GopDevicePath to be PciDevicePath\r
+  //\r
+  *GopDevicePath    = PciDevicePath;\r
+  TempPciDevicePath = PciDevicePath;\r
+\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &TempPciDevicePath,\r
+                  &PciDeviceHandle\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Try to connect this handle, so that GOP dirver could start on this\r
+  // device and create child handles with GraphicsOutput Protocol installed\r
+  // on them, then we get device paths of these child handles and select\r
+  // them as possible console device.\r
+  //\r
+  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
+\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  NULL,\r
+                  &GopHandleCount,\r
+                  &GopHandleBuffer\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // 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
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+      if (CompareMem (\r
+            PciDevicePath,\r
+            TempDevicePath,\r
+            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
+            ) == 0) {\r
+        //\r
+        // In current implementation, we only enable one of the child handles\r
+        // as console device, i.e. sotre one of the child handle's device\r
+        // path to variable "ConOut"\r
+        // In futhure, we could select all child handles to be console device\r
+        //\r
+\r
+        *GopDevicePath = TempDevicePath;\r
+\r
+        //\r
+        // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
+        // Add the integrity GOP device path.\r
+        //\r
+        BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);\r
+        BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);\r
+      }\r
+    }\r
+    gBS->FreePool (GopHandleBuffer);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PreparePciVgaDevicePath (\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
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;\r
+\r
+  DevicePath    = NULL;\r
+  GopDevicePath = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID*)&DevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  GetGopDevicePath (DevicePath, &GopDevicePath);\r
+  DevicePath = GopDevicePath;\r
+\r
+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PreparePciSerialDevicePath (\r
+  IN EFI_HANDLE                DeviceHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\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
+\r
+Returns:\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
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+\r
+  DevicePath = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID*)&DevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+  BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+VisitAllInstancesOfProtocol (\r
+  IN EFI_GUID                    *Id,\r
+  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,\r
+  IN VOID                        *Context\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     HandleCount;\r
+  EFI_HANDLE                *HandleBuffer;\r
+  UINTN                     Index;\r
+  VOID                      *Instance;\r
+\r
+  //\r
+  // Start to check all the PciIo to find all possible device\r
+  //\r
+  HandleCount = 0;\r
+  HandleBuffer = NULL;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  Id,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    Status = (*CallBackFunction) (\r
+               HandleBuffer[Index],\r
+               Instance,\r
+               Context\r
+               );\r
+  }\r
+\r
+  gBS->FreePool (HandleBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VisitingAPciInstance (\r
+  IN EFI_HANDLE  Handle,\r
+  IN VOID        *Instance,\r
+  IN VOID        *Context\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
+  PCI_TYPE00                Pci;\r
+\r
+  PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
+\r
+  //\r
+  // Check for all PCI device\r
+  //\r
+  Status = PciIo->Pci.Read (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint32,\r
+                    0,\r
+                    sizeof (Pci) / sizeof (UINT32),\r
+                    &Pci\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
+           Handle,\r
+           PciIo,\r
+           &Pci\r
+           );\r
+\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+VisitAllPciInstances (\r
+  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
+  )\r
+{\r
+  return VisitAllInstancesOfProtocol (\r
+           &gEfiPciIoProtocolGuid,\r
+           VisitingAPciInstance,\r
+           (VOID*)(UINTN) CallBackFunction\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Do platform specific PCI Device check and add them to\r
+  ConOut, ConIn, ErrOut.\r
+\r
+  @param[in]  Handle - Handle of PCI device instance\r
+  @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_STATUS - PCI Device check or Console variable update fail.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DetectAndPreparePlatformPciDevicePath (\r
+  IN EFI_HANDLE           Handle,\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN PCI_TYPE00           *Pci\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = PciIo->Attributes (\r
+    PciIo,\r
+    EfiPciIoAttributeOperationEnable,\r
+    EFI_PCI_DEVICE_ENABLE,\r
+    NULL\r
+    );\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
+      // 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
+    //\r
+    // Here we decide which Serial device to enable in PCI bus\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
+  }\r
+\r
+  //\r
+  // Here we decide which VGA device to enable in PCI bus\r
+  //\r
+  if (IS_PCI_VGA (Pci)) {\r
+    //\r
+    // Add them to ConOut.\r
+    //\r
+    DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));\r
+    PreparePciVgaDevicePath (Handle);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\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
+\r
+**/\r
+EFI_STATUS\r
+DetectAndPreparePlatformPciDevicePaths (\r
+  BOOLEAN DetectVgaOnly\r
+  )\r
+{\r
+  mDetectVgaOnly = DetectVgaOnly;\r
+  return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PlatformBdsConnectConsole (\r
+  IN BDS_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         - Predfined platform default console device array.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             - Success connect at least one ConIn and ConOut\r
+                            device, there must have one ConOut device is\r
+                            active vga device.\r
+\r
+  EFI_STATUS              - Return the status of\r
+                            BdsLibConnectAllDefaultConsoles ()\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                         Status;\r
+  UINTN                              Index;\r
+  EFI_DEVICE_PATH_PROTOCOL           *VarConout;\r
+  EFI_DEVICE_PATH_PROTOCOL           *VarConin;\r
+  UINTN                              DevicePathSize;\r
+\r
+  //\r
+  // Connect RootBridge\r
+  //\r
+  VarConout = BdsLibGetVariableAndSize (\r
+                VarConsoleOut,\r
+                &gEfiGlobalVariableGuid,\r
+                &DevicePathSize\r
+                );\r
+  VarConin = BdsLibGetVariableAndSize (\r
+               VarConsoleInp,\r
+               &gEfiGlobalVariableGuid,\r
+               &DevicePathSize\r
+               );\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
+\r
+    //\r
+    // Have chance to connect the platform default console,\r
+    // the platform default console is the minimue device group\r
+    // the platform should support\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
+        BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);\r
+      }\r
+      if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
+        BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);\r
+      }\r
+      if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
+        BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // Only detect VGA device and add them to ConOut\r
+    //\r
+    DetectAndPreparePlatformPciDevicePaths (TRUE);\r
+  }\r
+\r
+  //\r
+  // Connect the all the default console with current cosole variable\r
+  //\r
+  Status = BdsLibConnectAllDefaultConsoles ();\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Configure PCI Interrupt Line register for applicable devices\r
+  Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()\r
+\r
+  @param[in]  Handle - Handle of PCI device instance\r
+  @param[in]  PciIo - PCI IO protocol instance\r
+  @param[in]  PciHdr - PCI Header register block\r
+\r
+  @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetPciIntLine (\r
+  IN EFI_HANDLE           Handle,\r
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
+  IN PCI_TYPE00           *PciHdr\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+  UINTN                     RootSlot;\r
+  UINTN                     Idx;\r
+  UINT8                     IrqLine;\r
+  EFI_STATUS                Status;\r
+  UINT32                    RootBusNumber;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (PciHdr->Device.InterruptPin != 0) {\r
+\r
+    DevPathNode = DevicePathFromHandle (Handle);\r
+    ASSERT (DevPathNode != NULL);\r
+    DevPath = DevPathNode;\r
+\r
+    RootBusNumber = 0;\r
+    if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&\r
+        DevicePathSubType (DevPathNode) == ACPI_DP &&\r
+        ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {\r
+      RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;\r
+    }\r
+\r
+    //\r
+    // Compute index into PciHostIrqs[] table by walking\r
+    // the device path and adding up all device numbers\r
+    //\r
+    Status = EFI_NOT_FOUND;\r
+    RootSlot = 0;\r
+    Idx = PciHdr->Device.InterruptPin - 1;\r
+    while (!IsDevicePathEnd (DevPathNode)) {\r
+      if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&\r
+          DevicePathSubType (DevPathNode) == HW_PCI_DP) {\r
+\r
+        Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
+\r
+        //\r
+        // Unlike SeaBIOS, which starts climbing from the leaf device\r
+        // up toward the root, we traverse the device path starting at\r
+        // the root moving toward the leaf node.\r
+        // The slot number of the top-level parent bridge is needed for\r
+        // Q35 cases with more than 24 slots on the root bus.\r
+        //\r
+        if (Status != EFI_SUCCESS) {\r
+          Status = EFI_SUCCESS;\r
+          RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
+        }\r
+      }\r
+\r
+      DevPathNode = NextDevicePathNode (DevPathNode);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    if (RootBusNumber == 0 && RootSlot == 0) {\r
+      DEBUG((\r
+        EFI_D_ERROR,\r
+        "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
+        __FUNCTION__\r
+        ));\r
+      ASSERT (FALSE);\r
+    }\r
+\r
+    //\r
+    // Final PciHostIrqs[] index calculation depends on the platform\r
+    // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()\r
+    //\r
+    switch (mHostBridgeDevId) {\r
+      case INTEL_82441_DEVICE_ID:\r
+        Idx -= 1;\r
+        break;\r
+      case INTEL_Q35_MCH_DEVICE_ID:\r
+        //\r
+        // SeaBIOS contains the following comment:\r
+        // "Slots 0-24 rotate slot:pin mapping similar to piix above, but\r
+        //  with a different starting index - see q35-acpi-dsdt.dsl.\r
+        //\r
+        //  Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"\r
+        //\r
+        if (RootSlot > 24) {\r
+          //\r
+          // in this case, subtract back out RootSlot from Idx\r
+          // (SeaBIOS never adds it to begin with, but that would make our\r
+          //  device path traversal loop above too awkward)\r
+          //\r
+          Idx -= RootSlot;\r
+        }\r
+        break;\r
+      default:\r
+        ASSERT (FALSE); // should never get here\r
+    }\r
+    Idx %= ARRAY_SIZE (PciHostIrqs);\r
+    IrqLine = PciHostIrqs[Idx];\r
+\r
+    DEBUG_CODE_BEGIN ();\r
+    {\r
+      CHAR16        *DevPathString;\r
+      STATIC CHAR16 Fallback[] = L"<failed to convert>";\r
+      UINTN         Segment, Bus, Device, Function;\r
+\r
+      DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);\r
+      if (DevPathString == NULL) {\r
+        DevPathString = Fallback;\r
+      }\r
+      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
+        (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,\r
+        IrqLine));\r
+\r
+      if (DevPathString != Fallback) {\r
+        FreePool (DevPathString);\r
+      }\r
+    }\r
+    DEBUG_CODE_END ();\r
+\r
+    //\r
+    // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]\r
+    //\r
+    Status = PciIo->Pci.Write (\r
+               PciIo,\r
+               EfiPciIoWidthUint8,\r
+               PCI_INT_LINE_OFFSET,\r
+               1,\r
+               &IrqLine\r
+               );\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+VOID\r
+PciAcpiInitialization (\r
+  )\r
+{\r
+  UINTN  Pmba;\r
+\r
+  //\r
+  // Query Host Bridge DID to determine platform type\r
+  //\r
+  mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
+  switch (mHostBridgeDevId) {\r
+    case INTEL_82441_DEVICE_ID:\r
+      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
+      //\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
+      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
+      break;\r
+    default:\r
+      DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
+        __FUNCTION__, mHostBridgeDevId));\r
+      ASSERT (FALSE);\r
+      return;\r
+  }\r
+\r
+  //\r
+  // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices\r
+  //\r
+  VisitAllPciInstances (SetPciIntLine);\r
+\r
+  //\r
+  // Set ACPI SCI_EN bit in PMCNTRL\r
+  //\r
+  IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectRecursivelyIfPciMassStorage (\r
+  IN EFI_HANDLE           Handle,\r
+  IN EFI_PCI_IO_PROTOCOL  *Instance,\r
+  IN PCI_TYPE00           *PciHeader\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  CHAR16                    *DevPathStr;\r
+\r
+  if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {\r
+    DevicePath = NULL;\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    (VOID*)&DevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Print Device Path\r
+    //\r
+    DevPathStr = DevicePathToStr (DevicePath);\r
+    if (DevPathStr != NULL) {\r
+      DEBUG((\r
+        EFI_D_INFO,\r
+        "Found Mass Storage device: %s\n",\r
+        DevPathStr\r
+        ));\r
+      FreePool(DevPathStr);\r
+    }\r
+\r
+    Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This notification function is invoked when the\r
+  EMU Variable FVB has been changed.\r
+\r
+  @param  Event                 The event that occured\r
+  @param  Context               For EFI compatiblity.  Not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EmuVariablesUpdatedCallback (\r
+  IN  EFI_EVENT Event,\r
+  IN  VOID      *Context\r
+  )\r
+{\r
+  DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));\r
+  UpdateNvVarsOnFileSystem ();\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VisitingFileSystemInstance (\r
+  IN EFI_HANDLE  Handle,\r
+  IN VOID        *Instance,\r
+  IN VOID        *Context\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  STATIC BOOLEAN  ConnectedToFileSystem = FALSE;\r
+\r
+  if (ConnectedToFileSystem) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  Status = ConnectNvVarsToFileSystem (Handle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  ConnectedToFileSystem = TRUE;\r
+  mEmuVariableEvent =\r
+    EfiCreateProtocolNotifyEvent (\r
+      &gEfiDevicePathProtocolGuid,\r
+      TPL_CALLBACK,\r
+      EmuVariablesUpdatedCallback,\r
+      NULL,\r
+      &mEmuVariableEventReg\r
+      );\r
+  PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+VOID\r
+PlatformBdsRestoreNvVarsFromHardDisk (\r
+  )\r
+{\r
+  VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);\r
+  VisitAllInstancesOfProtocol (\r
+    &gEfiSimpleFileSystemProtocolGuid,\r
+    VisitingFileSystemInstance,\r
+    NULL\r
+    );\r
+\r
+}\r
+\r
+\r
+VOID\r
+PlatformBdsConnectSequence (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Connect with predeined 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
+\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r
+\r
+  Index = 0;\r
+\r
+  //\r
+  // Here we can get the customized platform connect sequence\r
+  // Notes: we can connect with new variable which record the\r
+  // last time boots connect device path sequence\r
+  //\r
+  while (gPlatformConnectSequence[Index] != NULL) {\r
+    //\r
+    // Build the platform boot option\r
+    //\r
+    BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);\r
+    Index++;\r
+  }\r
+\r
+  //\r
+  // Just use the simple policy to connect all devices\r
+  //\r
+  BdsLibConnectAll ();\r
+\r
+  PciAcpiInitialization ();\r
+\r
+  //\r
+  // Clear the logo after all devices are connected.\r
+  //\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+}\r
+\r
+VOID\r
+PlatformBdsGetDriverOption (\r
+  IN OUT LIST_ENTRY              *BdsDriverLists\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Load the predefined driver option, OEM/IBV can customize this\r
+  to load their own drivers\r
+\r
+Arguments:\r
+\r
+  BdsDriverLists  - The header of the driver option link list.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));\r
+  return;\r
+}\r
+\r
+VOID\r
+PlatformBdsDiagnostics (\r
+  IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,\r
+  IN BOOLEAN                     QuietBoot,\r
+  IN BASEM_MEMORY_TEST           BaseMemoryTest\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Perform the platform diagnostic, such like test memory. OEM/IBV also\r
+  can customize this fuction to support specific platform diagnostic.\r
+\r
+Arguments:\r
+\r
+  MemoryTestLevel  - The memory test intensive level\r
+\r
+  QuietBoot        - Indicate if need to enable the quiet boot\r
+\r
+  BaseMemoryTest   - A pointer to BaseMemoryTest()\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));\r
+\r
+  //\r
+  // Here we can decide if we need to show\r
+  // the diagnostics screen\r
+  // Notes: this quiet boot code should be remove\r
+  // from the graphic lib\r
+  //\r
+  if (QuietBoot) {\r
+    EnableQuietBoot (PcdGetPtr(PcdLogoFile));\r
+    //\r
+    // Perform system diagnostic\r
+    //\r
+    Status = BaseMemoryTest (MemoryTestLevel);\r
+    if (EFI_ERROR (Status)) {\r
+      DisableQuietBoot ();\r
+    }\r
+\r
+    return ;\r
+  }\r
+  //\r
+  // Perform system diagnostic\r
+  //\r
+  Status = BaseMemoryTest (MemoryTestLevel);\r
+}\r
+\r
+\r
+/**\r
+  Save the S3 boot script.\r
+\r
+  Note that DxeSmmReadyToLock must be signaled after this function returns;\r
+  otherwise the script wouldn't be saved actually.\r
+**/\r
+STATIC\r
+VOID\r
+SaveS3BootScript (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_S3_SAVE_STATE_PROTOCOL *BootScript;\r
+  STATIC CONST UINT8         Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };\r
+\r
+  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,\r
+                  (VOID **) &BootScript);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Despite the opcode documentation in the PI spec, the protocol\r
+  // implementation embeds a deep copy of the info in the boot script, rather\r
+  // than storing just a pointer to runtime or NVS storage.\r
+  //\r
+  Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,\r
+                         (UINT32) sizeof Info,\r
+                         (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+VOID\r
+EFIAPI\r
+PlatformBdsPolicyBehavior (\r
+  IN OUT LIST_ENTRY                  *DriverOptionList,\r
+  IN OUT LIST_ENTRY                  *BootOptionList,\r
+  IN PROCESS_CAPSULES                ProcessCapsules,\r
+  IN BASEM_MEMORY_TEST               BaseMemoryTest\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The function will excute 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
+Arguments:\r
+\r
+  DriverOptionList - The header of the driver option link list\r
+\r
+  BootOptionList   - The header of the boot option link list\r
+\r
+  ProcessCapsules  - A pointer to ProcessCapsules()\r
+\r
+  BaseMemoryTest   - A pointer to BaseMemoryTest()\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                         Status;\r
+  EFI_BOOT_MODE                      BootMode;\r
+\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));\r
+\r
+  if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {\r
+    DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
+      "from disk since flash variables appear to be supported.\n"));\r
+  } else {\r
+    //\r
+    // Try to restore variables from the hard disk early so\r
+    // they can be used for the other BDS connect operations.\r
+    //\r
+    PlatformBdsRestoreNvVarsFromHardDisk ();\r
+  }\r
+\r
+  //\r
+  // Load the driver option as the driver option list\r
+  //\r
+  PlatformBdsGetDriverOption (DriverOptionList);\r
+\r
+  //\r
+  // Get current Boot Mode\r
+  //\r
+  Status = BdsLibGetBootMode (&BootMode);\r
+  DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));\r
+\r
+  //\r
+  // Go the different platform policy with different boot mode\r
+  // Notes: this part code can be change with the table policy\r
+  //\r
+  ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
+  //\r
+  // Connect platform console\r
+  //\r
+  Status = PlatformBdsConnectConsole (gPlatformConsole);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Here OEM/IBV can customize with defined action\r
+    //\r
+    PlatformBdsNoConsoleAction ();\r
+  }\r
+\r
+  //\r
+  // Memory test and Logo show\r
+  //\r
+  PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);\r
+\r
+  //\r
+  // Perform some platform specific connect sequence\r
+  //\r
+  PlatformBdsConnectSequence ();\r
+\r
+  //\r
+  // Process QEMU's -kernel command line option\r
+  //\r
+  TryRunningQemuKernel ();\r
+\r
+  DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));\r
+  BdsLibConnectAll ();\r
+  BdsLibEnumerateAllBootOption (BootOptionList);\r
+\r
+  SetBootOrderFromQemu (BootOptionList);\r
+  //\r
+  // The BootOrder variable may have changed, reload the in-memory list with\r
+  // it.\r
+  //\r
+  BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
+\r
+  PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+PlatformBdsBootSuccess (\r
+  IN  BDS_COMMON_OPTION   *Option\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Hook point after a boot attempt succeeds. We don't expect a boot option to\r
+  return, so the EFI 1.0 specification defines that you will default to an\r
+  interactive mode and stop processing the BootOrder list in this case. This\r
+  is alos a platform implementation and can be customized by IBV/OEM.\r
+\r
+Arguments:\r
+\r
+  Option - Pointer to Boot Option that succeeded to boot.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  CHAR16  *TmpStr;\r
+\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));\r
+  //\r
+  // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
+  // select loop then we need to pop up a UI and wait for user input.\r
+  //\r
+  TmpStr = Option->StatusString;\r
+  if (TmpStr != NULL) {\r
+    BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
+    FreePool (TmpStr);\r
+  }\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+PlatformBdsBootFail (\r
+  IN  BDS_COMMON_OPTION  *Option,\r
+  IN  EFI_STATUS         Status,\r
+  IN  CHAR16             *ExitData,\r
+  IN  UINTN              ExitDataSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Hook point after a boot attempt fails.\r
+\r
+Arguments:\r
+\r
+  Option - Pointer to Boot Option that failed to boot.\r
+\r
+  Status - Status returned from failed boot.\r
+\r
+  ExitData - Exit data returned from failed boot.\r
+\r
+  ExitDataSize - Exit data size returned from failed boot.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  CHAR16  *TmpStr;\r
+\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));\r
+\r
+  //\r
+  // If Boot returned with failed status then we need to pop up a UI and wait\r
+  // for user input.\r
+  //\r
+  TmpStr = Option->StatusString;\r
+  if (TmpStr != NULL) {\r
+    BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
+    FreePool (TmpStr);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsNoConsoleAction (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is remained for IBV/OEM to do some platform action,\r
+  if there no console device can be connected.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS      - Direct return success now.\r
+\r
+--*/\r
+{\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+PlatformBdsLockNonUpdatableFlash (\r
+  VOID\r
+  )\r
+{\r
+  DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));\r
+  return;\r
+}\r
+\r
+\r
+/**\r
+  This notification function is invoked when an instance of the\r
+  EFI_DEVICE_PATH_PROTOCOL is produced.\r
+\r
+  @param  Event                 The event that occured\r
+  @param  Context               For EFI compatiblity.  Not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NotifyDevPath (\r
+  IN  EFI_EVENT Event,\r
+  IN  VOID      *Context\r
+  )\r
+{\r
+  EFI_HANDLE                            Handle;\r
+  EFI_STATUS                            Status;\r
+  UINTN                                 BufferSize;\r
+  EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;\r
+  ATAPI_DEVICE_PATH                    *Atapi;\r
+\r
+  //\r
+  // Examine all new handles\r
+  //\r
+  for (;;) {\r
+    //\r
+    // Get the next handle\r
+    //\r
+    BufferSize = sizeof (Handle);\r
+    Status = gBS->LocateHandle (\r
+              ByRegisterNotify,\r
+              NULL,\r
+              mEfiDevPathNotifyReg,\r
+              &BufferSize,\r
+              &Handle\r
+              );\r
+\r
+    //\r
+    // If not found, we're done\r
+    //\r
+    if (EFI_NOT_FOUND == Status) {\r
+      break;\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Get the DevicePath protocol on that handle\r
+    //\r
+    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    while (!IsDevicePathEnd (DevPathNode)) {\r
+      //\r
+      // Find the handler to dump this device path node\r
+      //\r
+      if (\r
+           (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
+           (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
+         ) {\r
+        Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
+        PciOr16 (\r
+          PCI_LIB_ADDRESS (\r
+            0,\r
+            1,\r
+            1,\r
+            (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
+            ),\r
+          BIT15\r
+          );\r
+      }\r
+\r
+      //\r
+      // Next device path node\r
+      //\r
+      DevPathNode = NextDevicePathNode (DevPathNode);\r
+    }\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+\r
+VOID\r
+InstallDevicePathCallback (\r
+  VOID\r
+  )\r
+{\r
+  DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
+  mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
+                          &gEfiDevicePathProtocolGuid,\r
+                          TPL_CALLBACK,\r
+                          NotifyDevPath,\r
+                          NULL,\r
+                          &mEfiDevPathNotifyReg\r
+                          );\r
+}\r
+\r
+/**\r
+  Lock the ConsoleIn device in system table. All key\r
+  presses will be ignored until the Password is typed in. The only way to\r
+  disable the password is to type it in to a ConIn device.\r
+\r
+  @param  Password        Password used to lock ConIn device.\r
+\r
+  @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.\r
+  @retval EFI_UNSUPPORTED Password not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LockKeyboards (\r
+  IN  CHAR16    *Password\r
+  )\r
+{\r
+    return EFI_UNSUPPORTED;\r
+}\r
+\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h
new file mode 100644 (file)
index 0000000..d6ff316
--- /dev/null
@@ -0,0 +1,292 @@
+/** @file\r
+  Platform BDS customizations include file.\r
+\r
+  Copyright (c) 2006 - 2007, 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
+\r
+Module Name:\r
+\r
+  BdsPlatform.h\r
+\r
+Abstract:\r
+\r
+  Head file for BDS Platform specific code\r
+\r
+**/\r
+\r
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/SmBios.h>\r
+#include <IndustryStandard/PeImage.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/NvVarsFileLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+\r
+#include <Protocol/Decompress.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/S3SaveState.h>\r
+#include <Protocol/DxeSmmReadyToLock.h>\r
+\r
+#include <Guid/Acpi.h>\r
+#include <Guid/SmBios.h>\r
+#include <Guid/Mps.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <OvmfPlatforms.h>\r
+\r
+extern BDS_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];\r
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];\r
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformDriverOption[];\r
+extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;\r
+extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;\r
+extern UART_DEVICE_PATH           gUartDeviceNode;\r
+extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;\r
+//\r
+//\r
+//\r
+#define VarConsoleInpDev        L"ConInDev"\r
+#define VarConsoleInp           L"ConIn"\r
+#define VarConsoleOutDev        L"ConOutDev"\r
+#define VarConsoleOut           L"ConOut"\r
+#define VarErrorOutDev          L"ErrOutDev"\r
+#define VarErrorOut             L"ErrOut"\r
+\r
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \\r
+  { \\r
+    { \\r
+      HARDWARE_DEVICE_PATH, \\r
+      HW_PCI_DP, \\r
+      { \\r
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \\r
+      } \\r
+    }, \\r
+    (Func), \\r
+    (Dev) \\r
+  }\r
+\r
+#define PNPID_DEVICE_PATH_NODE(PnpId) \\r
+  { \\r
+    { \\r
+      ACPI_DEVICE_PATH, \\r
+      ACPI_DP, \\r
+      { \\r
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \\r
+      }, \\r
+    }, \\r
+    EISA_PNP_ID((PnpId)), \\r
+    0 \\r
+  }\r
+\r
+#define gPciIsaBridge \\r
+  PCI_DEVICE_PATH_NODE(0, 0x1f)\r
+\r
+#define gP2PBridge \\r
+  PCI_DEVICE_PATH_NODE(0, 0x1e)\r
+\r
+#define gPnpPs2Keyboard \\r
+  PNPID_DEVICE_PATH_NODE(0x0303)\r
+\r
+#define gPnp16550ComPort \\r
+  PNPID_DEVICE_PATH_NODE(0x0501)\r
+\r
+#define gUart \\r
+  { \\r
+    { \\r
+      MESSAGING_DEVICE_PATH, \\r
+      MSG_UART_DP, \\r
+      { \\r
+        (UINT8) (sizeof (UART_DEVICE_PATH)), \\r
+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \\r
+      } \\r
+    }, \\r
+    0, \\r
+    115200, \\r
+    8, \\r
+    1, \\r
+    1 \\r
+  }\r
+\r
+#define gPcAnsiTerminal \\r
+  { \\r
+    { \\r
+      MESSAGING_DEVICE_PATH, \\r
+      MSG_VENDOR_DP, \\r
+      { \\r
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \\r
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \\r
+      } \\r
+    }, \\r
+    DEVICE_PATH_MESSAGING_PC_ANSI \\r
+  }\r
+\r
+#define PCI_CLASS_SCC          0x07\r
+#define PCI_SUBCLASS_SERIAL    0x00\r
+#define PCI_IF_16550           0x02\r
+#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)\r
+\r
+#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF\r
+#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )\r
+\r
+#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)\r
+\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      PciRootBridge;\r
+  PCI_DEVICE_PATH           IsaBridge;\r
+  ACPI_HID_DEVICE_PATH      Keyboard;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      PciRootBridge;\r
+  PCI_DEVICE_PATH           IsaBridge;\r
+  ACPI_HID_DEVICE_PATH      IsaSerial;\r
+  UART_DEVICE_PATH          Uart;\r
+  VENDOR_DEVICE_PATH        TerminalType;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      PciRootBridge;\r
+  PCI_DEVICE_PATH           VgaDevice;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      PciRootBridge;\r
+  PCI_DEVICE_PATH           PciBridge;\r
+  PCI_DEVICE_PATH           SerialDevice;\r
+  UART_DEVICE_PATH          Uart;\r
+  VENDOR_DEVICE_PATH        TerminalType;\r
+  EFI_DEVICE_PATH_PROTOCOL  End;\r
+} PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH;\r
+\r
+//\r
+// the short form device path for Usb keyboard\r
+//\r
+#define CLASS_HID           3\r
+#define SUBCLASS_BOOT       1\r
+#define PROTOCOL_KEYBOARD   1\r
+\r
+typedef struct {\r
+  USB_CLASS_DEVICE_PATH           UsbClass;\r
+  EFI_DEVICE_PATH_PROTOCOL        End;\r
+} USB_CLASS_FORMAT_DEVICE_PATH;\r
+\r
+//\r
+// Platform BDS Functions\r
+//\r
+\r
+VOID\r
+PlatformBdsGetDriverOption (\r
+  IN LIST_ENTRY               *BdsDriverLists\r
+  );\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+  EXTENDMEM_COVERAGE_LEVEL Level\r
+  );\r
+\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  CHAR16                        *Title,\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  UINTN                         Progress,\r
+  UINTN                         PreviousValue\r
+  );\r
+\r
+VOID\r
+PlatformBdsConnectSequence (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+ProcessCapsules (\r
+  EFI_BOOT_MODE BootMode\r
+  );\r
+\r
+EFI_STATUS\r
+PlatformBdsConnectConsole (\r
+  IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole\r
+  );\r
+\r
+EFI_STATUS\r
+PlatformBdsNoConsoleAction (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+ConvertMpsTable (\r
+  IN OUT  VOID     **Table\r
+  );\r
+\r
+EFI_STATUS\r
+ConvertSmbiosTable (\r
+  IN OUT VOID       **Table\r
+  );\r
+\r
+EFI_STATUS\r
+ConvertAcpiTable (\r
+ IN      UINTN      TableLen,\r
+ IN OUT  VOID       **Table\r
+  );\r
+\r
+EFI_STATUS\r
+ConvertSystemTable (\r
+ IN     EFI_GUID   *TableGuid,\r
+ IN OUT VOID       **Table\r
+  );\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                 TimeoutDefault,\r
+  IN BOOLEAN                ConnectAllHappened\r
+  );\r
+\r
+/**\r
+  Loads and boots UEFI Linux via the FwCfg interface.\r
+\r
+  @retval    EFI_NOT_FOUND - The Linux kernel was not found\r
+\r
+**/\r
+EFI_STATUS\r
+TryRunningQemuKernel (\r
+  VOID\r
+  );\r
+\r
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBdsLib.inf b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBdsLib.inf
new file mode 100644 (file)
index 0000000..239d50f
--- /dev/null
@@ -0,0 +1,73 @@
+## @file\r
+#  Platform BDS customizations library.\r
+#\r
+#  Copyright (c) 2007 - 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
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PlatformBdsLib\r
+  FILE_GUID                      = FB65006C-AC9F-4992-AD80-184B2BDBBD83\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = PlatformBdsLib|DXE_DRIVER\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  BdsPlatform.c\r
+  PlatformData.c\r
+  QemuKernel.c\r
+  BdsPlatform.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PcdLib\r
+  GenericBdsLib\r
+  PciLib\r
+  NvVarsFileLib\r
+  QemuFwCfgLib\r
+  LoadLinuxLib\r
+  QemuBootOrderLib\r
+  UefiLib\r
+\r
+[Pcd]\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId\r
+\r
+[Pcd.IA32, Pcd.X64]\r
+  gEfiMdePkgTokenSpaceGuid.PcdFSBClock\r
+\r
+[Protocols]\r
+  gEfiDecompressProtocolGuid\r
+  gEfiPciRootBridgeIoProtocolGuid\r
+  gEfiS3SaveStateProtocolGuid                   # PROTOCOL SOMETIMES_CONSUMED\r
+  gEfiDxeSmmReadyToLockProtocolGuid             # PROTOCOL SOMETIMES_PRODUCED\r
+\r
+[Guids]\r
+  gEfiEndOfDxeEventGroupGuid\r
+  gRootBridgesConnectedEventGroupGuid\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/PlatformData.c b/OvmfPkg/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100644 (file)
index 0000000..f69c1a8
--- /dev/null
@@ -0,0 +1,51 @@
+/** @file\r
+  Defined the platform specific device path which will be used by\r
+  platform Bbd to perform the platform policy connect.\r
+\r
+  Copyright (c) 2004 - 2008, 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
+\r
+**/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+//\r
+// Predefined platform default time out value\r
+//\r
+UINT16                      gPlatformBootTimeOutDefault = 5;\r
+\r
+ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  = gPnpPs2Keyboard;\r
+ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode = gPnp16550ComPort;\r
+UART_DEVICE_PATH           gUartDeviceNode            = gUart;\r
+VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    = gPcAnsiTerminal;\r
+\r
+//\r
+// Platform specific keyboard device path\r
+//\r
+\r
+//\r
+// Predefined platform default console device path\r
+//\r
+BDS_CONSOLE_CONNECT_ENTRY   gPlatformConsole[] = {\r
+  {\r
+    NULL,\r
+    0\r
+  }\r
+};\r
+\r
+//\r
+// Predefined platform specific driver option\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL    *gPlatformDriverOption[] = { NULL };\r
+\r
+//\r
+// Predefined platform connect sequence\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };\r
+\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/QemuKernel.c b/OvmfPkg/Library/PlatformBootManagerLib/QemuKernel.c
new file mode 100644 (file)
index 0000000..ef728df
--- /dev/null
@@ -0,0 +1,170 @@
+/** @file\r
+\r
+  Copyright (c) 2006 - 2015, 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
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/LoadLinuxLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+\r
+EFI_STATUS\r
+TryRunningQemuKernel (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     KernelSize;\r
+  UINTN                     KernelInitialSize;\r
+  VOID                      *KernelBuf;\r
+  UINTN                     SetupSize;\r
+  VOID                      *SetupBuf;\r
+  UINTN                     CommandLineSize;\r
+  CHAR8                     *CommandLine;\r
+  UINTN                     InitrdSize;\r
+  VOID*                     InitrdData;\r
+\r
+  SetupBuf = NULL;\r
+  SetupSize = 0;\r
+  KernelBuf = NULL;\r
+  KernelInitialSize = 0;\r
+  CommandLine = NULL;\r
+  CommandLineSize = 0;\r
+  InitrdData = NULL;\r
+  InitrdSize = 0;\r
+\r
+  if (!QemuFwCfgIsAvailable ()) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  QemuFwCfgSelectItem (QemuFwCfgItemKernelSize);\r
+  KernelSize = (UINTN) QemuFwCfgRead64 ();\r
+\r
+  QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize);\r
+  SetupSize = (UINTN) QemuFwCfgRead64 ();\r
+\r
+  if (KernelSize == 0 || SetupSize == 0) {\r
+    DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n"));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES (SetupSize));\r
+  if (SetupBuf == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel setup!\n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize));\r
+  DEBUG ((EFI_D_INFO, "Reading kernel setup image ..."));\r
+  QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData);\r
+  QemuFwCfgReadBytes (SetupSize, SetupBuf);\r
+  DEBUG ((EFI_D_INFO, " [done]\n"));\r
+\r
+  Status = LoadLinuxCheckKernelSetup (SetupBuf, SetupSize);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeAndReturn;\r
+  }\r
+\r
+  Status = LoadLinuxInitializeKernelSetup (SetupBuf);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeAndReturn;\r
+  }\r
+\r
+  KernelInitialSize = LoadLinuxGetKernelSize (SetupBuf, KernelSize);\r
+  if (KernelInitialSize == 0) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto FreeAndReturn;\r
+  }\r
+\r
+  KernelBuf = LoadLinuxAllocateKernelPages (\r
+                SetupBuf,\r
+                EFI_SIZE_TO_PAGES (KernelInitialSize));\r
+  if (KernelBuf == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel!\n"));\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeAndReturn;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "Kernel size: 0x%x\n", (UINT32) KernelSize));\r
+  DEBUG ((EFI_D_INFO, "Reading kernel image ..."));\r
+  QemuFwCfgSelectItem (QemuFwCfgItemKernelData);\r
+  QemuFwCfgReadBytes (KernelSize, KernelBuf);\r
+  DEBUG ((EFI_D_INFO, " [done]\n"));\r
+\r
+  QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);\r
+  CommandLineSize = (UINTN) QemuFwCfgRead64 ();\r
+\r
+  if (CommandLineSize > 0) {\r
+    CommandLine = LoadLinuxAllocateCommandLinePages (\r
+                    EFI_SIZE_TO_PAGES (CommandLineSize));\r
+    QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);\r
+    QemuFwCfgReadBytes (CommandLineSize, CommandLine);\r
+  } else {\r
+    CommandLine = NULL;\r
+  }\r
+\r
+  Status = LoadLinuxSetCommandLine (SetupBuf, CommandLine);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeAndReturn;\r
+  }\r
+\r
+  QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);\r
+  InitrdSize = (UINTN) QemuFwCfgRead64 ();\r
+\r
+  if (InitrdSize > 0) {\r
+    InitrdData = LoadLinuxAllocateInitrdPages (\r
+                   SetupBuf,\r
+                   EFI_SIZE_TO_PAGES (InitrdSize)\r
+                   );\r
+    DEBUG ((EFI_D_INFO, "Initrd size: 0x%x\n", (UINT32) InitrdSize));\r
+    DEBUG ((EFI_D_INFO, "Reading initrd image ..."));\r
+    QemuFwCfgSelectItem (QemuFwCfgItemInitrdData);\r
+    QemuFwCfgReadBytes (InitrdSize, InitrdData);\r
+    DEBUG ((EFI_D_INFO, " [done]\n"));\r
+  } else {\r
+    InitrdData = NULL;\r
+  }\r
+\r
+  Status = LoadLinuxSetInitrd (SetupBuf, InitrdData, InitrdSize);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeAndReturn;\r
+  }\r
+\r
+  //\r
+  // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
+  //\r
+  EfiSignalEventReadyToBoot();\r
+\r
+  Status = LoadLinux (KernelBuf, SetupBuf);\r
+\r
+FreeAndReturn:\r
+  if (SetupBuf != NULL) {\r
+    FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize));\r
+  }\r
+  if (KernelBuf != NULL) {\r
+    FreePages (KernelBuf, EFI_SIZE_TO_PAGES (KernelInitialSize));\r
+  }\r
+  if (CommandLine != NULL) {\r
+    FreePages (CommandLine, EFI_SIZE_TO_PAGES (CommandLineSize));\r
+  }\r
+  if (InitrdData != NULL) {\r
+    FreePages (InitrdData, EFI_SIZE_TO_PAGES (InitrdSize));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r