[edk2-devel] [edk2-platforms] [PATCH 09/11] SimicsOpenBoardPkg: Add Bds Hook Library

Agyeman, Prince posted 11 patches 4 years, 11 months ago
[edk2-devel] [edk2-platforms] [PATCH 09/11] SimicsOpenBoardPkg: Add Bds Hook Library
Posted by Agyeman, Prince 4 years, 11 months ago
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2336

Added Board BDS Hook library that implements simics specific
Bds hook points or callbacks.

Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael Kubacki <michael.a.kubacki@intel.com>

Signed-off-by: Prince Agyeman <prince.agyeman@intel.com>
---
 .../Library/BoardBdsHookLib/BoardBdsHook.h    |  173 ++
 .../Library/BoardBdsHookLib/BoardBdsHookLib.c | 1630 +++++++++++++++++
 .../BoardBdsHookLib/BoardBdsHookLib.inf       |   81 +
 3 files changed, 1884 insertions(+)
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf

diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
new file mode 100644
index 0000000000..fda41b1c97
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
@@ -0,0 +1,173 @@
+/** @file
+  Header file for the board board specific BDS hook library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/PeImage.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/NvVarsFileLib.h>
+#include <Library/BoardBdsHookLib.h>
+
+#include <Protocol/Decompress.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/S3SaveState.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Guid/Acpi.h>
+#include <Guid/SmBios.h>
+#include <Guid/Mps.h>
+#include <Guid/HobList.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+
+#include <SimicsPlatforms.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];
+extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH           gUartDeviceNode;
+extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+  { \
+    { \
+      HARDWARE_DEVICE_PATH, \
+      HW_PCI_DP, \
+      { \
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    (Func), \
+    (Dev) \
+  }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    EISA_PNP_ID((PnpId)), \
+    0 \
+  }
+
+#define gPciIsaBridge \
+  PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+  PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+  PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+  PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_UART_DP, \
+      { \
+        (UINT8) (sizeof (UART_DEVICE_PATH)), \
+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    0, \
+    115200, \
+    8, \
+    1, \
+    1 \
+  }
+
+#define gPcAnsiTerminal \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_VENDOR_DP, \
+      { \
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    DEVICE_PATH_MESSAGING_PC_ANSI \
+  }
+
+#define PCI_CLASS_SCC          0x07
+#define PCI_SUBCLASS_SERIAL    0x00
+#define PCI_IF_16550           0x02
+#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN  BIT1
+#define STD_ERROR   BIT2
+extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformInitializeConsole (
+  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
+  );
+
+/**
+  Use SystemTable ConOut to stop video based Simple Text Out consoles from going
+  to the video device. Put up LogoFile on every video device that is a console.
+
+  @param[in]  LogoFile   The file name of logo to display on the center of the screen.
+
+  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and logo displayed.
+  @retval EFI_UNSUPPORTED Logo not found.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableBootLogo(
+  IN  EFI_GUID  *LogoFile
+);
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
new file mode 100644
index 0000000000..1058dbf3cf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
@@ -0,0 +1,1630 @@
+/** @file
+  Board BDS hook Library. Implements board specific BDS hook library
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "BoardBdsHook.h"
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#define LEGACY_8259_MASK_REGISTER_MASTER                  0x21
+#define LEGACY_8259_MASK_REGISTER_SLAVE                   0xA1
+#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER  0x4D0
+#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE   0x4D1
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };
+
+
+ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH           gUartDeviceNode            = gUart;
+VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    = gPcAnsiTerminal;
+
+//
+// Global data
+//
+
+VOID          *mEfiDevPathNotifyReg;
+EFI_EVENT     mEfiDevPathEvent;
+VOID          *mEmuVariableEventReg;
+EFI_EVENT     mEmuVariableEvent;
+BOOLEAN       mDetectVgaOnly;
+UINT16        mHostBridgeDevId;
+
+//
+// Table of host IRQs matching PCI IRQs A-D
+// (for configuring PCI Interrupt Line register)
+//
+CONST UINT8 PciHostIrqs[] = {
+  0x0a, 0x0a, 0x0b, 0x0b
+};
+
+//
+// Type definitions
+//
+typedef
+EFI_STATUS
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
+  IN EFI_HANDLE           Handle,
+  IN VOID                 *Instance,
+  IN VOID                 *Context
+  );
+
+/**
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *Pci
+  );
+
+
+//
+// Function prototypes
+//
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+  IN EFI_GUID                    *Id,
+  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
+  IN VOID                        *Context
+  );
+
+EFI_STATUS
+VisitAllPciInstancesOfProtocol (
+  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+  );
+
+VOID
+InstallDevicePathCallback (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+  IN EFI_HANDLE  RootBridgeHandle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  );
+
+
+VOID
+PlatformRegisterFvBootOption (
+  EFI_GUID                         *FileGuid,
+  CHAR16                           *Description,
+  UINT32                           Attributes
+  )
+{
+  EFI_STATUS                        Status;
+  INTN                              OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
+  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
+  UINTN                             BootOptionCount;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID **) &LoadedImage
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+  DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+  ASSERT (DevicePath != NULL);
+  DevicePath = AppendDevicePathNode (
+                 DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+                 );
+  ASSERT (DevicePath != NULL);
+
+  Status = EfiBootManagerInitializeLoadOption (
+             &NewOption,
+             LoadOptionNumberUnassigned,
+             LoadOptionTypeBoot,
+             Attributes,
+             Description,
+             DevicePath,
+             NULL,
+             0
+             );
+  ASSERT_EFI_ERROR (Status);
+  FreePool (DevicePath);
+
+  BootOptions = EfiBootManagerGetLoadOptions (
+                  &BootOptionCount, LoadOptionTypeBoot
+                  );
+
+  OptionIndex = EfiBootManagerFindLoadOption (
+                  &NewOption, BootOptions, BootOptionCount
+                  );
+
+  if (OptionIndex == -1) {
+    Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
+    ASSERT_EFI_ERROR (Status);
+  }
+  EfiBootManagerFreeLoadOption (&NewOption);
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+/**
+  Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
+  whose device paths do not resolve exactly to an FvFile in the system.
+
+  This removes any boot options that point to binaries built into the firmware
+  and have become stale due to any of the following:
+  - DXEFV's base address or size changed (historical),
+  - DXEFV's FvNameGuid changed,
+  - the FILE_GUID of the pointed-to binary changed,
+  - the referenced binary is no longer built into the firmware.
+
+  EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
+  avoids exact duplicates.
+**/
+VOID
+RemoveStaleFvFileOptions (
+  VOID
+  )
+{
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+  UINTN                        BootOptionCount;
+  UINTN                        Index;
+
+  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
+                  LoadOptionTypeBoot);
+
+  for (Index = 0; Index < BootOptionCount; ++Index) {
+    EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+    EFI_STATUS               Status;
+    EFI_HANDLE               FvHandle;
+
+    //
+    // If the device path starts with neither MemoryMapped(...) nor Fv(...),
+    // then keep the boot option.
+    //
+    Node1 = BootOptions[Index].FilePath;
+    if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
+          DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
+        !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
+          DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+      continue;
+    }
+
+    //
+    // If the second device path node is not FvFile(...), then keep the boot
+    // option.
+    //
+    Node2 = NextDevicePathNode (Node1);
+    if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+      continue;
+    }
+
+    //
+    // Locate the Firmware Volume2 protocol instance that is denoted by the
+    // boot option. If this lookup fails (i.e., the boot option references a
+    // firmware volume that doesn't exist), then we'll proceed to delete the
+    // boot option.
+    //
+    SearchNode = Node1;
+    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
+                    &SearchNode, &FvHandle);
+
+    if (!EFI_ERROR (Status)) {
+      //
+      // The firmware volume was found; now let's see if it contains the FvFile
+      // identified by GUID.
+      //
+      EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol;
+      MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+      UINTN                             BufferSize;
+      EFI_FV_FILETYPE                   FoundType;
+      EFI_FV_FILE_ATTRIBUTES            FileAttributes;
+      UINT32                            AuthenticationStatus;
+
+      Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
+                      (VOID **)&FvProtocol);
+      ASSERT_EFI_ERROR (Status);
+
+      FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
+      //
+      // Buffer==NULL means we request metadata only: BufferSize, FoundType,
+      // FileAttributes.
+      //
+      Status = FvProtocol->ReadFile (
+                             FvProtocol,
+                             &FvFileNode->FvFileName, // NameGuid
+                             NULL,                    // Buffer
+                             &BufferSize,
+                             &FoundType,
+                             &FileAttributes,
+                             &AuthenticationStatus
+                             );
+      if (!EFI_ERROR (Status)) {
+        //
+        // The FvFile was found. Keep the boot option.
+        //
+        continue;
+      }
+    }
+
+    //
+    // Delete the boot option.
+    //
+    Status = EfiBootManagerDeleteLoadOptionVariable (
+               BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+    DEBUG_CODE (
+      CHAR16 *DevicePathString;
+
+      DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
+                           FALSE, FALSE);
+      DEBUG ((
+        EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,
+        "%a: removing stale Boot#%04x %s: %r\n",
+        __FUNCTION__,
+        (UINT32)BootOptions[Index].OptionNumber,
+        DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+        Status
+        ));
+      if (DevicePathString != NULL) {
+        FreePool (DevicePathString);
+      }
+      );
+  }
+
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+VOID
+PlatformRegisterOptionsAndKeys (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_INPUT_KEY                Enter;
+  EFI_INPUT_KEY                F2;
+  EFI_INPUT_KEY                Esc;
+  EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+
+  //
+  // Register ENTER as CONTINUE key
+  //
+  Enter.ScanCode    = SCAN_NULL;
+  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+  Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+  ASSERT_EFI_ERROR (Status);
+  DEBUG ((DEBUG_INFO, "PlatformRegisterOptionsAndKeys\n"));
+  if (EFI_ERROR(Status)){
+    return;
+  }
+  //
+  // Map F2 to Boot Manager Menu
+  //
+  F2.ScanCode     = SCAN_F2;
+  F2.UnicodeChar  = CHAR_NULL;
+  Esc.ScanCode    = SCAN_ESC;
+  Esc.UnicodeChar = CHAR_NULL;
+  Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+  ASSERT_EFI_ERROR (Status);
+  Status = EfiBootManagerAddKeyOptionVariable (
+             NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
+             );
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+  Status = EfiBootManagerAddKeyOptionVariable (
+             NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
+             );
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+}
+
+
+/**
+  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+  @param[in] DeviceHandle  Handle of the LPC Bridge device.
+
+  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added to
+                       ConOut, ConIn, and ErrOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+  IN EFI_HANDLE  RootBridgeHandle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Make the PCI bus driver connect the root bridge, non-recursively. This
+  // will produce a number of child handles with PciIo on them.
+  //
+  Status = gBS->ConnectController (
+                  RootBridgeHandle, // ControllerHandle
+                  NULL,             // DriverImageHandle
+                  NULL,             // RemainingDevicePath -- produce all
+                                    //   children
+                  FALSE             // Recursive
+                  );
+  return Status;
+}
+
+
+/**
+  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+  @param[in] DeviceHandle  Handle of the LPC Bridge device.
+
+  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added to
+                       ConOut, ConIn, and ErrOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  CHAR16                    *DevPathStr;
+
+  DevicePath = NULL;
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID*)&DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  TempDevicePath = DevicePath;
+
+  //
+  // Register Keyboard
+  //
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+
+  //
+  // Register COM1
+  //
+  DevicePath = TempDevicePath;
+  gPnp16550ComPortDeviceNode.UID = 0;
+
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+  //
+  // Print Device Path
+  //
+  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+  if (DevPathStr != NULL) {
+    DEBUG((
+      DEBUG_INFO,
+      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+      __LINE__,
+      gPnp16550ComPortDeviceNode.UID + 1,
+      DevPathStr
+      ));
+    FreePool(DevPathStr);
+  }
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+  //
+  // Register COM2
+  //
+  DevicePath = TempDevicePath;
+  gPnp16550ComPortDeviceNode.UID = 1;
+
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+  //
+  // Print Device Path
+  //
+  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+  if (DevPathStr != NULL) {
+    DEBUG((
+      DEBUG_INFO,
+      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+      __LINE__,
+      gPnp16550ComPortDeviceNode.UID + 1,
+      DevPathStr
+      ));
+    FreePool(DevPathStr);
+  }
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetGopDevicePath (
+   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+   )
+{
+  UINTN                           Index;
+  EFI_STATUS                      Status;
+  EFI_HANDLE                      PciDeviceHandle;
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
+  UINTN                           GopHandleCount;
+  EFI_HANDLE                      *GopHandleBuffer;
+
+  if (PciDevicePath == NULL || GopDevicePath == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Initialize the GopDevicePath to be PciDevicePath
+  //
+  *GopDevicePath    = PciDevicePath;
+  TempPciDevicePath = PciDevicePath;
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiDevicePathProtocolGuid,
+                  &TempPciDevicePath,
+                  &PciDeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Try to connect this handle, so that GOP driver could start on this
+  // device and create child handles with GraphicsOutput Protocol installed
+  // on them, then we get device paths of these child handles and select
+  // them as possible console device.
+  //
+  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  NULL,
+                  &GopHandleCount,
+                  &GopHandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Add all the child handles as possible Console Device
+    //
+    for (Index = 0; Index < GopHandleCount; Index++) {
+      Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+      if (CompareMem (
+            PciDevicePath,
+            TempDevicePath,
+            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+            ) == 0) {
+        //
+        // In current implementation, we only enable one of the child handles
+        // as console device, i.e. sotre one of the child handle's device
+        // path to variable "ConOut"
+        // In future, we could select all child handles to be console device
+        //
+
+        *GopDevicePath = TempDevicePath;
+
+        //
+        // Delete the PCI device's path that added by
+        // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
+        //
+        EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
+        EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
+      }
+    }
+    gBS->FreePool (GopHandleBuffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add PCI display to ConOut.
+
+  @param[in] DeviceHandle  Handle of the PCI display device.
+
+  @retval EFI_SUCCESS  The PCI display device has been added to ConOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciDisplayDevicePath (
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
+
+  DevicePath    = NULL;
+  GopDevicePath = NULL;
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID*)&DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  GetGopDevicePath (DevicePath, &GopDevicePath);
+  DevicePath = GopDevicePath;
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add PCI Serial to ConOut, ConIn, ErrOut.
+
+  @param[in] DeviceHandle  Handle of the PCI serial device.
+
+  @retval EFI_SUCCESS  The PCI serial device has been added to ConOut, ConIn,
+                       ErrOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciSerialDevicePath (
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  DevicePath = NULL;
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID*)&DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+  IN EFI_GUID                    *Id,
+  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
+  IN VOID                        *Context
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     HandleCount;
+  EFI_HANDLE                *HandleBuffer;
+  UINTN                     Index;
+  VOID                      *Instance;
+
+  //
+  // Start to check all the PciIo to find all possible device
+  //
+  HandleCount = 0;
+  HandleBuffer = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  Id,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    Status = (*CallBackFunction) (
+               HandleBuffer[Index],
+               Instance,
+               Context
+               );
+  }
+
+  gBS->FreePool (HandleBuffer);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingAPciInstance (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  PCI_TYPE00                Pci;
+
+  PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+
+  //
+  // Check for all PCI device
+  //
+  Status = PciIo->Pci.Read (
+                    PciIo,
+                    EfiPciIoWidthUint32,
+                    0,
+                    sizeof (Pci) / sizeof (UINT32),
+                    &Pci
+                    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
+           Handle,
+           PciIo,
+           &Pci
+           );
+
+}
+
+
+
+EFI_STATUS
+VisitAllPciInstances (
+  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+  )
+{
+  return VisitAllInstancesOfProtocol (
+           &gEfiPciIoProtocolGuid,
+           VisitingAPciInstance,
+           (VOID*)(UINTN) CallBackFunction
+           );
+}
+
+
+/**
+  Do platform specific PCI Device check and add them to
+  ConOut, ConIn, ErrOut.
+
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  Pci - PCI Header register block
+
+  @retval EFI_SUCCESS - PCI Device check and Console variable update
+                        successfully.
+  @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *Pci
+  )
+{
+  EFI_STATUS                Status;
+
+  Status = PciIo->Attributes (
+    PciIo,
+    EfiPciIoAttributeOperationEnable,
+    EFI_PCI_DEVICE_ENABLE,
+    NULL
+    );
+  ASSERT_EFI_ERROR (Status);
+
+  if (!mDetectVgaOnly) {
+    //
+    // Here we decide whether it is LPC Bridge
+    //
+    if ((IS_PCI_LPC (Pci)) ||
+        ((IS_PCI_ISA_PDECODE (Pci)) &&
+         (Pci->Hdr.VendorId == 0x8086) &&
+         (Pci->Hdr.DeviceId == 0x7000)
+        )
+       ) {
+      //
+      // Add IsaKeyboard to ConIn,
+      // add IsaSerial to ConOut, ConIn, ErrOut
+      //
+      DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
+      PrepareLpcBridgeDevicePath (Handle);
+      return EFI_SUCCESS;
+    }
+    //
+    // Here we decide which Serial device to enable in PCI bus
+    //
+    if (IS_PCI_16550SERIAL (Pci)) {
+      //
+      // Add them to ConOut, ConIn, ErrOut.
+      //
+      DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
+      PreparePciSerialDevicePath (Handle);
+      return EFI_SUCCESS;
+    }
+  }
+
+  //
+  // Here we decide which display device to enable in PCI bus
+  //
+  if (IS_PCI_DISPLAY (Pci)) {
+    //
+    // Add them to ConOut.
+    //
+    DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
+    PreparePciDisplayDevicePath (Handle);
+    return EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+
+/**
+  Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+
+  @param[in]  DetectVgaOnly - Only detect VGA device if it's TRUE.
+
+  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+  @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+DetectAndPreparePlatformPciDevicePaths (
+  BOOLEAN DetectVgaOnly
+  )
+{
+  mDetectVgaOnly = DetectVgaOnly;
+  return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+}
+
+/**
+  Connect the predefined platform default console device.
+
+  Always try to find and enable PCI display devices.
+
+  @param[in] PlatformConsole  Predefined platform default console device array.
+**/
+VOID
+PlatformInitializeConsole (
+  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
+  )
+{
+  UINTN                              Index;
+  EFI_DEVICE_PATH_PROTOCOL           *VarConout;
+  EFI_DEVICE_PATH_PROTOCOL           *VarConin;
+
+  //
+  // Connect RootBridge
+  //
+  GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
+  GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
+
+  if (VarConout == NULL || VarConin == NULL) {
+    //
+    // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+    //
+    DetectAndPreparePlatformPciDevicePaths (FALSE);
+    DetectAndPreparePlatformPciDevicePaths(TRUE);
+    //
+    // Have chance to connect the platform default console,
+    // the platform default console is the minimue device group
+    // the platform should support
+    //
+    for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+      //
+      // Update the console variable with the connect type
+      //
+      if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+        EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
+      }
+      if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+        EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
+      }
+      if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+        EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
+      }
+    }
+  } else {
+    //
+    // Only detect VGA device and add them to ConOut
+    //
+    DetectAndPreparePlatformPciDevicePaths (TRUE);
+  }
+}
+
+
+/**
+  Configure PCI Interrupt Line register for applicable devices
+  Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
+
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  PciHdr - PCI Header register block
+
+  @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPciIntLine (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *PciHdr
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
+  UINTN                     RootSlot;
+  UINTN                     Idx;
+  UINT8                     IrqLine;
+  EFI_STATUS                Status;
+  UINT32                    RootBusNumber;
+
+  Status = EFI_SUCCESS;
+
+  if (PciHdr->Device.InterruptPin != 0) {
+
+    DevPathNode = DevicePathFromHandle (Handle);
+    ASSERT (DevPathNode != NULL);
+    DevPath = DevPathNode;
+
+    RootBusNumber = 0;
+    if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
+        DevicePathSubType (DevPathNode) == ACPI_DP &&
+        ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+      RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
+    }
+
+    //
+    // Compute index into PciHostIrqs[] table by walking
+    // the device path and adding up all device numbers
+    //
+    Status = EFI_NOT_FOUND;
+    RootSlot = 0;
+    Idx = PciHdr->Device.InterruptPin - 1;
+    while (!IsDevicePathEnd (DevPathNode)) {
+      if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
+          DevicePathSubType (DevPathNode) == HW_PCI_DP) {
+
+        Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+
+        //
+        // Unlike SeaBIOS, which starts climbing from the leaf device
+        // up toward the root, we traverse the device path starting at
+        // the root moving toward the leaf node.
+        // The slot number of the top-level parent bridge is needed
+        // with more than 24 slots on the root bus.
+        //
+        if (Status != EFI_SUCCESS) {
+          Status = EFI_SUCCESS;
+          RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+        }
+      }
+
+      DevPathNode = NextDevicePathNode (DevPathNode);
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    if (RootBusNumber == 0 && RootSlot == 0) {
+      return Status; //bugbug: workaround; need SIMICS change B0/D0/F0 PCI_IntPin reg(0x3D) = 0X0
+//      DEBUG((
+//        DEBUG_ERROR,
+//       "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
+//        __FUNCTION__
+//        ));
+//      ASSERT (FALSE);
+    }
+
+    //
+    // Final PciHostIrqs[] index calculation depends on the platform
+    // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
+    //
+    switch (mHostBridgeDevId) {
+      case INTEL_82441_DEVICE_ID:
+        Idx -= 1;
+        break;
+      case INTEL_ICH10_DEVICE_ID:
+        //
+        // SeaBIOS contains the following comment:
+        // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
+        //  with a different starting index.
+        //
+        //  Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
+        //
+        if (RootSlot > 24) {
+          //
+          // in this case, subtract back out RootSlot from Idx
+          // (SeaBIOS never adds it to begin with, but that would make our
+          //  device path traversal loop above too awkward)
+          //
+          Idx -= RootSlot;
+        }
+        break;
+      default:
+        ASSERT (FALSE); // should never get here
+    }
+    Idx %= ARRAY_SIZE (PciHostIrqs);
+    IrqLine = PciHostIrqs[Idx];
+
+    DEBUG_CODE_BEGIN ();
+    {
+      CHAR16        *DevPathString;
+      STATIC CHAR16 Fallback[] = L"<failed to convert>";
+      UINTN         Segment, Bus, Device, Function;
+
+      DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
+      if (DevPathString == NULL) {
+        DevPathString = Fallback;
+      }
+      Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+      ASSERT_EFI_ERROR (Status);
+
+      DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
+        (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
+        IrqLine));
+
+      if (DevPathString != Fallback) {
+        FreePool (DevPathString);
+      }
+    }
+    DEBUG_CODE_END ();
+
+    //
+    // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
+    //
+    Status = PciIo->Pci.Write (
+               PciIo,
+               EfiPciIoWidthUint8,
+               PCI_INT_LINE_OFFSET,
+               1,
+               &IrqLine
+               );
+  }
+
+  return Status;
+}
+
+/**
+Write to mask and edge/level triggered registers of master and slave 8259 PICs.
+
+@param[in]  Mask       low byte for master PIC mask register,
+high byte for slave PIC mask register.
+@param[in]  EdgeLevel  low byte for master PIC edge/level triggered register,
+high byte for slave PIC edge/level triggered register.
+
+**/
+VOID
+Interrupt8259WriteMask(
+  IN UINT16  Mask,
+  IN UINT16  EdgeLevel
+)
+{
+  IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
+  IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
+  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8)EdgeLevel);
+  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8)(EdgeLevel >> 8));
+}
+
+VOID
+PciAcpiInitialization (
+  VOID
+  )
+{
+  UINTN  Pmba;
+
+  //
+  // Query Host Bridge DID to determine platform type
+  //
+  mHostBridgeDevId = PcdGet16 (PcdSimicsX58HostBridgePciDevId);
+  switch (mHostBridgeDevId) {
+    case INTEL_82441_DEVICE_ID:
+      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+      //
+      // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
+      //
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+      break;
+    case INTEL_ICH10_DEVICE_ID:
+      Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
+      //
+      // 00:1f.0 LPC Bridge LNK routing targets
+      //
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+      break;
+    default:
+      DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+        __FUNCTION__, mHostBridgeDevId));
+      ASSERT (FALSE);
+      return;
+  }
+
+  //
+  // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
+  //
+  VisitAllPciInstances (SetPciIntLine);
+
+  //
+  // Set ACPI SCI_EN bit in PMCNTRL
+  //
+  IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
+  //
+  // Set all 8259 interrupts to edge triggered and disabled
+  //
+  Interrupt8259WriteMask(0xFFFF, 0x0000);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRecursivelyIfPciMassStorage (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *Instance,
+  IN PCI_TYPE00           *PciHeader
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  CHAR16                    *DevPathStr;
+
+  //
+  // Recognize PCI Mass Storage
+  //
+  if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
+    DevicePath = NULL;
+    Status = gBS->HandleProtocol (
+                    Handle,
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID*)&DevicePath
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Print Device Path
+    //
+    DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+    if (DevPathStr != NULL) {
+      DEBUG(( DEBUG_INFO, "Found Mass Storage device: %s\n", DevPathStr));
+      FreePool(DevPathStr);
+    }
+
+    Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+   }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This notification function is invoked when the
+  EMU Variable FVB has been changed.
+
+  @param  Event                 The event that occurred
+  @param  Context               For EFI compatibility.  Not used.
+
+**/
+VOID
+EFIAPI
+EmuVariablesUpdatedCallback (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+  UpdateNvVarsOnFileSystem ();
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingFileSystemInstance (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  )
+{
+  EFI_STATUS      Status;
+  STATIC BOOLEAN  ConnectedToFileSystem = FALSE;
+
+  if (ConnectedToFileSystem) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  Status = ConnectNvVarsToFileSystem (Handle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ConnectedToFileSystem = TRUE;
+  mEmuVariableEvent =
+    EfiCreateProtocolNotifyEvent (
+      &gEfiDevicePathProtocolGuid,
+      TPL_CALLBACK,
+      EmuVariablesUpdatedCallback,
+      NULL,
+      &mEmuVariableEventReg
+      );
+  PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
+
+  return EFI_SUCCESS;
+}
+
+
+VOID
+PlatformBdsRestoreNvVarsFromHardDisk (
+  )
+{
+  VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
+  VisitAllInstancesOfProtocol (
+    &gEfiSimpleFileSystemProtocolGuid,
+    VisitingFileSystemInstance,
+    NULL
+    );
+}
+
+/**
+  Connect with predefined platform connect sequence.
+
+  The OEM/IBV can customize with their own connect sequence.
+**/
+VOID
+PlatformBdsConnectSequence (
+  VOID
+  )
+{
+  UINTN Index;
+
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+  Index = 0;
+
+  //
+  // Here we can get the customized platform connect sequence
+  // Notes: we can connect with new variable which record the
+  // last time boots connect device path sequence
+  //
+  while (gPlatformConnectSequence[Index] != NULL) {
+    //
+    // Build the platform boot option
+    //
+    EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
+    Index++;
+  }
+
+  //
+  // Just use the simple policy to connect all devices
+  //
+  DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
+  EfiBootManagerConnectAll ();
+
+  PciAcpiInitialization ();
+}
+
+/**
+  Do the platform specific action after the console is ready
+
+  Possible things that can be done in PlatformBootManagerAfterConsole:
+
+  > Console post action:
+    > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
+    > Signal console ready platform customized event
+  > Run diagnostics like memory testing
+  > Connect certain devices
+  > Dispatch aditional option roms
+  > Special boot: e.g.: USB boot, enter UI
+**/
+// VOID
+// EFIAPI
+// PlatformBootManagerAfterConsole (
+//   VOID
+//   )
+// {
+
+// }
+
+/**
+  This notification function is invoked when an instance of the
+  EFI_DEVICE_PATH_PROTOCOL is produced.
+
+  @param  Event                 The event that occurred
+  @param  Context               For EFI compatibility.  Not used.
+
+**/
+VOID
+EFIAPI
+NotifyDevPath (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  EFI_HANDLE                            Handle;
+  EFI_STATUS                            Status;
+  UINTN                                 BufferSize;
+  EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;
+  ATAPI_DEVICE_PATH                    *Atapi;
+
+  //
+  // Examine all new handles
+  //
+  for (;;) {
+    //
+    // Get the next handle
+    //
+    BufferSize = sizeof (Handle);
+    Status = gBS->LocateHandle (
+              ByRegisterNotify,
+              NULL,
+              mEfiDevPathNotifyReg,
+              &BufferSize,
+              &Handle
+              );
+
+    //
+    // If not found, we're done
+    //
+    if (EFI_NOT_FOUND == Status) {
+      break;
+    }
+
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    //
+    // Get the DevicePath protocol on that handle
+    //
+    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
+    ASSERT_EFI_ERROR (Status);
+
+    while (!IsDevicePathEnd (DevPathNode)) {
+      //
+      // Find the handler to dump this device path node
+      //
+      if (
+           (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
+           (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
+         ) {
+        Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
+        PciOr16 (
+          PCI_LIB_ADDRESS (
+            0,
+            1,
+            1,
+            (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
+            ),
+          BIT15
+          );
+      }
+
+      //
+      // Next device path node
+      //
+      DevPathNode = NextDevicePathNode (DevPathNode);
+    }
+  }
+
+  return;
+}
+
+
+VOID
+InstallDevicePathCallback (
+  VOID
+  )
+{
+  DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
+  mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
+                          &gEfiDevicePathProtocolGuid,
+                          TPL_CALLBACK,
+                          NotifyDevPath,
+                          NULL,
+                          &mEfiDevPathNotifyReg
+                          );
+}
+
+
+
+/**
+  ReadyToBoot callback to set video and text mode for internal shell boot.
+  That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
+  before booting to Shell for showing USB devices in Shell.
+
+  When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
+  by default. Hence, when booting to EFI shell, connecting input consoles are required.
+
+  @param  Event   Pointer to this event
+  @param  Context Event hanlder private data
+
+  @retval None.
+**/
+VOID
+EFIAPI
+BdsReadyToBootCallback (
+  IN  EFI_EVENT                 Event,
+  IN  VOID                      *Context
+  )
+{
+   DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+}
+
+
+/**
+  This is the callback function for PCI ENUMERATION COMPLETE.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsSmmReadyToLockCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+
+  VOID                *ProtocolPointer;
+  EFI_STATUS          Status;
+
+  //
+  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+  // if it is, we will skip it until real event is triggered
+  //
+  Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+  if (EFI_SUCCESS != Status) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+  //
+  // Dispatch the deferred 3rd party images.
+  //
+  EfiBootManagerDispatchDeferredImages ();
+
+  //
+  // For non-trusted console it must be handled here.
+  //
+  //UpdateGraphicConOut (FALSE);
+}
+
+
+/**
+  This is the callback function for PCI ENUMERATION COMPLETE.
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsPciEnumCompleteCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  VOID                                *ProtocolPointer;
+  EFI_STATUS                          Status;
+  PLATFORM_CONSOLE_CONNECT_ENTRY      PlatformConsole[3];
+  UINTN                               PlatformConsoleCount;
+  UINTN                               MaxCount;
+  //
+  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+  // if it is, we will skip it until real event is triggered
+  //
+  Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+  if (EFI_SUCCESS != Status) {
+    return;
+  }
+
+  PlatformConsoleCount = 0;
+  MaxCount             = ARRAY_SIZE(PlatformConsole);
+
+  if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+    PlatformConsole[PlatformConsoleCount].ConnectType = ConOut;
+    PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
+    PlatformConsoleCount++;
+  }
+  if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL) &&
+    PlatformConsoleCount < MaxCount) {
+    PlatformConsole[PlatformConsoleCount].ConnectType = ConIn;
+    PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
+    PlatformConsoleCount++;
+  }
+
+  if (PlatformConsoleCount < MaxCount){
+    PlatformConsole[PlatformConsoleCount].ConnectType = 0;
+    PlatformConsole[PlatformConsoleCount].DevicePath = NULL;
+  }else{
+    PlatformConsole[MaxCount - 1].ConnectType = 0;
+    PlatformConsole[MaxCount - 1].DevicePath = NULL;
+  }
+
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+  PlatformInitializeConsole (PlatformConsole);
+}
+
+
+/**
+  Before console after trusted console event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsBeforeConsoleAfterTrustedConsoleCallback (
+  IN EFI_EVENT          Event,
+  IN VOID               *Context
+  )
+{
+  EFI_BOOT_MANAGER_LOAD_OPTION  *NvBootOptions;
+  UINTN                         NvBootOptionCount;
+  UINTN                         Index;
+  EFI_STATUS                    Status;
+
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);
+  for (Index = 0; Index < NvBootOptionCount; Index++) {
+    Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a: removing Boot#%04x %r\n",
+        __FUNCTION__,
+        (UINT32) NvBootOptions[Index].OptionNumber,
+        Status
+        ));
+    }
+  }
+
+  InstallDevicePathCallback ();
+
+  VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid, ConnectRootBridge, NULL);
+  //
+  // Enable LPC
+  //
+  PciOr16 (POWER_MGMT_REGISTER_ICH10(0x04), BIT0 | BIT1 | BIT2);
+
+  PlatformRegisterOptionsAndKeys ();
+}
+
+
+/**
+  Before console before end of DXE event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
+  IN EFI_EVENT          Event,
+  IN VOID               *Context
+){
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+}
+
+/**
+  After console ready before boot option event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+BdsAfterConsoleReadyBeforeBootOptionCallback (
+  IN EFI_EVENT          Event,
+  IN VOID               *Context
+  )
+{
+  EFI_BOOT_MODE                      BootMode;
+
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+  if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
+    DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
+      "from disk since flash variables appear to be supported.\n"));
+  } else {
+    //
+    // Try to restore variables from the hard disk early so
+    // they can be used for the other BDS connect operations.
+    //
+    PlatformBdsRestoreNvVarsFromHardDisk ();
+  }
+
+  //
+  // Get current Boot Mode
+  //
+  BootMode = GetBootModeHob ();
+  DEBUG ((DEBUG_ERROR, "Boot Mode:%x\n", BootMode));
+
+  //
+  // Go the different platform policy with different boot mode
+  // Notes: this part code can be change with the table policy
+  //
+  ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
+
+  //
+  // Perform some platform specific connect sequence
+  //
+  PlatformBdsConnectSequence ();
+
+  //
+  // Logo show
+  //
+  EnableBootLogo(PcdGetPtr(PcdLogoFile));
+
+  EfiBootManagerRefreshAllBootOption ();
+
+  //
+  // Register UEFI Shell
+  //
+  PlatformRegisterFvBootOption (
+    PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
+    );
+
+  RemoveStaleFvFileOptions ();
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
new file mode 100644
index 0000000000..a77edf2699
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
@@ -0,0 +1,81 @@
+## @file
+#  Board BDS hook Library definition file.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BoardBdsHookLib
+  FILE_GUID                      = 285AB0B8-D0D2-4D83-BF20-F85ED040383E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = BoardBdsHookLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  BoardBdsHookLib.c
+  BoardBdsHook.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  BoardModulePkg/BoardModulePkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  OvmfPkg/OvmfPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  BaseLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  UefiBootManagerLib
+  BootLogoLib
+  DevicePathLib
+  PciLib
+  NvVarsFileLib
+  DxeLoadLinuxLib
+  UefiLib
+  LogoLib
+
+[Pcd]
+  gSimicsOpenBoardPkgTokenSpaceGuid.PcdEmuVariableEvent
+  gSimicsOpenBoardPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
+  gSimicsOpenBoardPkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+  gSimicsOpenBoardPkgTokenSpaceGuid.PcdShellFile
+  gSimicsOpenBoardPkgTokenSpaceGuid.PcdLogoFile
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath  ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath       ## CONSUMES
+
+[Pcd.IA32, Pcd.X64]
+  gEfiMdePkgTokenSpaceGuid.PcdFSBClock
+
+[Protocols]
+  gEfiDecompressProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiS3SaveStateProtocolGuid                   # PROTOCOL SOMETIMES_CONSUMED
+  gEfiDxeSmmReadyToLockProtocolGuid             # PROTOCOL SOMETIMES_PRODUCED
+  gEfiLoadedImageProtocolGuid                   # PROTOCOL SOMETIMES_PRODUCED
+  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL SOMETIMES_CONSUMED
+  gEfiPciEnumerationCompleteProtocolGuid        # PROTOCOL SOMETIMES_CONSUMED
+
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+
+[Depex]
+  TRUE
-- 
2.19.1.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#52229): https://edk2.groups.io/g/devel/message/52229
Mute This Topic: https://groups.io/mt/68590735/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-platforms] [PATCH 09/11] SimicsOpenBoardPkg: Add Bds Hook Library
Posted by Nate DeSimone 4 years, 11 months ago
Hi Prince,

Feedback inline.

On Sat, Dec 14, 2019 at 01:32:35AM +0000, Agyeman, Prince wrote:
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2336
> 
> Added Board BDS Hook library that implements simics specific
> Bds hook points or callbacks.
> 
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Michael Kubacki <michael.a.kubacki@intel.com>
> 
> Signed-off-by: Prince Agyeman <prince.agyeman@intel.com>
> ---
>  .../Library/BoardBdsHookLib/BoardBdsHook.h    |  173 ++
>  .../Library/BoardBdsHookLib/BoardBdsHookLib.c | 1630 +++++++++++++++++
>  .../BoardBdsHookLib/BoardBdsHookLib.inf       |   81 +
>  3 files changed, 1884 insertions(+)
>  create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
>  create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
>  create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
> 
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
> new file mode 100644
> index 0000000000..fda41b1c97
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHook.h
> @@ -0,0 +1,173 @@
> +/** @file
> +  Header file for the board board specific BDS hook library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
> +#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_

Please make the macros match the file name: _BOARD_BDS_HOOK_H_

> +
> +
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/SmBios.h>
> +#include <IndustryStandard/PeImage.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +#include <Library/BootLogoLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/NvVarsFileLib.h>
> +#include <Library/BoardBdsHookLib.h>
> +
> +#include <Protocol/Decompress.h>
> +#include <Protocol/PciIo.h>
> +#include <Protocol/FirmwareVolume2.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +#include <Protocol/S3SaveState.h>
> +#include <Protocol/DxeSmmReadyToLock.h>
> +#include <Protocol/LoadedImage.h>
> +
> +#include <Guid/Acpi.h>
> +#include <Guid/SmBios.h>
> +#include <Guid/Mps.h>
> +#include <Guid/HobList.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/EventGroup.h>
> +
> +#include <SimicsPlatforms.h>
> +
> +extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];
> +extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;
> +extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;
> +extern UART_DEVICE_PATH           gUartDeviceNode;
> +extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;
> +
> +#define PCI_DEVICE_PATH_NODE(Func, Dev) \
> +  { \
> +    { \
> +      HARDWARE_DEVICE_PATH, \
> +      HW_PCI_DP, \
> +      { \
> +        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
> +      } \
> +    }, \
> +    (Func), \
> +    (Dev) \
> +  }
> +
> +#define PNPID_DEVICE_PATH_NODE(PnpId) \
> +  { \
> +    { \
> +      ACPI_DEVICE_PATH, \
> +      ACPI_DP, \
> +      { \
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
> +      }, \
> +    }, \
> +    EISA_PNP_ID((PnpId)), \
> +    0 \
> +  }
> +
> +#define gPciIsaBridge \
> +  PCI_DEVICE_PATH_NODE(0, 0x1f)
> +
> +#define gP2PBridge \
> +  PCI_DEVICE_PATH_NODE(0, 0x1e)
> +
> +#define gPnpPs2Keyboard \
> +  PNPID_DEVICE_PATH_NODE(0x0303)
> +
> +#define gPnp16550ComPort \
> +  PNPID_DEVICE_PATH_NODE(0x0501)
> +
> +#define gUart \
> +  { \
> +    { \
> +      MESSAGING_DEVICE_PATH, \
> +      MSG_UART_DP, \
> +      { \
> +        (UINT8) (sizeof (UART_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
> +      } \
> +    }, \
> +    0, \
> +    115200, \
> +    8, \
> +    1, \
> +    1 \
> +  }
> +
> +#define gPcAnsiTerminal \
> +  { \
> +    { \
> +      MESSAGING_DEVICE_PATH, \
> +      MSG_VENDOR_DP, \
> +      { \
> +        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
> +      } \
> +    }, \
> +    DEVICE_PATH_MESSAGING_PC_ANSI \
> +  }
> +
> +#define PCI_CLASS_SCC          0x07
> +#define PCI_SUBCLASS_SERIAL    0x00
> +#define PCI_IF_16550           0x02
> +#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
> +#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
> +
> +typedef struct {
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     ConnectType;
> +} PLATFORM_CONSOLE_CONNECT_ENTRY;
> +
> +#define CONSOLE_OUT BIT0
> +#define CONSOLE_IN  BIT1
> +#define STD_ERROR   BIT2
> +extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
> +
> +//
> +// Platform BDS Functions
> +//
> +
> +VOID
> +PlatformInitializeConsole (
> +  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
> +  );
> +
> +/**
> +  Use SystemTable ConOut to stop video based Simple Text Out consoles from going
> +  to the video device. Put up LogoFile on every video device that is a console.
> +
> +  @param[in]  LogoFile   The file name of logo to display on the center of the screen.
> +
> +  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and logo displayed.
> +  @retval EFI_UNSUPPORTED Logo not found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EnableBootLogo(
> +  IN  EFI_GUID  *LogoFile
> +);
> +
> +#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
> new file mode 100644
> index 0000000000..1058dbf3cf
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.c
> @@ -0,0 +1,1630 @@
> +/** @file
> +  Board BDS hook Library. Implements board specific BDS hook library
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "BoardBdsHook.h"
> +#include <Guid/RootBridgesConnectedEventGroup.h>
> +#include <Protocol/FirmwareVolume2.h>
> +
> +#define LEGACY_8259_MASK_REGISTER_MASTER                  0x21
> +#define LEGACY_8259_MASK_REGISTER_SLAVE                   0xA1
> +#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER  0x4D0
> +#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE   0x4D1
> +
> +//
> +// Predefined platform connect sequence
> +//
> +EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };
> +
> +
> +ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  = gPnpPs2Keyboard;
> +ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode = gPnp16550ComPort;
> +UART_DEVICE_PATH           gUartDeviceNode            = gUart;
> +VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    = gPcAnsiTerminal;
> +
> +//
> +// Global data
> +//
> +
> +VOID          *mEfiDevPathNotifyReg;
> +EFI_EVENT     mEfiDevPathEvent;
> +VOID          *mEmuVariableEventReg;
> +EFI_EVENT     mEmuVariableEvent;
> +BOOLEAN       mDetectVgaOnly;
> +UINT16        mHostBridgeDevId;
> +
> +//
> +// Table of host IRQs matching PCI IRQs A-D
> +// (for configuring PCI Interrupt Line register)
> +//
> +CONST UINT8 PciHostIrqs[] = {
> +  0x0a, 0x0a, 0x0b, 0x0b
> +};
> +
> +//
> +// Type definitions
> +//
> +typedef
> +EFI_STATUS
> +(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
> +  IN EFI_HANDLE           Handle,
> +  IN VOID                 *Instance,
> +  IN VOID                 *Context
> +  );
> +
> +/**
> +  @param[in]  Handle - Handle of PCI device instance
> +  @param[in]  PciIo - PCI IO protocol instance
> +  @param[in]  Pci - PCI Header register block
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN PCI_TYPE00           *Pci
> +  );
> +
> +
> +//
> +// Function prototypes
> +//
> +
> +EFI_STATUS
> +VisitAllInstancesOfProtocol (
> +  IN EFI_GUID                    *Id,
> +  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
> +  IN VOID                        *Context
> +  );
> +
> +EFI_STATUS
> +VisitAllPciInstancesOfProtocol (
> +  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
> +  );
> +
> +VOID
> +InstallDevicePathCallback (
> +  VOID
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +ConnectRootBridge (
> +  IN EFI_HANDLE  RootBridgeHandle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  );
> +
> +
> +VOID
> +PlatformRegisterFvBootOption (
> +  EFI_GUID                         *FileGuid,
> +  CHAR16                           *Description,
> +  UINT32                           Attributes
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  INTN                              OptionIndex;
> +  EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
> +  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
> +  UINTN                             BootOptionCount;
> +  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **) &LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
> +  DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
> +  ASSERT (DevicePath != NULL);
> +  DevicePath = AppendDevicePathNode (
> +                 DevicePath,
> +                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
> +                 );
> +  ASSERT (DevicePath != NULL);
> +
> +  Status = EfiBootManagerInitializeLoadOption (
> +             &NewOption,
> +             LoadOptionNumberUnassigned,
> +             LoadOptionTypeBoot,
> +             Attributes,
> +             Description,
> +             DevicePath,
> +             NULL,
> +             0
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +  FreePool (DevicePath);
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (
> +                  &BootOptionCount, LoadOptionTypeBoot
> +                  );
> +
> +  OptionIndex = EfiBootManagerFindLoadOption (
> +                  &NewOption, BootOptions, BootOptionCount
> +                  );
> +
> +  if (OptionIndex == -1) {
> +    Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +  EfiBootManagerFreeLoadOption (&NewOption);
> +  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +}
> +
> +/**
> +  Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
> +  whose device paths do not resolve exactly to an FvFile in the system.
> +
> +  This removes any boot options that point to binaries built into the firmware
> +  and have become stale due to any of the following:
> +  - DXEFV's base address or size changed (historical),
> +  - DXEFV's FvNameGuid changed,
> +  - the FILE_GUID of the pointed-to binary changed,
> +  - the referenced binary is no longer built into the firmware.
> +
> +  EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
> +  avoids exact duplicates.
> +**/
> +VOID
> +RemoveStaleFvFileOptions (
> +  VOID
> +  )
> +{
> +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
> +  UINTN                        BootOptionCount;
> +  UINTN                        Index;
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
> +                  LoadOptionTypeBoot);
> +
> +  for (Index = 0; Index < BootOptionCount; ++Index) {
> +    EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
> +    EFI_STATUS               Status;
> +    EFI_HANDLE               FvHandle;
> +
> +    //
> +    // If the device path starts with neither MemoryMapped(...) nor Fv(...),
> +    // then keep the boot option.
> +    //
> +    Node1 = BootOptions[Index].FilePath;
> +    if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
> +          DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
> +        !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
> +          DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
> +      continue;
> +    }
> +
> +    //
> +    // If the second device path node is not FvFile(...), then keep the boot
> +    // option.
> +    //
> +    Node2 = NextDevicePathNode (Node1);
> +    if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
> +        DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
> +      continue;
> +    }
> +
> +    //
> +    // Locate the Firmware Volume2 protocol instance that is denoted by the
> +    // boot option. If this lookup fails (i.e., the boot option references a
> +    // firmware volume that doesn't exist), then we'll proceed to delete the
> +    // boot option.
> +    //
> +    SearchNode = Node1;
> +    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
> +                    &SearchNode, &FvHandle);
> +
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // The firmware volume was found; now let's see if it contains the FvFile
> +      // identified by GUID.
> +      //
> +      EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol;
> +      MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
> +      UINTN                             BufferSize;
> +      EFI_FV_FILETYPE                   FoundType;
> +      EFI_FV_FILE_ATTRIBUTES            FileAttributes;
> +      UINT32                            AuthenticationStatus;
> +
> +      Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
> +                      (VOID **)&FvProtocol);
> +      ASSERT_EFI_ERROR (Status);
> +
> +      FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
> +      //
> +      // Buffer==NULL means we request metadata only: BufferSize, FoundType,
> +      // FileAttributes.
> +      //
> +      Status = FvProtocol->ReadFile (
> +                             FvProtocol,
> +                             &FvFileNode->FvFileName, // NameGuid
> +                             NULL,                    // Buffer
> +                             &BufferSize,
> +                             &FoundType,
> +                             &FileAttributes,
> +                             &AuthenticationStatus
> +                             );
> +      if (!EFI_ERROR (Status)) {
> +        //
> +        // The FvFile was found. Keep the boot option.
> +        //
> +        continue;
> +      }
> +    }
> +
> +    //
> +    // Delete the boot option.
> +    //
> +    Status = EfiBootManagerDeleteLoadOptionVariable (
> +               BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
> +    DEBUG_CODE (
> +      CHAR16 *DevicePathString;
> +
> +      DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
> +                           FALSE, FALSE);
> +      DEBUG ((
> +        EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,
> +        "%a: removing stale Boot#%04x %s: %r\n",
> +        __FUNCTION__,
> +        (UINT32)BootOptions[Index].OptionNumber,
> +        DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
> +        Status
> +        ));
> +      if (DevicePathString != NULL) {
> +        FreePool (DevicePathString);
> +      }
> +      );
> +  }
> +
> +  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +}
> +
> +VOID
> +PlatformRegisterOptionsAndKeys (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_INPUT_KEY                Enter;
> +  EFI_INPUT_KEY                F2;
> +  EFI_INPUT_KEY                Esc;
> +  EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
> +
> +  //
> +  // Register ENTER as CONTINUE key
> +  //
> +  Enter.ScanCode    = SCAN_NULL;
> +  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
> +  Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
> +  ASSERT_EFI_ERROR (Status);
> +  DEBUG ((DEBUG_INFO, "PlatformRegisterOptionsAndKeys\n"));
> +  if (EFI_ERROR(Status)){
> +    return;
> +  }
> +  //
> +  // Map F2 to Boot Manager Menu
> +  //
> +  F2.ScanCode     = SCAN_F2;
> +  F2.UnicodeChar  = CHAR_NULL;
> +  Esc.ScanCode    = SCAN_ESC;
> +  Esc.UnicodeChar = CHAR_NULL;
> +  Status = EfiBootManagerGetBootManagerMenu (&BootOption);
> +  ASSERT_EFI_ERROR (Status);
> +  Status = EfiBootManagerAddKeyOptionVariable (
> +             NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
> +             );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +  Status = EfiBootManagerAddKeyOptionVariable (
> +             NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
> +             );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +}
> +
> +
> +/**
> +  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
> +
> +  @param[in] DeviceHandle  Handle of the LPC Bridge device.
> +
> +  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added to
> +                       ConOut, ConIn, and ErrOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ConnectRootBridge (
> +  IN EFI_HANDLE  RootBridgeHandle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  //
> +  // Make the PCI bus driver connect the root bridge, non-recursively. This
> +  // will produce a number of child handles with PciIo on them.
> +  //
> +  Status = gBS->ConnectController (
> +                  RootBridgeHandle, // ControllerHandle
> +                  NULL,             // DriverImageHandle
> +                  NULL,             // RemainingDevicePath -- produce all
> +                                    //   children
> +                  FALSE             // Recursive
> +                  );
> +  return Status;
> +}
> +
> +
> +/**
> +  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
> +
> +  @param[in] DeviceHandle  Handle of the LPC Bridge device.
> +
> +  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added to
> +                       ConOut, ConIn, and ErrOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +PrepareLpcBridgeDevicePath (
> +  IN EFI_HANDLE                DeviceHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
> +  CHAR16                    *DevPathStr;
> +
> +  DevicePath = NULL;
> +  Status = gBS->HandleProtocol (
> +                  DeviceHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID*)&DevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  TempDevicePath = DevicePath;
> +
> +  //
> +  // Register Keyboard
> +  //
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
> +
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +
> +  //
> +  // Register COM1
> +  //
> +  DevicePath = TempDevicePath;
> +  gPnp16550ComPortDeviceNode.UID = 0;
> +
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
> +
> +  //
> +  // Print Device Path
> +  //
> +  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
> +  if (DevPathStr != NULL) {
> +    DEBUG((
> +      DEBUG_INFO,
> +      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
> +      __LINE__,
> +      gPnp16550ComPortDeviceNode.UID + 1,
> +      DevPathStr
> +      ));
> +    FreePool(DevPathStr);
> +  }
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +
> +  //
> +  // Register COM2
> +  //
> +  DevicePath = TempDevicePath;
> +  gPnp16550ComPortDeviceNode.UID = 1;
> +
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
> +
> +  //
> +  // Print Device Path
> +  //
> +  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
> +  if (DevPathStr != NULL) {
> +    DEBUG((
> +      DEBUG_INFO,
> +      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
> +      __LINE__,
> +      gPnp16550ComPortDeviceNode.UID + 1,
> +      DevPathStr
> +      ));
> +    FreePool(DevPathStr);
> +  }
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +GetGopDevicePath (
> +   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
> +   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
> +   )
> +{
> +  UINTN                           Index;
> +  EFI_STATUS                      Status;
> +  EFI_HANDLE                      PciDeviceHandle;
> +  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
> +  UINTN                           GopHandleCount;
> +  EFI_HANDLE                      *GopHandleBuffer;
> +
> +  if (PciDevicePath == NULL || GopDevicePath == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Initialize the GopDevicePath to be PciDevicePath
> +  //
> +  *GopDevicePath    = PciDevicePath;
> +  TempPciDevicePath = PciDevicePath;
> +
> +  Status = gBS->LocateDevicePath (
> +                  &gEfiDevicePathProtocolGuid,
> +                  &TempPciDevicePath,
> +                  &PciDeviceHandle
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Try to connect this handle, so that GOP driver could start on this
> +  // device and create child handles with GraphicsOutput Protocol installed
> +  // on them, then we get device paths of these child handles and select
> +  // them as possible console device.
> +  //
> +  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiGraphicsOutputProtocolGuid,
> +                  NULL,
> +                  &GopHandleCount,
> +                  &GopHandleBuffer
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    //
> +    // Add all the child handles as possible Console Device
> +    //
> +    for (Index = 0; Index < GopHandleCount; Index++) {
> +      Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
> +      if (EFI_ERROR (Status)) {
> +        continue;
> +      }
> +      if (CompareMem (
> +            PciDevicePath,
> +            TempDevicePath,
> +            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
> +            ) == 0) {
> +        //
> +        // In current implementation, we only enable one of the child handles
> +        // as console device, i.e. sotre one of the child handle's device
> +        // path to variable "ConOut"
> +        // In future, we could select all child handles to be console device
> +        //
> +
> +        *GopDevicePath = TempDevicePath;
> +
> +        //
> +        // Delete the PCI device's path that added by
> +        // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
> +        //
> +        EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
> +        EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
> +      }
> +    }
> +    gBS->FreePool (GopHandleBuffer);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Add PCI display to ConOut.
> +
> +  @param[in] DeviceHandle  Handle of the PCI display device.
> +
> +  @retval EFI_SUCCESS  The PCI display device has been added to ConOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +PreparePciDisplayDevicePath (
> +  IN EFI_HANDLE                DeviceHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
> +
> +  DevicePath    = NULL;
> +  GopDevicePath = NULL;
> +  Status = gBS->HandleProtocol (
> +                  DeviceHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID*)&DevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  GetGopDevicePath (DevicePath, &GopDevicePath);
> +  DevicePath = GopDevicePath;
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Add PCI Serial to ConOut, ConIn, ErrOut.
> +
> +  @param[in] DeviceHandle  Handle of the PCI serial device.
> +
> +  @retval EFI_SUCCESS  The PCI serial device has been added to ConOut, ConIn,
> +                       ErrOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +PreparePciSerialDevicePath (
> +  IN EFI_HANDLE                DeviceHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +
> +  DevicePath = NULL;
> +  Status = gBS->HandleProtocol (
> +                  DeviceHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID*)&DevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +VisitAllInstancesOfProtocol (
> +  IN EFI_GUID                    *Id,
> +  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
> +  IN VOID                        *Context
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINTN                     HandleCount;
> +  EFI_HANDLE                *HandleBuffer;
> +  UINTN                     Index;
> +  VOID                      *Instance;
> +
> +  //
> +  // Start to check all the PciIo to find all possible device
> +  //
> +  HandleCount = 0;
> +  HandleBuffer = NULL;
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  Id,
> +                  NULL,
> +                  &HandleCount,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  for (Index = 0; Index < HandleCount; Index++) {
> +    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    Status = (*CallBackFunction) (
> +               HandleBuffer[Index],
> +               Instance,
> +               Context
> +               );
> +  }
> +
> +  gBS->FreePool (HandleBuffer);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +VisitingAPciInstance (
> +  IN EFI_HANDLE  Handle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_PCI_IO_PROTOCOL       *PciIo;
> +  PCI_TYPE00                Pci;
> +
> +  PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
> +
> +  //
> +  // Check for all PCI device
> +  //
> +  Status = PciIo->Pci.Read (
> +                    PciIo,
> +                    EfiPciIoWidthUint32,
> +                    0,
> +                    sizeof (Pci) / sizeof (UINT32),
> +                    &Pci
> +                    );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
> +           Handle,
> +           PciIo,
> +           &Pci
> +           );
> +
> +}
> +
> +
> +
> +EFI_STATUS
> +VisitAllPciInstances (
> +  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
> +  )
> +{
> +  return VisitAllInstancesOfProtocol (
> +           &gEfiPciIoProtocolGuid,
> +           VisitingAPciInstance,
> +           (VOID*)(UINTN) CallBackFunction
> +           );
> +}
> +
> +
> +/**
> +  Do platform specific PCI Device check and add them to
> +  ConOut, ConIn, ErrOut.
> +
> +  @param[in]  Handle - Handle of PCI device instance
> +  @param[in]  PciIo - PCI IO protocol instance
> +  @param[in]  Pci - PCI Header register block
> +
> +  @retval EFI_SUCCESS - PCI Device check and Console variable update
> +                        successfully.
> +  @retval EFI_STATUS - PCI Device check or Console variable update fail.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DetectAndPreparePlatformPciDevicePath (
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN PCI_TYPE00           *Pci
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  Status = PciIo->Attributes (
> +    PciIo,
> +    EfiPciIoAttributeOperationEnable,
> +    EFI_PCI_DEVICE_ENABLE,
> +    NULL
> +    );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  if (!mDetectVgaOnly) {
> +    //
> +    // Here we decide whether it is LPC Bridge
> +    //
> +    if ((IS_PCI_LPC (Pci)) ||
> +        ((IS_PCI_ISA_PDECODE (Pci)) &&
> +         (Pci->Hdr.VendorId == 0x8086) &&
> +         (Pci->Hdr.DeviceId == 0x7000)
> +        )
> +       ) {
> +      //
> +      // Add IsaKeyboard to ConIn,
> +      // add IsaSerial to ConOut, ConIn, ErrOut
> +      //
> +      DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
> +      PrepareLpcBridgeDevicePath (Handle);
> +      return EFI_SUCCESS;
> +    }
> +    //
> +    // Here we decide which Serial device to enable in PCI bus
> +    //
> +    if (IS_PCI_16550SERIAL (Pci)) {
> +      //
> +      // Add them to ConOut, ConIn, ErrOut.
> +      //
> +      DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
> +      PreparePciSerialDevicePath (Handle);
> +      return EFI_SUCCESS;
> +    }
> +  }
> +
> +  //
> +  // Here we decide which display device to enable in PCI bus
> +  //
> +  if (IS_PCI_DISPLAY (Pci)) {
> +    //
> +    // Add them to ConOut.
> +    //
> +    DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
> +    PreparePciDisplayDevicePath (Handle);
> +    return EFI_SUCCESS;
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
> +
> +  @param[in]  DetectVgaOnly - Only detect VGA device if it's TRUE.
> +
> +  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
> +  @retval EFI_STATUS - PCI Device check or Console variable update fail.
> +
> +**/
> +EFI_STATUS
> +DetectAndPreparePlatformPciDevicePaths (
> +  BOOLEAN DetectVgaOnly
> +  )
> +{
> +  mDetectVgaOnly = DetectVgaOnly;
> +  return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
> +}
> +
> +/**
> +  Connect the predefined platform default console device.
> +
> +  Always try to find and enable PCI display devices.
> +
> +  @param[in] PlatformConsole  Predefined platform default console device array.
> +**/
> +VOID
> +PlatformInitializeConsole (
> +  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
> +  )
> +{
> +  UINTN                              Index;
> +  EFI_DEVICE_PATH_PROTOCOL           *VarConout;
> +  EFI_DEVICE_PATH_PROTOCOL           *VarConin;
> +
> +  //
> +  // Connect RootBridge
> +  //
> +  GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
> +  GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
> +
> +  if (VarConout == NULL || VarConin == NULL) {
> +    //
> +    // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
> +    //
> +    DetectAndPreparePlatformPciDevicePaths (FALSE);
> +    DetectAndPreparePlatformPciDevicePaths(TRUE);
> +    //
> +    // Have chance to connect the platform default console,
> +    // the platform default console is the minimue device group
> +    // the platform should support
> +    //
> +    for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
> +      //
> +      // Update the console variable with the connect type
> +      //
> +      if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
> +        EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
> +      }
> +      if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
> +        EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
> +      }
> +      if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
> +        EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
> +      }
> +    }
> +  } else {
> +    //
> +    // Only detect VGA device and add them to ConOut
> +    //
> +    DetectAndPreparePlatformPciDevicePaths (TRUE);
> +  }
> +}
> +
> +
> +/**
> +  Configure PCI Interrupt Line register for applicable devices
> +  Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
> +
> +  @param[in]  Handle - Handle of PCI device instance
> +  @param[in]  PciIo - PCI IO protocol instance
> +  @param[in]  PciHdr - PCI Header register block
> +
> +  @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SetPciIntLine (
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN PCI_TYPE00           *PciHdr
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
> +  UINTN                     RootSlot;
> +  UINTN                     Idx;
> +  UINT8                     IrqLine;
> +  EFI_STATUS                Status;
> +  UINT32                    RootBusNumber;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (PciHdr->Device.InterruptPin != 0) {
> +
> +    DevPathNode = DevicePathFromHandle (Handle);
> +    ASSERT (DevPathNode != NULL);
> +    DevPath = DevPathNode;
> +
> +    RootBusNumber = 0;
> +    if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
> +        DevicePathSubType (DevPathNode) == ACPI_DP &&
> +        ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
> +      RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
> +    }
> +
> +    //
> +    // Compute index into PciHostIrqs[] table by walking
> +    // the device path and adding up all device numbers
> +    //
> +    Status = EFI_NOT_FOUND;
> +    RootSlot = 0;
> +    Idx = PciHdr->Device.InterruptPin - 1;
> +    while (!IsDevicePathEnd (DevPathNode)) {
> +      if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
> +          DevicePathSubType (DevPathNode) == HW_PCI_DP) {
> +
> +        Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
> +
> +        //
> +        // Unlike SeaBIOS, which starts climbing from the leaf device
> +        // up toward the root, we traverse the device path starting at
> +        // the root moving toward the leaf node.
> +        // The slot number of the top-level parent bridge is needed
> +        // with more than 24 slots on the root bus.
> +        //
> +        if (Status != EFI_SUCCESS) {
> +          Status = EFI_SUCCESS;
> +          RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
> +        }
> +      }
> +
> +      DevPathNode = NextDevicePathNode (DevPathNode);
> +    }
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +    if (RootBusNumber == 0 && RootSlot == 0) {
> +      return Status; //bugbug: workaround; need SIMICS change B0/D0/F0 PCI_IntPin reg(0x3D) = 0X0
> +//      DEBUG((
> +//        DEBUG_ERROR,
> +//       "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
> +//        __FUNCTION__
> +//        ));
> +//      ASSERT (FALSE);
> +    }
> +
> +    //
> +    // Final PciHostIrqs[] index calculation depends on the platform
> +    // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
> +    //
> +    switch (mHostBridgeDevId) {
> +      case INTEL_82441_DEVICE_ID:
> +        Idx -= 1;
> +        break;
> +      case INTEL_ICH10_DEVICE_ID:
> +        //
> +        // SeaBIOS contains the following comment:
> +        // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
> +        //  with a different starting index.
> +        //
> +        //  Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
> +        //
> +        if (RootSlot > 24) {
> +          //
> +          // in this case, subtract back out RootSlot from Idx
> +          // (SeaBIOS never adds it to begin with, but that would make our
> +          //  device path traversal loop above too awkward)
> +          //
> +          Idx -= RootSlot;
> +        }
> +        break;
> +      default:
> +        ASSERT (FALSE); // should never get here
> +    }
> +    Idx %= ARRAY_SIZE (PciHostIrqs);
> +    IrqLine = PciHostIrqs[Idx];
> +
> +    DEBUG_CODE_BEGIN ();
> +    {
> +      CHAR16        *DevPathString;
> +      STATIC CHAR16 Fallback[] = L"<failed to convert>";
> +      UINTN         Segment, Bus, Device, Function;
> +
> +      DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
> +      if (DevPathString == NULL) {
> +        DevPathString = Fallback;
> +      }
> +      Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
> +      ASSERT_EFI_ERROR (Status);
> +
> +      DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
> +        (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
> +        IrqLine));
> +
> +      if (DevPathString != Fallback) {
> +        FreePool (DevPathString);
> +      }
> +    }
> +    DEBUG_CODE_END ();
> +
> +    //
> +    // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
> +    //
> +    Status = PciIo->Pci.Write (
> +               PciIo,
> +               EfiPciIoWidthUint8,
> +               PCI_INT_LINE_OFFSET,
> +               1,
> +               &IrqLine
> +               );
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +Write to mask and edge/level triggered registers of master and slave 8259 PICs.
> +
> +@param[in]  Mask       low byte for master PIC mask register,
> +high byte for slave PIC mask register.
> +@param[in]  EdgeLevel  low byte for master PIC edge/level triggered register,
> +high byte for slave PIC edge/level triggered register.
> +
> +**/
> +VOID
> +Interrupt8259WriteMask(
> +  IN UINT16  Mask,
> +  IN UINT16  EdgeLevel
> +)
> +{
> +  IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
> +  IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
> +  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8)EdgeLevel);
> +  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8)(EdgeLevel >> 8));
> +}
> +
> +VOID
> +PciAcpiInitialization (
> +  VOID
> +  )
> +{
> +  UINTN  Pmba;
> +
> +  //
> +  // Query Host Bridge DID to determine platform type
> +  //
> +  mHostBridgeDevId = PcdGet16 (PcdSimicsX58HostBridgePciDevId);
> +  switch (mHostBridgeDevId) {
> +    case INTEL_82441_DEVICE_ID:
> +      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
> +      //
> +      // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
> +      //
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
> +      break;
> +    case INTEL_ICH10_DEVICE_ID:
> +      Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
> +      //
> +      // 00:1f.0 LPC Bridge LNK routing targets
> +      //
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
> +      break;
> +    default:
> +      DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
> +        __FUNCTION__, mHostBridgeDevId));
> +      ASSERT (FALSE);
> +      return;
> +  }
> +
> +  //
> +  // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
> +  //
> +  VisitAllPciInstances (SetPciIntLine);
> +
> +  //
> +  // Set ACPI SCI_EN bit in PMCNTRL
> +  //
> +  IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
> +  //
> +  // Set all 8259 interrupts to edge triggered and disabled
> +  //
> +  Interrupt8259WriteMask(0xFFFF, 0x0000);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +ConnectRecursivelyIfPciMassStorage (
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *Instance,
> +  IN PCI_TYPE00           *PciHeader
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  CHAR16                    *DevPathStr;
> +
> +  //
> +  // Recognize PCI Mass Storage
> +  //
> +  if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
> +    DevicePath = NULL;
> +    Status = gBS->HandleProtocol (
> +                    Handle,
> +                    &gEfiDevicePathProtocolGuid,
> +                    (VOID*)&DevicePath
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    //
> +    // Print Device Path
> +    //
> +    DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
> +    if (DevPathStr != NULL) {
> +      DEBUG(( DEBUG_INFO, "Found Mass Storage device: %s\n", DevPathStr));
> +      FreePool(DevPathStr);
> +    }
> +
> +    Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +   }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This notification function is invoked when the
> +  EMU Variable FVB has been changed.
> +
> +  @param  Event                 The event that occurred
> +  @param  Context               For EFI compatibility.  Not used.
> +
> +**/
> +VOID
> +EFIAPI
> +EmuVariablesUpdatedCallback (
> +  IN  EFI_EVENT Event,
> +  IN  VOID      *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +  UpdateNvVarsOnFileSystem ();
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +VisitingFileSystemInstance (
> +  IN EFI_HANDLE  Handle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  )
> +{
> +  EFI_STATUS      Status;
> +  STATIC BOOLEAN  ConnectedToFileSystem = FALSE;
> +
> +  if (ConnectedToFileSystem) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  Status = ConnectNvVarsToFileSystem (Handle);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ConnectedToFileSystem = TRUE;
> +  mEmuVariableEvent =
> +    EfiCreateProtocolNotifyEvent (
> +      &gEfiDevicePathProtocolGuid,
> +      TPL_CALLBACK,
> +      EmuVariablesUpdatedCallback,
> +      NULL,
> +      &mEmuVariableEventReg
> +      );
> +  PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +VOID
> +PlatformBdsRestoreNvVarsFromHardDisk (
> +  )
> +{
> +  VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
> +  VisitAllInstancesOfProtocol (
> +    &gEfiSimpleFileSystemProtocolGuid,
> +    VisitingFileSystemInstance,
> +    NULL
> +    );
> +}
> +
> +/**
> +  Connect with predefined platform connect sequence.
> +
> +  The OEM/IBV can customize with their own connect sequence.
> +**/
> +VOID
> +PlatformBdsConnectSequence (
> +  VOID
> +  )
> +{
> +  UINTN Index;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  Index = 0;
> +
> +  //
> +  // Here we can get the customized platform connect sequence
> +  // Notes: we can connect with new variable which record the
> +  // last time boots connect device path sequence
> +  //
> +  while (gPlatformConnectSequence[Index] != NULL) {
> +    //
> +    // Build the platform boot option
> +    //
> +    EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
> +    Index++;
> +  }
> +
> +  //
> +  // Just use the simple policy to connect all devices
> +  //
> +  DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
> +  EfiBootManagerConnectAll ();
> +
> +  PciAcpiInitialization ();
> +}
> +
> +/**
> +  Do the platform specific action after the console is ready
> +
> +  Possible things that can be done in PlatformBootManagerAfterConsole:
> +
> +  > Console post action:
> +    > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
> +    > Signal console ready platform customized event
> +  > Run diagnostics like memory testing
> +  > Connect certain devices
> +  > Dispatch aditional option roms
> +  > Special boot: e.g.: USB boot, enter UI
> +**/
> +// VOID
> +// EFIAPI
> +// PlatformBootManagerAfterConsole (
> +//   VOID
> +//   )
> +// {
> +
> +// }
> +
> +/**
> +  This notification function is invoked when an instance of the
> +  EFI_DEVICE_PATH_PROTOCOL is produced.
> +
> +  @param  Event                 The event that occurred
> +  @param  Context               For EFI compatibility.  Not used.
> +
> +**/
> +VOID
> +EFIAPI
> +NotifyDevPath (
> +  IN  EFI_EVENT Event,
> +  IN  VOID      *Context
> +  )
> +{
> +  EFI_HANDLE                            Handle;
> +  EFI_STATUS                            Status;
> +  UINTN                                 BufferSize;
> +  EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;
> +  ATAPI_DEVICE_PATH                    *Atapi;
> +
> +  //
> +  // Examine all new handles
> +  //
> +  for (;;) {
> +    //
> +    // Get the next handle
> +    //
> +    BufferSize = sizeof (Handle);
> +    Status = gBS->LocateHandle (
> +              ByRegisterNotify,
> +              NULL,
> +              mEfiDevPathNotifyReg,
> +              &BufferSize,
> +              &Handle
> +              );
> +
> +    //
> +    // If not found, we're done
> +    //
> +    if (EFI_NOT_FOUND == Status) {
> +      break;
> +    }
> +
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // Get the DevicePath protocol on that handle
> +    //
> +    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    while (!IsDevicePathEnd (DevPathNode)) {
> +      //
> +      // Find the handler to dump this device path node
> +      //
> +      if (
> +           (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
> +           (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
> +         ) {
> +        Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
> +        PciOr16 (
> +          PCI_LIB_ADDRESS (
> +            0,
> +            1,
> +            1,
> +            (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
> +            ),
> +          BIT15
> +          );
> +      }
> +
> +      //
> +      // Next device path node
> +      //
> +      DevPathNode = NextDevicePathNode (DevPathNode);
> +    }
> +  }
> +
> +  return;
> +}
> +
> +
> +VOID
> +InstallDevicePathCallback (
> +  VOID
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
> +  mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
> +                          &gEfiDevicePathProtocolGuid,
> +                          TPL_CALLBACK,
> +                          NotifyDevPath,
> +                          NULL,
> +                          &mEfiDevPathNotifyReg
> +                          );
> +}
> +
> +
> +
> +/**
> +  ReadyToBoot callback to set video and text mode for internal shell boot.
> +  That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
> +  before booting to Shell for showing USB devices in Shell.
> +
> +  When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
> +  by default. Hence, when booting to EFI shell, connecting input consoles are required.
> +
> +  @param  Event   Pointer to this event
> +  @param  Context Event hanlder private data
> +
> +  @retval None.
> +**/
> +VOID
> +EFIAPI
> +BdsReadyToBootCallback (
> +  IN  EFI_EVENT                 Event,
> +  IN  VOID                      *Context
> +  )
> +{
> +   DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +}
> +
> +
> +/**
> +  This is the callback function for PCI ENUMERATION COMPLETE.
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsSmmReadyToLockCallback (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +
> +  VOID                *ProtocolPointer;
> +  EFI_STATUS          Status;
> +
> +  //
> +  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
> +  // if it is, we will skip it until real event is triggered
> +  //
> +  Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, (VOID **) &ProtocolPointer);
> +  if (EFI_SUCCESS != Status) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  //
> +  // Dispatch the deferred 3rd party images.
> +  //
> +  EfiBootManagerDispatchDeferredImages ();
> +
> +  //
> +  // For non-trusted console it must be handled here.
> +  //
> +  //UpdateGraphicConOut (FALSE);
> +}
> +
> +
> +/**
> +  This is the callback function for PCI ENUMERATION COMPLETE.
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsPciEnumCompleteCallback (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  VOID                                *ProtocolPointer;
> +  EFI_STATUS                          Status;
> +  PLATFORM_CONSOLE_CONNECT_ENTRY      PlatformConsole[3];
> +  UINTN                               PlatformConsoleCount;
> +  UINTN                               MaxCount;
> +  //
> +  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
> +  // if it is, we will skip it until real event is triggered
> +  //
> +  Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
> +  if (EFI_SUCCESS != Status) {
> +    return;
> +  }
> +
> +  PlatformConsoleCount = 0;
> +  MaxCount             = ARRAY_SIZE(PlatformConsole);
> +
> +  if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
> +    PlatformConsole[PlatformConsoleCount].ConnectType = ConOut;
> +    PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
> +    PlatformConsoleCount++;
> +  }
> +  if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL) &&
> +    PlatformConsoleCount < MaxCount) {
> +    PlatformConsole[PlatformConsoleCount].ConnectType = ConIn;
> +    PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
> +    PlatformConsoleCount++;
> +  }
> +
> +  if (PlatformConsoleCount < MaxCount){
> +    PlatformConsole[PlatformConsoleCount].ConnectType = 0;
> +    PlatformConsole[PlatformConsoleCount].DevicePath = NULL;
> +  }else{
> +    PlatformConsole[MaxCount - 1].ConnectType = 0;
> +    PlatformConsole[MaxCount - 1].DevicePath = NULL;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  PlatformInitializeConsole (PlatformConsole);
> +}
> +
> +
> +/**
> +  Before console after trusted console event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsBeforeConsoleAfterTrustedConsoleCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  EFI_BOOT_MANAGER_LOAD_OPTION  *NvBootOptions;
> +  UINTN                         NvBootOptionCount;
> +  UINTN                         Index;
> +  EFI_STATUS                    Status;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);
> +  for (Index = 0; Index < NvBootOptionCount; Index++) {
> +    Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "%a: removing Boot#%04x %r\n",
> +        __FUNCTION__,
> +        (UINT32) NvBootOptions[Index].OptionNumber,
> +        Status
> +        ));
> +    }
> +  }
> +
> +  InstallDevicePathCallback ();
> +
> +  VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid, ConnectRootBridge, NULL);
> +  //
> +  // Enable LPC
> +  //
> +  PciOr16 (POWER_MGMT_REGISTER_ICH10(0x04), BIT0 | BIT1 | BIT2);
> +
> +  PlatformRegisterOptionsAndKeys ();
> +}
> +
> +
> +/**
> +  Before console before end of DXE event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +){
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +}
> +
> +/**
> +  After console ready before boot option event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsAfterConsoleReadyBeforeBootOptionCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  EFI_BOOT_MODE                      BootMode;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
> +    DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
> +      "from disk since flash variables appear to be supported.\n"));
> +  } else {
> +    //
> +    // Try to restore variables from the hard disk early so
> +    // they can be used for the other BDS connect operations.
> +    //
> +    PlatformBdsRestoreNvVarsFromHardDisk ();
> +  }
> +
> +  //
> +  // Get current Boot Mode
> +  //
> +  BootMode = GetBootModeHob ();
> +  DEBUG ((DEBUG_ERROR, "Boot Mode:%x\n", BootMode));
> +
> +  //
> +  // Go the different platform policy with different boot mode
> +  // Notes: this part code can be change with the table policy
> +  //
> +  ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
> +
> +  //
> +  // Perform some platform specific connect sequence
> +  //
> +  PlatformBdsConnectSequence ();
> +
> +  //
> +  // Logo show
> +  //
> +  EnableBootLogo(PcdGetPtr(PcdLogoFile));
> +
> +  EfiBootManagerRefreshAllBootOption ();
> +
> +  //
> +  // Register UEFI Shell
> +  //
> +  PlatformRegisterFvBootOption (
> +    PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
> +    );
> +
> +  RemoveStaleFvFileOptions ();
> +}
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
> new file mode 100644
> index 0000000000..a77edf2699
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHookLib.inf
> @@ -0,0 +1,81 @@
> +## @file
> +#  Board BDS hook Library definition file.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = BoardBdsHookLib
> +  FILE_GUID                      = 285AB0B8-D0D2-4D83-BF20-F85ED040383E
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = BoardBdsHookLib|DXE_DRIVER
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  BoardBdsHookLib.c
> +  BoardBdsHook.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MinPlatformPkg/MinPlatformPkg.dec
> +  BoardModulePkg/BoardModulePkg.dec
> +  SimicsOpenBoardPkg/OpenBoardPkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +  SimicsIch10Pkg/Ich10Pkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  BaseMemoryLib
> +  DebugLib
> +  PcdLib
> +  UefiBootManagerLib
> +  BootLogoLib
> +  DevicePathLib
> +  PciLib
> +  NvVarsFileLib
> +  DxeLoadLinuxLib
> +  UefiLib
> +  LogoLib
> +
> +[Pcd]
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdEmuVariableEvent
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdShellFile
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdLogoFile
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath  ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath       ## CONSUMES
> +
> +[Pcd.IA32, Pcd.X64]
> +  gEfiMdePkgTokenSpaceGuid.PcdFSBClock
> +
> +[Protocols]
> +  gEfiDecompressProtocolGuid
> +  gEfiPciRootBridgeIoProtocolGuid
> +  gEfiS3SaveStateProtocolGuid                   # PROTOCOL SOMETIMES_CONSUMED
> +  gEfiDxeSmmReadyToLockProtocolGuid             # PROTOCOL SOMETIMES_PRODUCED
> +  gEfiLoadedImageProtocolGuid                   # PROTOCOL SOMETIMES_PRODUCED
> +  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL SOMETIMES_CONSUMED
> +  gEfiPciEnumerationCompleteProtocolGuid        # PROTOCOL SOMETIMES_CONSUMED
> +
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid
> +
> +[Depex]
> +  TRUE
> -- 
> 2.19.1.windows.1
> 

Thanks,
Nate
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#52302): https://edk2.groups.io/g/devel/message/52302
Mute This Topic: https://groups.io/mt/68590735/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [edk2-platforms] [PATCH 09/11] SimicsOpenBoardPkg: Add Bds Hook Library
Posted by Kubacki, Michael A 4 years, 11 months ago
Reviewed-by: Michael Kubacki <michael.a.kubacki@intel.com>

> -----Original Message-----
> From: Agyeman, Prince <prince.agyeman@intel.com>
> Sent: Friday, December 13, 2019 5:33 PM
> To: devel@edk2.groups.io
> Cc: Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Kubacki,
> Michael A <michael.a.kubacki@intel.com>
> Subject: [edk2-platforms] [PATCH 09/11] SimicsOpenBoardPkg: Add Bds
> Hook Library
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2336
> 
> Added Board BDS Hook library that implements simics specific
> Bds hook points or callbacks.
> 
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Michael Kubacki <michael.a.kubacki@intel.com>
> 
> Signed-off-by: Prince Agyeman <prince.agyeman@intel.com>
> ---
>  .../Library/BoardBdsHookLib/BoardBdsHook.h    |  173 ++
>  .../Library/BoardBdsHookLib/BoardBdsHookLib.c | 1630
> +++++++++++++++++
>  .../BoardBdsHookLib/BoardBdsHookLib.inf       |   81 +
>  3 files changed, 1884 insertions(+)
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHo
> ok.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHo
> okLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsHo
> okLib.inf
> 
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ook.h
> b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ook.h
> new file mode 100644
> index 0000000000..fda41b1c97
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ook.h
> @@ -0,0 +1,173 @@
> +/** @file
> +  Header file for the board board specific BDS hook library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
> +#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
> +
> +
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/SmBios.h>
> +#include <IndustryStandard/PeImage.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +#include <Library/BootLogoLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/NvVarsFileLib.h>
> +#include <Library/BoardBdsHookLib.h>
> +
> +#include <Protocol/Decompress.h>
> +#include <Protocol/PciIo.h>
> +#include <Protocol/FirmwareVolume2.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +#include <Protocol/S3SaveState.h>
> +#include <Protocol/DxeSmmReadyToLock.h>
> +#include <Protocol/LoadedImage.h>
> +
> +#include <Guid/Acpi.h>
> +#include <Guid/SmBios.h>
> +#include <Guid/Mps.h>
> +#include <Guid/HobList.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/EventGroup.h>
> +
> +#include <SimicsPlatforms.h>
> +
> +extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];
> +extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;
> +extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;
> +extern UART_DEVICE_PATH           gUartDeviceNode;
> +extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;
> +
> +#define PCI_DEVICE_PATH_NODE(Func, Dev) \
> +  { \
> +    { \
> +      HARDWARE_DEVICE_PATH, \
> +      HW_PCI_DP, \
> +      { \
> +        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
> +      } \
> +    }, \
> +    (Func), \
> +    (Dev) \
> +  }
> +
> +#define PNPID_DEVICE_PATH_NODE(PnpId) \
> +  { \
> +    { \
> +      ACPI_DEVICE_PATH, \
> +      ACPI_DP, \
> +      { \
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
> +      }, \
> +    }, \
> +    EISA_PNP_ID((PnpId)), \
> +    0 \
> +  }
> +
> +#define gPciIsaBridge \
> +  PCI_DEVICE_PATH_NODE(0, 0x1f)
> +
> +#define gP2PBridge \
> +  PCI_DEVICE_PATH_NODE(0, 0x1e)
> +
> +#define gPnpPs2Keyboard \
> +  PNPID_DEVICE_PATH_NODE(0x0303)
> +
> +#define gPnp16550ComPort \
> +  PNPID_DEVICE_PATH_NODE(0x0501)
> +
> +#define gUart \
> +  { \
> +    { \
> +      MESSAGING_DEVICE_PATH, \
> +      MSG_UART_DP, \
> +      { \
> +        (UINT8) (sizeof (UART_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
> +      } \
> +    }, \
> +    0, \
> +    115200, \
> +    8, \
> +    1, \
> +    1 \
> +  }
> +
> +#define gPcAnsiTerminal \
> +  { \
> +    { \
> +      MESSAGING_DEVICE_PATH, \
> +      MSG_VENDOR_DP, \
> +      { \
> +        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
> +      } \
> +    }, \
> +    DEVICE_PATH_MESSAGING_PC_ANSI \
> +  }
> +
> +#define PCI_CLASS_SCC          0x07
> +#define PCI_SUBCLASS_SERIAL    0x00
> +#define PCI_IF_16550           0x02
> +#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC,
> PCI_SUBCLASS_SERIAL, PCI_IF_16550)
> +#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE,
> PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
> +
> +typedef struct {
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  UINTN                     ConnectType;
> +} PLATFORM_CONSOLE_CONNECT_ENTRY;
> +
> +#define CONSOLE_OUT BIT0
> +#define CONSOLE_IN  BIT1
> +#define STD_ERROR   BIT2
> +extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
> +
> +//
> +// Platform BDS Functions
> +//
> +
> +VOID
> +PlatformInitializeConsole (
> +  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
> +  );
> +
> +/**
> +  Use SystemTable ConOut to stop video based Simple Text Out consoles
> from going
> +  to the video device. Put up LogoFile on every video device that is a
> console.
> +
> +  @param[in]  LogoFile   The file name of logo to display on the center of the
> screen.
> +
> +  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and
> logo displayed.
> +  @retval EFI_UNSUPPORTED Logo not found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EnableBootLogo(
> +  IN  EFI_GUID  *LogoFile
> +);
> +
> +#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ookLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ookLib.c
> new file mode 100644
> index 0000000000..1058dbf3cf
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ookLib.c
> @@ -0,0 +1,1630 @@
> +/** @file
> +  Board BDS hook Library. Implements board specific BDS hook library
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "BoardBdsHook.h"
> +#include <Guid/RootBridgesConnectedEventGroup.h>
> +#include <Protocol/FirmwareVolume2.h>
> +
> +#define LEGACY_8259_MASK_REGISTER_MASTER                  0x21
> +#define LEGACY_8259_MASK_REGISTER_SLAVE                   0xA1
> +#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER
> 0x4D0
> +#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE   0x4D1
> +
> +//
> +// Predefined platform connect sequence
> +//
> +EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };
> +
> +
> +ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  =
> gPnpPs2Keyboard;
> +ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode =
> gPnp16550ComPort;
> +UART_DEVICE_PATH           gUartDeviceNode            = gUart;
> +VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    =
> gPcAnsiTerminal;
> +
> +//
> +// Global data
> +//
> +
> +VOID          *mEfiDevPathNotifyReg;
> +EFI_EVENT     mEfiDevPathEvent;
> +VOID          *mEmuVariableEventReg;
> +EFI_EVENT     mEmuVariableEvent;
> +BOOLEAN       mDetectVgaOnly;
> +UINT16        mHostBridgeDevId;
> +
> +//
> +// Table of host IRQs matching PCI IRQs A-D
> +// (for configuring PCI Interrupt Line register)
> +//
> +CONST UINT8 PciHostIrqs[] = {
> +  0x0a, 0x0a, 0x0b, 0x0b
> +};
> +
> +//
> +// Type definitions
> +//
> +typedef
> +EFI_STATUS
> +(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
> +  IN EFI_HANDLE           Handle,
> +  IN VOID                 *Instance,
> +  IN VOID                 *Context
> +  );
> +
> +/**
> +  @param[in]  Handle - Handle of PCI device instance
> +  @param[in]  PciIo - PCI IO protocol instance
> +  @param[in]  Pci - PCI Header register block
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN PCI_TYPE00           *Pci
> +  );
> +
> +
> +//
> +// Function prototypes
> +//
> +
> +EFI_STATUS
> +VisitAllInstancesOfProtocol (
> +  IN EFI_GUID                    *Id,
> +  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
> +  IN VOID                        *Context
> +  );
> +
> +EFI_STATUS
> +VisitAllPciInstancesOfProtocol (
> +  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
> +  );
> +
> +VOID
> +InstallDevicePathCallback (
> +  VOID
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +ConnectRootBridge (
> +  IN EFI_HANDLE  RootBridgeHandle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  );
> +
> +
> +VOID
> +PlatformRegisterFvBootOption (
> +  EFI_GUID                         *FileGuid,
> +  CHAR16                           *Description,
> +  UINT32                           Attributes
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  INTN                              OptionIndex;
> +  EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
> +  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
> +  UINTN                             BootOptionCount;
> +  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
> +  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
> +  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiLoadedImageProtocolGuid,
> +                  (VOID **) &LoadedImage
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
> +  DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
> +  ASSERT (DevicePath != NULL);
> +  DevicePath = AppendDevicePathNode (
> +                 DevicePath,
> +                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
> +                 );
> +  ASSERT (DevicePath != NULL);
> +
> +  Status = EfiBootManagerInitializeLoadOption (
> +             &NewOption,
> +             LoadOptionNumberUnassigned,
> +             LoadOptionTypeBoot,
> +             Attributes,
> +             Description,
> +             DevicePath,
> +             NULL,
> +             0
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +  FreePool (DevicePath);
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (
> +                  &BootOptionCount, LoadOptionTypeBoot
> +                  );
> +
> +  OptionIndex = EfiBootManagerFindLoadOption (
> +                  &NewOption, BootOptions, BootOptionCount
> +                  );
> +
> +  if (OptionIndex == -1) {
> +    Status = EfiBootManagerAddLoadOptionVariable (&NewOption,
> MAX_UINTN);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +  EfiBootManagerFreeLoadOption (&NewOption);
> +  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +}
> +
> +/**
> +  Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot
> options
> +  whose device paths do not resolve exactly to an FvFile in the system.
> +
> +  This removes any boot options that point to binaries built into the
> firmware
> +  and have become stale due to any of the following:
> +  - DXEFV's base address or size changed (historical),
> +  - DXEFV's FvNameGuid changed,
> +  - the FILE_GUID of the pointed-to binary changed,
> +  - the referenced binary is no longer built into the firmware.
> +
> +  EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption()
> only
> +  avoids exact duplicates.
> +**/
> +VOID
> +RemoveStaleFvFileOptions (
> +  VOID
> +  )
> +{
> +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
> +  UINTN                        BootOptionCount;
> +  UINTN                        Index;
> +
> +  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
> +                  LoadOptionTypeBoot);
> +
> +  for (Index = 0; Index < BootOptionCount; ++Index) {
> +    EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
> +    EFI_STATUS               Status;
> +    EFI_HANDLE               FvHandle;
> +
> +    //
> +    // If the device path starts with neither MemoryMapped(...) nor Fv(...),
> +    // then keep the boot option.
> +    //
> +    Node1 = BootOptions[Index].FilePath;
> +    if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
> +          DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
> +        !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
> +          DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
> +      continue;
> +    }
> +
> +    //
> +    // If the second device path node is not FvFile(...), then keep the boot
> +    // option.
> +    //
> +    Node2 = NextDevicePathNode (Node1);
> +    if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
> +        DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
> +      continue;
> +    }
> +
> +    //
> +    // Locate the Firmware Volume2 protocol instance that is denoted by the
> +    // boot option. If this lookup fails (i.e., the boot option references a
> +    // firmware volume that doesn't exist), then we'll proceed to delete the
> +    // boot option.
> +    //
> +    SearchNode = Node1;
> +    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
> +                    &SearchNode, &FvHandle);
> +
> +    if (!EFI_ERROR (Status)) {
> +      //
> +      // The firmware volume was found; now let's see if it contains the FvFile
> +      // identified by GUID.
> +      //
> +      EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol;
> +      MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
> +      UINTN                             BufferSize;
> +      EFI_FV_FILETYPE                   FoundType;
> +      EFI_FV_FILE_ATTRIBUTES            FileAttributes;
> +      UINT32                            AuthenticationStatus;
> +
> +      Status = gBS->HandleProtocol (FvHandle,
> &gEfiFirmwareVolume2ProtocolGuid,
> +                      (VOID **)&FvProtocol);
> +      ASSERT_EFI_ERROR (Status);
> +
> +      FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
> +      //
> +      // Buffer==NULL means we request metadata only: BufferSize,
> FoundType,
> +      // FileAttributes.
> +      //
> +      Status = FvProtocol->ReadFile (
> +                             FvProtocol,
> +                             &FvFileNode->FvFileName, // NameGuid
> +                             NULL,                    // Buffer
> +                             &BufferSize,
> +                             &FoundType,
> +                             &FileAttributes,
> +                             &AuthenticationStatus
> +                             );
> +      if (!EFI_ERROR (Status)) {
> +        //
> +        // The FvFile was found. Keep the boot option.
> +        //
> +        continue;
> +      }
> +    }
> +
> +    //
> +    // Delete the boot option.
> +    //
> +    Status = EfiBootManagerDeleteLoadOptionVariable (
> +               BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
> +    DEBUG_CODE (
> +      CHAR16 *DevicePathString;
> +
> +      DevicePathString =
> ConvertDevicePathToText(BootOptions[Index].FilePath,
> +                           FALSE, FALSE);
> +      DEBUG ((
> +        EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,
> +        "%a: removing stale Boot#%04x %s: %r\n",
> +        __FUNCTION__,
> +        (UINT32)BootOptions[Index].OptionNumber,
> +        DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
> +        Status
> +        ));
> +      if (DevicePathString != NULL) {
> +        FreePool (DevicePathString);
> +      }
> +      );
> +  }
> +
> +  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
> +}
> +
> +VOID
> +PlatformRegisterOptionsAndKeys (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_INPUT_KEY                Enter;
> +  EFI_INPUT_KEY                F2;
> +  EFI_INPUT_KEY                Esc;
> +  EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
> +
> +  //
> +  // Register ENTER as CONTINUE key
> +  //
> +  Enter.ScanCode    = SCAN_NULL;
> +  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
> +  Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
> +  ASSERT_EFI_ERROR (Status);
> +  DEBUG ((DEBUG_INFO, "PlatformRegisterOptionsAndKeys\n"));
> +  if (EFI_ERROR(Status)){
> +    return;
> +  }
> +  //
> +  // Map F2 to Boot Manager Menu
> +  //
> +  F2.ScanCode     = SCAN_F2;
> +  F2.UnicodeChar  = CHAR_NULL;
> +  Esc.ScanCode    = SCAN_ESC;
> +  Esc.UnicodeChar = CHAR_NULL;
> +  Status = EfiBootManagerGetBootManagerMenu (&BootOption);
> +  ASSERT_EFI_ERROR (Status);
> +  Status = EfiBootManagerAddKeyOptionVariable (
> +             NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
> +             );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +  Status = EfiBootManagerAddKeyOptionVariable (
> +             NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
> +             );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
> +}
> +
> +
> +/**
> +  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
> +
> +  @param[in] DeviceHandle  Handle of the LPC Bridge device.
> +
> +  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added
> to
> +                       ConOut, ConIn, and ErrOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ConnectRootBridge (
> +  IN EFI_HANDLE  RootBridgeHandle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  //
> +  // Make the PCI bus driver connect the root bridge, non-recursively. This
> +  // will produce a number of child handles with PciIo on them.
> +  //
> +  Status = gBS->ConnectController (
> +                  RootBridgeHandle, // ControllerHandle
> +                  NULL,             // DriverImageHandle
> +                  NULL,             // RemainingDevicePath -- produce all
> +                                    //   children
> +                  FALSE             // Recursive
> +                  );
> +  return Status;
> +}
> +
> +
> +/**
> +  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
> +
> +  @param[in] DeviceHandle  Handle of the LPC Bridge device.
> +
> +  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added
> to
> +                       ConOut, ConIn, and ErrOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +PrepareLpcBridgeDevicePath (
> +  IN EFI_HANDLE                DeviceHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
> +  CHAR16                    *DevPathStr;
> +
> +  DevicePath = NULL;
> +  Status = gBS->HandleProtocol (
> +                  DeviceHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID*)&DevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  TempDevicePath = DevicePath;
> +
> +  //
> +  // Register Keyboard
> +  //
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
> +
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +
> +  //
> +  // Register COM1
> +  //
> +  DevicePath = TempDevicePath;
> +  gPnp16550ComPortDeviceNode.UID = 0;
> +
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
> +
> +  //
> +  // Print Device Path
> +  //
> +  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
> +  if (DevPathStr != NULL) {
> +    DEBUG((
> +      DEBUG_INFO,
> +      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
> +      __LINE__,
> +      gPnp16550ComPortDeviceNode.UID + 1,
> +      DevPathStr
> +      ));
> +    FreePool(DevPathStr);
> +  }
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +
> +  //
> +  // Register COM2
> +  //
> +  DevicePath = TempDevicePath;
> +  gPnp16550ComPortDeviceNode.UID = 1;
> +
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
> +
> +  //
> +  // Print Device Path
> +  //
> +  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
> +  if (DevPathStr != NULL) {
> +    DEBUG((
> +      DEBUG_INFO,
> +      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
> +      __LINE__,
> +      gPnp16550ComPortDeviceNode.UID + 1,
> +      DevPathStr
> +      ));
> +    FreePool(DevPathStr);
> +  }
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +GetGopDevicePath (
> +   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
> +   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
> +   )
> +{
> +  UINTN                           Index;
> +  EFI_STATUS                      Status;
> +  EFI_HANDLE                      PciDeviceHandle;
> +  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
> +  UINTN                           GopHandleCount;
> +  EFI_HANDLE                      *GopHandleBuffer;
> +
> +  if (PciDevicePath == NULL || GopDevicePath == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Initialize the GopDevicePath to be PciDevicePath
> +  //
> +  *GopDevicePath    = PciDevicePath;
> +  TempPciDevicePath = PciDevicePath;
> +
> +  Status = gBS->LocateDevicePath (
> +                  &gEfiDevicePathProtocolGuid,
> +                  &TempPciDevicePath,
> +                  &PciDeviceHandle
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Try to connect this handle, so that GOP driver could start on this
> +  // device and create child handles with GraphicsOutput Protocol installed
> +  // on them, then we get device paths of these child handles and select
> +  // them as possible console device.
> +  //
> +  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiGraphicsOutputProtocolGuid,
> +                  NULL,
> +                  &GopHandleCount,
> +                  &GopHandleBuffer
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    //
> +    // Add all the child handles as possible Console Device
> +    //
> +    for (Index = 0; Index < GopHandleCount; Index++) {
> +      Status = gBS->HandleProtocol (GopHandleBuffer[Index],
> &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
> +      if (EFI_ERROR (Status)) {
> +        continue;
> +      }
> +      if (CompareMem (
> +            PciDevicePath,
> +            TempDevicePath,
> +            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
> +            ) == 0) {
> +        //
> +        // In current implementation, we only enable one of the child handles
> +        // as console device, i.e. sotre one of the child handle's device
> +        // path to variable "ConOut"
> +        // In future, we could select all child handles to be console device
> +        //
> +
> +        *GopDevicePath = TempDevicePath;
> +
> +        //
> +        // Delete the PCI device's path that added by
> +        // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
> +        //
> +        EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL,
> PciDevicePath);
> +        EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath,
> NULL);
> +      }
> +    }
> +    gBS->FreePool (GopHandleBuffer);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Add PCI display to ConOut.
> +
> +  @param[in] DeviceHandle  Handle of the PCI display device.
> +
> +  @retval EFI_SUCCESS  The PCI display device has been added to ConOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +PreparePciDisplayDevicePath (
> +  IN EFI_HANDLE                DeviceHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
> +
> +  DevicePath    = NULL;
> +  GopDevicePath = NULL;
> +  Status = gBS->HandleProtocol (
> +                  DeviceHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID*)&DevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  GetGopDevicePath (DevicePath, &GopDevicePath);
> +  DevicePath = GopDevicePath;
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Add PCI Serial to ConOut, ConIn, ErrOut.
> +
> +  @param[in] DeviceHandle  Handle of the PCI serial device.
> +
> +  @retval EFI_SUCCESS  The PCI serial device has been added to ConOut,
> ConIn,
> +                       ErrOut.
> +
> +  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
> +                       from DeviceHandle.
> +**/
> +EFI_STATUS
> +PreparePciSerialDevicePath (
> +  IN EFI_HANDLE                DeviceHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +
> +  DevicePath = NULL;
> +  Status = gBS->HandleProtocol (
> +                  DeviceHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID*)&DevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
> +  DevicePath = AppendDevicePathNode (DevicePath,
> (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
> +
> +  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
> +  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +VisitAllInstancesOfProtocol (
> +  IN EFI_GUID                    *Id,
> +  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
> +  IN VOID                        *Context
> +  )
> +{
> +  EFI_STATUS                Status;
> +  UINTN                     HandleCount;
> +  EFI_HANDLE                *HandleBuffer;
> +  UINTN                     Index;
> +  VOID                      *Instance;
> +
> +  //
> +  // Start to check all the PciIo to find all possible device
> +  //
> +  HandleCount = 0;
> +  HandleBuffer = NULL;
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  Id,
> +                  NULL,
> +                  &HandleCount,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  for (Index = 0; Index < HandleCount; Index++) {
> +    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    Status = (*CallBackFunction) (
> +               HandleBuffer[Index],
> +               Instance,
> +               Context
> +               );
> +  }
> +
> +  gBS->FreePool (HandleBuffer);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +VisitingAPciInstance (
> +  IN EFI_HANDLE  Handle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_PCI_IO_PROTOCOL       *PciIo;
> +  PCI_TYPE00                Pci;
> +
> +  PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
> +
> +  //
> +  // Check for all PCI device
> +  //
> +  Status = PciIo->Pci.Read (
> +                    PciIo,
> +                    EfiPciIoWidthUint32,
> +                    0,
> +                    sizeof (Pci) / sizeof (UINT32),
> +                    &Pci
> +                    );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
> +           Handle,
> +           PciIo,
> +           &Pci
> +           );
> +
> +}
> +
> +
> +
> +EFI_STATUS
> +VisitAllPciInstances (
> +  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
> +  )
> +{
> +  return VisitAllInstancesOfProtocol (
> +           &gEfiPciIoProtocolGuid,
> +           VisitingAPciInstance,
> +           (VOID*)(UINTN) CallBackFunction
> +           );
> +}
> +
> +
> +/**
> +  Do platform specific PCI Device check and add them to
> +  ConOut, ConIn, ErrOut.
> +
> +  @param[in]  Handle - Handle of PCI device instance
> +  @param[in]  PciIo - PCI IO protocol instance
> +  @param[in]  Pci - PCI Header register block
> +
> +  @retval EFI_SUCCESS - PCI Device check and Console variable update
> +                        successfully.
> +  @retval EFI_STATUS - PCI Device check or Console variable update fail.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DetectAndPreparePlatformPciDevicePath (
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN PCI_TYPE00           *Pci
> +  )
> +{
> +  EFI_STATUS                Status;
> +
> +  Status = PciIo->Attributes (
> +    PciIo,
> +    EfiPciIoAttributeOperationEnable,
> +    EFI_PCI_DEVICE_ENABLE,
> +    NULL
> +    );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  if (!mDetectVgaOnly) {
> +    //
> +    // Here we decide whether it is LPC Bridge
> +    //
> +    if ((IS_PCI_LPC (Pci)) ||
> +        ((IS_PCI_ISA_PDECODE (Pci)) &&
> +         (Pci->Hdr.VendorId == 0x8086) &&
> +         (Pci->Hdr.DeviceId == 0x7000)
> +        )
> +       ) {
> +      //
> +      // Add IsaKeyboard to ConIn,
> +      // add IsaSerial to ConOut, ConIn, ErrOut
> +      //
> +      DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
> +      PrepareLpcBridgeDevicePath (Handle);
> +      return EFI_SUCCESS;
> +    }
> +    //
> +    // Here we decide which Serial device to enable in PCI bus
> +    //
> +    if (IS_PCI_16550SERIAL (Pci)) {
> +      //
> +      // Add them to ConOut, ConIn, ErrOut.
> +      //
> +      DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
> +      PreparePciSerialDevicePath (Handle);
> +      return EFI_SUCCESS;
> +    }
> +  }
> +
> +  //
> +  // Here we decide which display device to enable in PCI bus
> +  //
> +  if (IS_PCI_DISPLAY (Pci)) {
> +    //
> +    // Add them to ConOut.
> +    //
> +    DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
> +    PreparePciDisplayDevicePath (Handle);
> +    return EFI_SUCCESS;
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Do platform specific PCI Device check and add them to ConOut, ConIn,
> ErrOut
> +
> +  @param[in]  DetectVgaOnly - Only detect VGA device if it's TRUE.
> +
> +  @retval EFI_SUCCESS - PCI Device check and Console variable update
> successfully.
> +  @retval EFI_STATUS - PCI Device check or Console variable update fail.
> +
> +**/
> +EFI_STATUS
> +DetectAndPreparePlatformPciDevicePaths (
> +  BOOLEAN DetectVgaOnly
> +  )
> +{
> +  mDetectVgaOnly = DetectVgaOnly;
> +  return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
> +}
> +
> +/**
> +  Connect the predefined platform default console device.
> +
> +  Always try to find and enable PCI display devices.
> +
> +  @param[in] PlatformConsole  Predefined platform default console device
> array.
> +**/
> +VOID
> +PlatformInitializeConsole (
> +  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
> +  )
> +{
> +  UINTN                              Index;
> +  EFI_DEVICE_PATH_PROTOCOL           *VarConout;
> +  EFI_DEVICE_PATH_PROTOCOL           *VarConin;
> +
> +  //
> +  // Connect RootBridge
> +  //
> +  GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **)
> &VarConout, NULL);
> +  GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **)
> &VarConin, NULL);
> +
> +  if (VarConout == NULL || VarConin == NULL) {
> +    //
> +    // Do platform specific PCI Device check and add them to ConOut, ConIn,
> ErrOut
> +    //
> +    DetectAndPreparePlatformPciDevicePaths (FALSE);
> +    DetectAndPreparePlatformPciDevicePaths(TRUE);
> +    //
> +    // Have chance to connect the platform default console,
> +    // the platform default console is the minimue device group
> +    // the platform should support
> +    //
> +    for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
> +      //
> +      // Update the console variable with the connect type
> +      //
> +      if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) ==
> CONSOLE_IN) {
> +        EfiBootManagerUpdateConsoleVariable (ConIn,
> PlatformConsole[Index].DevicePath, NULL);
> +      }
> +      if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) ==
> CONSOLE_OUT) {
> +        EfiBootManagerUpdateConsoleVariable (ConOut,
> PlatformConsole[Index].DevicePath, NULL);
> +      }
> +      if ((PlatformConsole[Index].ConnectType & STD_ERROR) ==
> STD_ERROR) {
> +        EfiBootManagerUpdateConsoleVariable (ErrOut,
> PlatformConsole[Index].DevicePath, NULL);
> +      }
> +    }
> +  } else {
> +    //
> +    // Only detect VGA device and add them to ConOut
> +    //
> +    DetectAndPreparePlatformPciDevicePaths (TRUE);
> +  }
> +}
> +
> +
> +/**
> +  Configure PCI Interrupt Line register for applicable devices
> +  Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
> +
> +  @param[in]  Handle - Handle of PCI device instance
> +  @param[in]  PciIo - PCI IO protocol instance
> +  @param[in]  PciHdr - PCI Header register block
> +
> +  @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SetPciIntLine (
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN PCI_TYPE00           *PciHdr
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
> +  UINTN                     RootSlot;
> +  UINTN                     Idx;
> +  UINT8                     IrqLine;
> +  EFI_STATUS                Status;
> +  UINT32                    RootBusNumber;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (PciHdr->Device.InterruptPin != 0) {
> +
> +    DevPathNode = DevicePathFromHandle (Handle);
> +    ASSERT (DevPathNode != NULL);
> +    DevPath = DevPathNode;
> +
> +    RootBusNumber = 0;
> +    if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
> +        DevicePathSubType (DevPathNode) == ACPI_DP &&
> +        ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID ==
> EISA_PNP_ID(0x0A03)) {
> +      RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
> +    }
> +
> +    //
> +    // Compute index into PciHostIrqs[] table by walking
> +    // the device path and adding up all device numbers
> +    //
> +    Status = EFI_NOT_FOUND;
> +    RootSlot = 0;
> +    Idx = PciHdr->Device.InterruptPin - 1;
> +    while (!IsDevicePathEnd (DevPathNode)) {
> +      if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
> +          DevicePathSubType (DevPathNode) == HW_PCI_DP) {
> +
> +        Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
> +
> +        //
> +        // Unlike SeaBIOS, which starts climbing from the leaf device
> +        // up toward the root, we traverse the device path starting at
> +        // the root moving toward the leaf node.
> +        // The slot number of the top-level parent bridge is needed
> +        // with more than 24 slots on the root bus.
> +        //
> +        if (Status != EFI_SUCCESS) {
> +          Status = EFI_SUCCESS;
> +          RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
> +        }
> +      }
> +
> +      DevPathNode = NextDevicePathNode (DevPathNode);
> +    }
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +    if (RootBusNumber == 0 && RootSlot == 0) {
> +      return Status; //bugbug: workaround; need SIMICS change B0/D0/F0
> PCI_IntPin reg(0x3D) = 0X0
> +//      DEBUG((
> +//        DEBUG_ERROR,
> +//       "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
> +//        __FUNCTION__
> +//        ));
> +//      ASSERT (FALSE);
> +    }
> +
> +    //
> +    // Final PciHostIrqs[] index calculation depends on the platform
> +    // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
> +    //
> +    switch (mHostBridgeDevId) {
> +      case INTEL_82441_DEVICE_ID:
> +        Idx -= 1;
> +        break;
> +      case INTEL_ICH10_DEVICE_ID:
> +        //
> +        // SeaBIOS contains the following comment:
> +        // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
> +        //  with a different starting index.
> +        //
> +        //  Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
> +        //
> +        if (RootSlot > 24) {
> +          //
> +          // in this case, subtract back out RootSlot from Idx
> +          // (SeaBIOS never adds it to begin with, but that would make our
> +          //  device path traversal loop above too awkward)
> +          //
> +          Idx -= RootSlot;
> +        }
> +        break;
> +      default:
> +        ASSERT (FALSE); // should never get here
> +    }
> +    Idx %= ARRAY_SIZE (PciHostIrqs);
> +    IrqLine = PciHostIrqs[Idx];
> +
> +    DEBUG_CODE_BEGIN ();
> +    {
> +      CHAR16        *DevPathString;
> +      STATIC CHAR16 Fallback[] = L"<failed to convert>";
> +      UINTN         Segment, Bus, Device, Function;
> +
> +      DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
> +      if (DevPathString == NULL) {
> +        DevPathString = Fallback;
> +      }
> +      Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device,
> &Function);
> +      ASSERT_EFI_ERROR (Status);
> +
> +      DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n",
> __FUNCTION__,
> +        (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
> +        IrqLine));
> +
> +      if (DevPathString != Fallback) {
> +        FreePool (DevPathString);
> +      }
> +    }
> +    DEBUG_CODE_END ();
> +
> +    //
> +    // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
> +    //
> +    Status = PciIo->Pci.Write (
> +               PciIo,
> +               EfiPciIoWidthUint8,
> +               PCI_INT_LINE_OFFSET,
> +               1,
> +               &IrqLine
> +               );
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +Write to mask and edge/level triggered registers of master and slave 8259
> PICs.
> +
> +@param[in]  Mask       low byte for master PIC mask register,
> +high byte for slave PIC mask register.
> +@param[in]  EdgeLevel  low byte for master PIC edge/level triggered
> register,
> +high byte for slave PIC edge/level triggered register.
> +
> +**/
> +VOID
> +Interrupt8259WriteMask(
> +  IN UINT16  Mask,
> +  IN UINT16  EdgeLevel
> +)
> +{
> +  IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
> +  IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
> +  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER,
> (UINT8)EdgeLevel);
> +  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE,
> (UINT8)(EdgeLevel >> 8));
> +}
> +
> +VOID
> +PciAcpiInitialization (
> +  VOID
> +  )
> +{
> +  UINTN  Pmba;
> +
> +  //
> +  // Query Host Bridge DID to determine platform type
> +  //
> +  mHostBridgeDevId = PcdGet16 (PcdSimicsX58HostBridgePciDevId);
> +  switch (mHostBridgeDevId) {
> +    case INTEL_82441_DEVICE_ID:
> +      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
> +      //
> +      // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
> +      //
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
> +      break;
> +    case INTEL_ICH10_DEVICE_ID:
> +      Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
> +      //
> +      // 00:1f.0 LPC Bridge LNK routing targets
> +      //
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
> +      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
> +      break;
> +    default:
> +      DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID:
> 0x%04x\n",
> +        __FUNCTION__, mHostBridgeDevId));
> +      ASSERT (FALSE);
> +      return;
> +  }
> +
> +  //
> +  // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
> +  //
> +  VisitAllPciInstances (SetPciIntLine);
> +
> +  //
> +  // Set ACPI SCI_EN bit in PMCNTRL
> +  //
> +  IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
> +  //
> +  // Set all 8259 interrupts to edge triggered and disabled
> +  //
> +  Interrupt8259WriteMask(0xFFFF, 0x0000);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +ConnectRecursivelyIfPciMassStorage (
> +  IN EFI_HANDLE           Handle,
> +  IN EFI_PCI_IO_PROTOCOL  *Instance,
> +  IN PCI_TYPE00           *PciHeader
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
> +  CHAR16                    *DevPathStr;
> +
> +  //
> +  // Recognize PCI Mass Storage
> +  //
> +  if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
> +    DevicePath = NULL;
> +    Status = gBS->HandleProtocol (
> +                    Handle,
> +                    &gEfiDevicePathProtocolGuid,
> +                    (VOID*)&DevicePath
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    //
> +    // Print Device Path
> +    //
> +    DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
> +    if (DevPathStr != NULL) {
> +      DEBUG(( DEBUG_INFO, "Found Mass Storage device: %s\n",
> DevPathStr));
> +      FreePool(DevPathStr);
> +    }
> +
> +    Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +   }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This notification function is invoked when the
> +  EMU Variable FVB has been changed.
> +
> +  @param  Event                 The event that occurred
> +  @param  Context               For EFI compatibility.  Not used.
> +
> +**/
> +VOID
> +EFIAPI
> +EmuVariablesUpdatedCallback (
> +  IN  EFI_EVENT Event,
> +  IN  VOID      *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +  UpdateNvVarsOnFileSystem ();
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +VisitingFileSystemInstance (
> +  IN EFI_HANDLE  Handle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  )
> +{
> +  EFI_STATUS      Status;
> +  STATIC BOOLEAN  ConnectedToFileSystem = FALSE;
> +
> +  if (ConnectedToFileSystem) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  Status = ConnectNvVarsToFileSystem (Handle);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ConnectedToFileSystem = TRUE;
> +  mEmuVariableEvent =
> +    EfiCreateProtocolNotifyEvent (
> +      &gEfiDevicePathProtocolGuid,
> +      TPL_CALLBACK,
> +      EmuVariablesUpdatedCallback,
> +      NULL,
> +      &mEmuVariableEventReg
> +      );
> +  PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +VOID
> +PlatformBdsRestoreNvVarsFromHardDisk (
> +  )
> +{
> +  VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
> +  VisitAllInstancesOfProtocol (
> +    &gEfiSimpleFileSystemProtocolGuid,
> +    VisitingFileSystemInstance,
> +    NULL
> +    );
> +}
> +
> +/**
> +  Connect with predefined platform connect sequence.
> +
> +  The OEM/IBV can customize with their own connect sequence.
> +**/
> +VOID
> +PlatformBdsConnectSequence (
> +  VOID
> +  )
> +{
> +  UINTN Index;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  Index = 0;
> +
> +  //
> +  // Here we can get the customized platform connect sequence
> +  // Notes: we can connect with new variable which record the
> +  // last time boots connect device path sequence
> +  //
> +  while (gPlatformConnectSequence[Index] != NULL) {
> +    //
> +    // Build the platform boot option
> +    //
> +    EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index],
> NULL);
> +    Index++;
> +  }
> +
> +  //
> +  // Just use the simple policy to connect all devices
> +  //
> +  DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
> +  EfiBootManagerConnectAll ();
> +
> +  PciAcpiInitialization ();
> +}
> +
> +/**
> +  Do the platform specific action after the console is ready
> +
> +  Possible things that can be done in PlatformBootManagerAfterConsole:
> +
> +  > Console post action:
> +    > Dynamically switch output mode from 100x31 to 80x25 for certain
> senarino
> +    > Signal console ready platform customized event
> +  > Run diagnostics like memory testing
> +  > Connect certain devices
> +  > Dispatch aditional option roms
> +  > Special boot: e.g.: USB boot, enter UI
> +**/
> +// VOID
> +// EFIAPI
> +// PlatformBootManagerAfterConsole (
> +//   VOID
> +//   )
> +// {
> +
> +// }
> +
> +/**
> +  This notification function is invoked when an instance of the
> +  EFI_DEVICE_PATH_PROTOCOL is produced.
> +
> +  @param  Event                 The event that occurred
> +  @param  Context               For EFI compatibility.  Not used.
> +
> +**/
> +VOID
> +EFIAPI
> +NotifyDevPath (
> +  IN  EFI_EVENT Event,
> +  IN  VOID      *Context
> +  )
> +{
> +  EFI_HANDLE                            Handle;
> +  EFI_STATUS                            Status;
> +  UINTN                                 BufferSize;
> +  EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;
> +  ATAPI_DEVICE_PATH                    *Atapi;
> +
> +  //
> +  // Examine all new handles
> +  //
> +  for (;;) {
> +    //
> +    // Get the next handle
> +    //
> +    BufferSize = sizeof (Handle);
> +    Status = gBS->LocateHandle (
> +              ByRegisterNotify,
> +              NULL,
> +              mEfiDevPathNotifyReg,
> +              &BufferSize,
> +              &Handle
> +              );
> +
> +    //
> +    // If not found, we're done
> +    //
> +    if (EFI_NOT_FOUND == Status) {
> +      break;
> +    }
> +
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    //
> +    // Get the DevicePath protocol on that handle
> +    //
> +    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,
> (VOID **)&DevPathNode);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    while (!IsDevicePathEnd (DevPathNode)) {
> +      //
> +      // Find the handler to dump this device path node
> +      //
> +      if (
> +           (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
> +           (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
> +         ) {
> +        Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
> +        PciOr16 (
> +          PCI_LIB_ADDRESS (
> +            0,
> +            1,
> +            1,
> +            (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
> +            ),
> +          BIT15
> +          );
> +      }
> +
> +      //
> +      // Next device path node
> +      //
> +      DevPathNode = NextDevicePathNode (DevPathNode);
> +    }
> +  }
> +
> +  return;
> +}
> +
> +
> +VOID
> +InstallDevicePathCallback (
> +  VOID
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
> +  mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
> +                          &gEfiDevicePathProtocolGuid,
> +                          TPL_CALLBACK,
> +                          NotifyDevPath,
> +                          NULL,
> +                          &mEfiDevPathNotifyReg
> +                          );
> +}
> +
> +
> +
> +/**
> +  ReadyToBoot callback to set video and text mode for internal shell boot.
> +  That will not connect USB controller while CSM and FastBoot are disabled,
> we need to connect them
> +  before booting to Shell for showing USB devices in Shell.
> +
> +  When FastBoot is enabled and Windows Console is the chosen Console
> behavior, input devices will not be connected
> +  by default. Hence, when booting to EFI shell, connecting input consoles are
> required.
> +
> +  @param  Event   Pointer to this event
> +  @param  Context Event hanlder private data
> +
> +  @retval None.
> +**/
> +VOID
> +EFIAPI
> +BdsReadyToBootCallback (
> +  IN  EFI_EVENT                 Event,
> +  IN  VOID                      *Context
> +  )
> +{
> +   DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +}
> +
> +
> +/**
> +  This is the callback function for PCI ENUMERATION COMPLETE.
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsSmmReadyToLockCallback (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +
> +  VOID                *ProtocolPointer;
> +  EFI_STATUS          Status;
> +
> +  //
> +  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
> +  // if it is, we will skip it until real event is triggered
> +  //
> +  Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid,
> NULL, (VOID **) &ProtocolPointer);
> +  if (EFI_SUCCESS != Status) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  //
> +  // Dispatch the deferred 3rd party images.
> +  //
> +  EfiBootManagerDispatchDeferredImages ();
> +
> +  //
> +  // For non-trusted console it must be handled here.
> +  //
> +  //UpdateGraphicConOut (FALSE);
> +}
> +
> +
> +/**
> +  This is the callback function for PCI ENUMERATION COMPLETE.
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsPciEnumCompleteCallback (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  VOID                                *ProtocolPointer;
> +  EFI_STATUS                          Status;
> +  PLATFORM_CONSOLE_CONNECT_ENTRY      PlatformConsole[3];
> +  UINTN                               PlatformConsoleCount;
> +  UINTN                               MaxCount;
> +  //
> +  // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
> +  // if it is, we will skip it until real event is triggered
> +  //
> +  Status = gBS->LocateProtocol
> (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **)
> &ProtocolPointer);
> +  if (EFI_SUCCESS != Status) {
> +    return;
> +  }
> +
> +  PlatformConsoleCount = 0;
> +  MaxCount             = ARRAY_SIZE(PlatformConsole);
> +
> +  if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >=
> sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
> +    PlatformConsole[PlatformConsoleCount].ConnectType = ConOut;
> +    PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr
> (PcdTrustedConsoleOutputDevicePath);
> +    PlatformConsoleCount++;
> +  }
> +  if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >=
> sizeof(EFI_DEVICE_PATH_PROTOCOL) &&
> +    PlatformConsoleCount < MaxCount) {
> +    PlatformConsole[PlatformConsoleCount].ConnectType = ConIn;
> +    PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr
> (PcdTrustedConsoleInputDevicePath);
> +    PlatformConsoleCount++;
> +  }
> +
> +  if (PlatformConsoleCount < MaxCount){
> +    PlatformConsole[PlatformConsoleCount].ConnectType = 0;
> +    PlatformConsole[PlatformConsoleCount].DevicePath = NULL;
> +  }else{
> +    PlatformConsole[MaxCount - 1].ConnectType = 0;
> +    PlatformConsole[MaxCount - 1].DevicePath = NULL;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  PlatformInitializeConsole (PlatformConsole);
> +}
> +
> +
> +/**
> +  Before console after trusted console event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsBeforeConsoleAfterTrustedConsoleCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  EFI_BOOT_MANAGER_LOAD_OPTION  *NvBootOptions;
> +  UINTN                         NvBootOptionCount;
> +  UINTN                         Index;
> +  EFI_STATUS                    Status;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount,
> LoadOptionTypeBoot);
> +  for (Index = 0; Index < NvBootOptionCount; Index++) {
> +    Status = EfiBootManagerDeleteLoadOptionVariable
> (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "%a: removing Boot#%04x %r\n",
> +        __FUNCTION__,
> +        (UINT32) NvBootOptions[Index].OptionNumber,
> +        Status
> +        ));
> +    }
> +  }
> +
> +  InstallDevicePathCallback ();
> +
> +  VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
> ConnectRootBridge, NULL);
> +  //
> +  // Enable LPC
> +  //
> +  PciOr16 (POWER_MGMT_REGISTER_ICH10(0x04), BIT0 | BIT1 | BIT2);
> +
> +  PlatformRegisterOptionsAndKeys ();
> +}
> +
> +
> +/**
> +  Before console before end of DXE event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +){
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +}
> +
> +/**
> +  After console ready before boot option event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +BdsAfterConsoleReadyBeforeBootOptionCallback (
> +  IN EFI_EVENT          Event,
> +  IN VOID               *Context
> +  )
> +{
> +  EFI_BOOT_MODE                      BootMode;
> +
> +  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
> +
> +  if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
> +    DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars
> "
> +      "from disk since flash variables appear to be supported.\n"));
> +  } else {
> +    //
> +    // Try to restore variables from the hard disk early so
> +    // they can be used for the other BDS connect operations.
> +    //
> +    PlatformBdsRestoreNvVarsFromHardDisk ();
> +  }
> +
> +  //
> +  // Get current Boot Mode
> +  //
> +  BootMode = GetBootModeHob ();
> +  DEBUG ((DEBUG_ERROR, "Boot Mode:%x\n", BootMode));
> +
> +  //
> +  // Go the different platform policy with different boot mode
> +  // Notes: this part code can be change with the table policy
> +  //
> +  ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
> +
> +  //
> +  // Perform some platform specific connect sequence
> +  //
> +  PlatformBdsConnectSequence ();
> +
> +  //
> +  // Logo show
> +  //
> +  EnableBootLogo(PcdGetPtr(PcdLogoFile));
> +
> +  EfiBootManagerRefreshAllBootOption ();
> +
> +  //
> +  // Register UEFI Shell
> +  //
> +  PlatformRegisterFvBootOption (
> +    PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
> +    );
> +
> +  RemoveStaleFvFileOptions ();
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ookLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ookLib.inf
> new file mode 100644
> index 0000000000..a77edf2699
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/BoardBdsHookLib/BoardBdsH
> ookLib.inf
> @@ -0,0 +1,81 @@
> +## @file
> +#  Board BDS hook Library definition file.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = BoardBdsHookLib
> +  FILE_GUID                      = 285AB0B8-D0D2-4D83-BF20-F85ED040383E
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = BoardBdsHookLib|DXE_DRIVER
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  BoardBdsHookLib.c
> +  BoardBdsHook.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MinPlatformPkg/MinPlatformPkg.dec
> +  BoardModulePkg/BoardModulePkg.dec
> +  SimicsOpenBoardPkg/OpenBoardPkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +  SimicsIch10Pkg/Ich10Pkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  BaseMemoryLib
> +  DebugLib
> +  PcdLib
> +  UefiBootManagerLib
> +  BootLogoLib
> +  DevicePathLib
> +  PciLib
> +  NvVarsFileLib
> +  DxeLoadLinuxLib
> +  UefiLib
> +  LogoLib
> +
> +[Pcd]
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdEmuVariableEvent
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdShellFile
> +  gSimicsOpenBoardPkgTokenSpaceGuid.PcdLogoFile
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleInputDevicePath  ##
> CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedConsoleOutputDevicePath
> ## CONSUMES
> +  gMinPlatformPkgTokenSpaceGuid.PcdTrustedStorageDevicePath       ##
> CONSUMES
> +
> +[Pcd.IA32, Pcd.X64]
> +  gEfiMdePkgTokenSpaceGuid.PcdFSBClock
> +
> +[Protocols]
> +  gEfiDecompressProtocolGuid
> +  gEfiPciRootBridgeIoProtocolGuid
> +  gEfiS3SaveStateProtocolGuid                   # PROTOCOL
> SOMETIMES_CONSUMED
> +  gEfiDxeSmmReadyToLockProtocolGuid             # PROTOCOL
> SOMETIMES_PRODUCED
> +  gEfiLoadedImageProtocolGuid                   # PROTOCOL
> SOMETIMES_PRODUCED
> +  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL
> SOMETIMES_CONSUMED
> +  gEfiPciEnumerationCompleteProtocolGuid        # PROTOCOL
> SOMETIMES_CONSUMED
> +
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid
> +
> +[Depex]
> +  TRUE
> --
> 2.19.1.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#52475): https://edk2.groups.io/g/devel/message/52475
Mute This Topic: https://groups.io/mt/68590735/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-