[edk2-devel] [edk2-platform patch 5/7] SimicsOpenBoardPkg: Add Overrides modules for SIMICS QSP Platform

David Wei david.y.wei at intel.com
Fri Aug 23 17:09:53 UTC 2019


Hi Mike,
Please see the updates online below. Please let me know if you have any more comments.

Thanks
David

-----Original Message-----
From: Kubacki, Michael A 
Sent: Monday, August 19, 2019 6:05 PM
To: Wei, David Y <david.y.wei at intel.com>; devel at edk2.groups.io
Cc: Wu, Hao A <hao.a.wu at intel.com>; Gao, Liming <liming.gao at intel.com>; Sinha, Ankit <ankit.sinha at intel.com>; Agyeman, Prince <prince.agyeman at intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone at intel.com>; Kinney, Michael D <michael.d.kinney at intel.com>
Subject: RE: [edk2-platform patch 5/7] SimicsOpenBoardPkg: Add Overrides modules for SIMICS QSP Platform

Agree with Nate's feedback on moving the noted items out of the "Overrides" directory.
Ydwei: done
Please do submit a patch for style fixes in MinPlatformPkg/Acpi/AcpiTables directly.

> -----Original Message-----
> From: Wei, David Y
> Sent: Friday, August 9, 2019 3:47 PM
> To: devel at edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu at intel.com>; Gao, Liming <liming.gao at intel.com>;
> Sinha, Ankit <ankit.sinha at intel.com>; Agyeman, Prince
> <prince.agyeman at intel.com>; Kubacki, Michael A
> <michael.a.kubacki at intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone at intel.com>; Kinney, Michael D
> <michael.d.kinney at intel.com>
> Subject: [edk2-platform patch 5/7] SimicsOpenBoardPkg: Add Overrides
> modules for SIMICS QSP Platform
> 
> Overrides/MdeModulePkg/Library/PciHostBridgeLib - it is platform related.
> should be Customized
> Overrides/MdeModulePkg/Logo - the Logo image is Customized
> Overrides/MdePkg/Library/BasePciLibCf8 - use the functions specific for SIMICS
> 
> Cc: Hao Wu <hao.a.wu at intel.com>
> Cc: Liming Gao <liming.gao at intel.com>
> Cc: Ankit Sinha <ankit.sinha at intel.com>
> Cc: Agyeman Prince <prince.agyeman at intel.com>
> Cc: Kubacki Michael A <michael.a.kubacki at intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> 
> Signed-off-by: David Wei <david.y.wei at intel.com>
> ---
>  .../Library/PciHostBridgeLib/PciHostBridgeLib.c    |  419 ++++++
>  .../Library/PlatformBootManagerLib/BdsPlatform.c   | 1553
> +++++++++++++++++++
>  .../Library/PlatformBootManagerLib/PlatformData.c  |   35 +
>  .../Overrides/MdeModulePkg/Logo/Logo.c             |  154 ++
>  .../MdePkg/Library/BasePciLibCf8/PciLib.c          | 1221 +++++++++++++++
>  .../MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.c  | 1579
> ++++++++++++++++++++
>  .../MinPlatformPkg/Acpi/AcpiTables/Facs/Facs.c     |   84 ++
>  .../MinPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.c     |  359 +++++
>  .../MinPlatformPkg/Acpi/AcpiTables/Hpet/Hpet.c     |   78 +
>  .../MinPlatformPkg/Acpi/AcpiTables/Wsmt/Wsmt.c     |   46 +
>  .../Overrides/OvmfPkg/QemuVideoDxe/ComponentName.c |  205 +++
>  .../Overrides/OvmfPkg/QemuVideoDxe/Driver.c        | 1011 +++++++++++++
>  .../QemuVideoDxe/DriverSupportedEfiVersion.c       |   15 +
>  .../Overrides/OvmfPkg/QemuVideoDxe/Gop.c           |  417 ++++++
>  .../Overrides/OvmfPkg/QemuVideoDxe/Initialize.c    |  341 +++++
>  .../Overrides/OvmfPkg/QemuVideoDxe/VbeShim.c       |  302 ++++
>  .../8259InterruptControllerDxe/8259.c              |  622 ++++++++
>  .../Library/PciHostBridgeLib/PciHostBridge.h       |   68 +
>  .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |   50 +
>  .../Library/PlatformBootManagerLib/BdsPlatform.h   |  156 ++
>  .../PlatformBootManagerLib.inf                     |   69 +
>  .../Overrides/MdeModulePkg/Logo/Logo.bmp           |  Bin 0 -> 141078 bytes
>  .../Overrides/MdeModulePkg/Logo/Logo.idf           |   10 +
>  .../Overrides/MdeModulePkg/Logo/Logo.inf           |   28 +
>  .../Overrides/MdeModulePkg/Logo/Logo.uni           |   16 +
>  .../Overrides/MdeModulePkg/Logo/LogoDxe.inf        |   55 +
>  .../Overrides/MdeModulePkg/Logo/LogoDxe.uni        |   16 +
>  .../Overrides/MdeModulePkg/Logo/LogoDxeExtra.uni   |   14 +
>  .../Overrides/MdeModulePkg/Logo/LogoExtra.uni      |   14 +
>  .../Library/BasePciLibCf8/DxePciLibX58Ich10.inf    |   40 +
>  .../MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.h  |   45 +
>  .../Acpi/AcpiTables/AcpiPlatform.inf               |  105 ++
>  .../Overrides/OvmfPkg/QemuVideoDxe/Qemu.h          |  507 +++++++
>  .../OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf          |   73 +
>  .../Overrides/OvmfPkg/QemuVideoDxe/VbeShim.asm     |  281 ++++
>  .../Overrides/OvmfPkg/QemuVideoDxe/VbeShim.h       |  701 +++++++++
>  .../Overrides/OvmfPkg/QemuVideoDxe/VbeShim.sh      |   79 +
>  .../8259InterruptControllerDxe/8259.h              |  218 +++
>  .../8259InterruptControllerDxe/8259.inf            |   46 +
>  .../8259InterruptControllerDxe/Legacy8259.uni      |   16 +
>  .../8259InterruptControllerDxe/Legacy8259Extra.uni |   14 +
>  41 files changed, 11062 insertions(+)
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciHos
> tBridgeLib/PciHostBridgeLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platfor
> mBootManagerLib/BdsPlatform.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platfor
> mBootManagerLib/PlatformData.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf8/
> PciLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/AcpiPlatform.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/Facs/Facs.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/Fadt/Fadt.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/Hpet/Hpet.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/Wsmt/Wsmt.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Com
> ponentName.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Driv
> er.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Driv
> erSupportedEfiVersion.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Gop.
> c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Initia
> lize.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/VbeS
> him.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interrupt
> ControllerDxe/8259.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciHos
> tBridgeLib/PciHostBridge.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciHos
> tBridgeLib/PciHostBridgeLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platfor
> mBootManagerLib/BdsPlatform.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platfor
> mBootManagerLib/PlatformBootManagerLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.bm
> p
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.idf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.uni
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoDxe.
> inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoDxe.
> uni
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoDxe
> Extra.uni
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoExtr
> a.uni
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf8/
> DxePciLibX58Ich10.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/AcpiPlatform.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTabl
> es/AcpiPlatform.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qem
> u.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qem
> uVideoDxe.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/VbeS
> him.asm
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/VbeS
> him.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/VbeS
> him.sh
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interrupt
> ControllerDxe/8259.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interrupt
> ControllerDxe/8259.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interrupt
> ControllerDxe/Legacy8259.uni
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interrupt
> ControllerDxe/Legacy8259Extra.uni
> 
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridgeLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 0000000000..2aaa4b3e90
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,419 @@
> +/** @file
> +  OVMF's instance of the PCI Host Bridge Library.
> +
> +  Copyright (C) 2016, Red Hat, Inc.
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/X58Ich10.h>
> +
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/PciLib.h>
> +#include "PciHostBridge.h"
> +
> +
> +#pragma pack(1)
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
> +} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
> +#pragma pack ()
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +
> +STATIC
> +CONST
> +OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate =
> {
> +  {
> +    {
> +      ACPI_DEVICE_PATH,
> +      ACPI_DP,
> +      {
> +        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
> +        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    EISA_PNP_ID(0x0A03), // HID
> +    0                    // UID
> +  },
> +
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      END_DEVICE_PATH_LENGTH,
> +      0
> +    }
> +  }
> +};
> +
> +STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0
> };
> +
> +/**
> +  Initialize a PCI_ROOT_BRIDGE structure.
> +
> +  @param[in]  Supports         Supported attributes.
> +
> +  @param[in]  Attributes       Initial attributes.
> +
> +  @param[in]  AllocAttributes  Allocation attributes.
> +
> +  @param[in]  RootBusNumber    The bus number to store in RootBus.
> +
> +  @param[in]  MaxSubBusNumber  The inclusive maximum bus number that
> can be
> +                               assigned to any subordinate bus found behind any
> +                               PCI bridge hanging off this root bus.
> +
> +                               The caller is repsonsible for ensuring that
> +                               RootBusNumber <= MaxSubBusNumber. If
> +                               RootBusNumber equals MaxSubBusNumber, then the
> +                               root bus has no room for subordinate buses.
> +
> +  @param[in]  Io               IO aperture.
> +
> +  @param[in]  Mem              MMIO aperture.
> +
> +  @param[in]  MemAbove4G       MMIO aperture above 4G.
> +
> +  @param[in]  PMem             Prefetchable MMIO aperture.
> +
> +  @param[in]  PMemAbove4G      Prefetchable MMIO aperture above 4G.
> +
> +  @param[out] RootBus          The PCI_ROOT_BRIDGE structure (allocated by
> the
> +                               caller) that should be filled in by this
> +                               function.
> +
> +  @retval EFI_SUCCESS           Initialization successful. A device path
> +                                consisting of an ACPI device path node, with
> +                                UID = RootBusNumber, has been allocated and
> +                                linked into RootBus.
> +
> +  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +**/
> +EFI_STATUS
> +InitRootBridge (
> +  IN  UINT64                   Supports,
> +  IN  UINT64                   Attributes,
> +  IN  UINT64                   AllocAttributes,
> +  IN  UINT8                    RootBusNumber,
> +  IN  UINT8                    MaxSubBusNumber,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *Io,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *Mem,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *PMem,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
> +  OUT PCI_ROOT_BRIDGE          *RootBus
> +  )
> +{
> +  OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
> +
> +  //
> +  // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
> +  //
> +  ZeroMem (RootBus, sizeof *RootBus);
> +
> +  RootBus->Segment = 0;
> +
> +  RootBus->Supports   = Supports;
> +  RootBus->Attributes = Attributes;
> +
> +  RootBus->DmaAbove4G = FALSE;
> +
> +  RootBus->AllocationAttributes = AllocAttributes;
> +  RootBus->Bus.Base  = RootBusNumber;
> +  RootBus->Bus.Limit = MaxSubBusNumber;
> +  CopyMem (&RootBus->Io, Io, sizeof (*Io));
> +  CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
> +  CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof
> (*MemAbove4G));
> +  CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
> +  CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof
> (*PMemAbove4G));
> +
> +  RootBus->NoExtendedConfigSpace = (PcdGet16
> (PcdSimicsX58HostBridgePciDevId) !=
> +                                    INTEL_ICH10_DEVICE_ID);
> +
> +  DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
> +                 &mRootBridgeDevicePathTemplate);
> +  if (DevicePath == NULL) {
> +    DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__,
> EFI_OUT_OF_RESOURCES));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  DevicePath->AcpiDevicePath.UID = RootBusNumber;
> +  RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
> +
> +  DEBUG ((EFI_D_INFO,
> +    "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
> +    __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().
> +
> +  param[in] RootBus  The PCI_ROOT_BRIDGE structure, allocated by the caller
> and
> +                     initialized with InitRootBridge(), that should be
> +                     uninitialized. This function doesn't free RootBus.
> +**/
> +STATIC
> +VOID
> +UninitRootBridge (
> +  IN PCI_ROOT_BRIDGE *RootBus
> +  )
> +{
> +  FreePool (RootBus->DevicePath);
> +}
> +
> +
> +/**
> +  Return all the root bridge instances in an array.
> +
> +  @param Count  Return the count of root bridge instances.
> +
> +  @return All the root bridge instances in an array.
> +          The array should be passed into PciHostBridgeFreeRootBridges()
> +          when it's not used.
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> +  UINTN *Count
> +  )
> +{
> +  EFI_STATUS           Status;
> +  UINT64               ExtraRootBridges;
> +  PCI_ROOT_BRIDGE      *Bridges;
> +  UINTN                Initialized;
> +  UINTN                LastRootBridgeNumber;
> +  UINTN                RootBridgeNumber;
> +  UINT64               Attributes;
> +  UINT64               AllocationAttributes;
> +  PCI_ROOT_BRIDGE_APERTURE Io;
> +  PCI_ROOT_BRIDGE_APERTURE Mem;
> +  PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
> +
> +  ZeroMem (&Io, sizeof (Io));
> +  ZeroMem (&Mem, sizeof (Mem));
> +  ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
> +
> +  Attributes = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
> +    EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
> +    EFI_PCI_ATTRIBUTE_ISA_IO_16 |
> +    EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
> +    EFI_PCI_ATTRIBUTE_VGA_MEMORY |
> +    EFI_PCI_ATTRIBUTE_VGA_IO_16 |
> +    EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
> +
> +  AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
> +  if (PcdGet64 (PcdPciMmio64Size) > 0) {
> +    AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
> +    MemAbove4G.Base = PcdGet64 (PcdPciMmio64Base);
> +    MemAbove4G.Limit = PcdGet64 (PcdPciMmio64Base) +
> +                       PcdGet64 (PcdPciMmio64Size) - 1;
> +  } else {
> +    CopyMem (&MemAbove4G, &mNonExistAperture, sizeof
> (mNonExistAperture));
> +  }
> +
> +  Io.Base = PcdGet64 (PcdPciIoBase);
> +  Io.Limit = PcdGet64 (PcdPciIoBase) + (PcdGet64 (PcdPciIoSize) - 1);
> +  Mem.Base = PcdGet64 (PcdPciMmio32Base);
> +  Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64
> (PcdPciMmio32Size) - 1);
> +
> +  *Count = 0;
> +  ExtraRootBridges = 0;
> +
> +  //
> +  // Allocate the "main" root bridge, and any extra root bridges.
> +  //
> +  Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
> +  if (Bridges == NULL) {
> +    DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__,
> EFI_OUT_OF_RESOURCES));
> +    return NULL;
> +  }
> +  Initialized = 0;
> +
> +  //
> +  // The "main" root bus is always there.
> +  //
> +  LastRootBridgeNumber = 0;
> +
> +  //
> +  // Scan all other root buses. If function 0 of any device on a bus returns a
> +  // VendorId register value different from all-bits-one, then that bus is
> +  // alive.
> +  //
> +  for (RootBridgeNumber = 1;
> +       RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;
> +       ++RootBridgeNumber) {
> +    UINTN Device;
> +
> +    for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
> +      if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
> +                       PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
> +        break;
> +      }
> +    }
> +    if (Device <= PCI_MAX_DEVICE) {
> +      //
> +      // Found the next root bus. We can now install the *previous* one,
> +      // because now we know how big a bus number range *that* one has, for
> any
> +      // subordinate buses that might exist behind PCI bridges hanging off it.
> +      //
> +      Status = InitRootBridge (
> +        Attributes,
> +        Attributes,
> +        AllocationAttributes,
> +        (UINT8) LastRootBridgeNumber,
> +        (UINT8) (RootBridgeNumber - 1),
> +        &Io,
> +        &Mem,
> +        &MemAbove4G,
> +        &mNonExistAperture,
> +        &mNonExistAperture,
> +        &Bridges[Initialized]
> +        );
> +      if (EFI_ERROR (Status)) {
> +        goto FreeBridges;
> +      }
> +      ++Initialized;
> +      LastRootBridgeNumber = RootBridgeNumber;
> +    }
> +  }
> +
> +  //
> +  // Install the last root bus (which might be the only, ie. main, root bus, if
> +  // we've found no extra root buses).
> +  //
> +  Status = InitRootBridge (
> +    Attributes,
> +    Attributes,
> +    AllocationAttributes,
> +    (UINT8) LastRootBridgeNumber,
> +    PCI_MAX_BUS,
> +    &Io,
> +    &Mem,
> +    &MemAbove4G,
> +    &mNonExistAperture,
> +    &mNonExistAperture,
> +    &Bridges[Initialized]
> +    );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeBridges;
> +  }
> +  ++Initialized;
> +
> +  *Count = Initialized;
> +  return Bridges;
> +
> +FreeBridges:
> +  while (Initialized > 0) {
> +    --Initialized;
> +    UninitRootBridge (&Bridges[Initialized]);
> +  }
> +
> +  FreePool (Bridges);
> +  return NULL;
> +}
> +
> +
> +/**
> +  Free the root bridge instances array returned from
> +  PciHostBridgeGetRootBridges().
> +
> +  @param  The root bridge instances array.
> +  @param  The count of the array.
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeFreeRootBridges (
> +  PCI_ROOT_BRIDGE *Bridges,
> +  UINTN           Count
> +  )
> +{
> +  if (Bridges == NULL && Count == 0) {
> +    return;
> +  }
> +  ASSERT (Bridges != NULL && Count > 0);
> +
> +  do {
> +    --Count;
> +    UninitRootBridge (&Bridges[Count]);
> +  } while (Count > 0);
> +
> +  FreePool (Bridges);
> +}
> +
> +
> +/**
> +  Inform the platform that the resource conflict happens.
> +
> +  @param HostBridgeHandle Handle of the Host Bridge.
> +  @param Configuration    Pointer to PCI I/O and PCI memory resource
> +                          descriptors. The Configuration contains the resources
> +                          for all the root bridges. The resource for each root
> +                          bridge is terminated with END descriptor and an
> +                          additional END is appended indicating the end of the
> +                          entire resources. The resource descriptor field
> +                          values follow the description in
> +                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +                          .SubmitResources().
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeResourceConflict (
> +  EFI_HANDLE                        HostBridgeHandle,
> +  VOID                              *Configuration
> +  )
> +{
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
> +  UINTN                             RootBridgeIndex;
> +  DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> +  RootBridgeIndex = 0;
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +    DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> +    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR;
> Descriptor++) {
> +      ASSERT (Descriptor->ResType <
> +              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
> +               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
> +               )
> +              );
> +      DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
> +              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
> +              Descriptor->AddrLen, Descriptor->AddrRangeMax
> +              ));
> +      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +        DEBUG ((EFI_D_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
> +                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
> +                ((Descriptor->SpecificFlag &
> +
> EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
> +                  ) != 0) ? L" (Prefetchable)" : L""
> +                ));
> +      }
> +    }
> +    //
> +    // Skip the END descriptor for root bridge
> +    //
> +    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
> +    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
> +                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
> +                   );
> +  }
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/BdsPlatform.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/BdsPlatform.c
> new file mode 100644
> index 0000000000..0b66862e46
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/BdsPlatform.c
> @@ -0,0 +1,1553 @@
> +/** @file
> +  Platform BDS customizations.
> +
> +  Copyright (c) 2004 - 2018 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "BdsPlatform.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
> +
> +//
> +// 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
> +  );
> +
> +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 : EFI_D_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);
> +
> +  //
> +  // 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);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +ConnectRootBridge (
> +  IN EFI_HANDLE  RootBridgeHandle,
> +  IN VOID        *Instance,
> +  IN VOID        *Context
> +  );
> +
> +STATIC
> +VOID
> +SaveS3BootScript (
> +  VOID
> +  );
> +
> +//
> +// BDS Platform Functions
> +//
> +/**
> +  Do the platform init, can be customized by OEM/IBV
> +
> +  Possible things that can be done in PlatformBootManagerBeforeConsole:
> +
> +  > Update console variable: 1. include hot-plug devices;
> +  >                          2. Clear ConIn and add SOL for AMT
> +  > Register new Driver#### or Boot####
> +  > Register new Key####: e.g.: F12
> +  > Signal ReadyToLock event
> +  > Authentication action: 1. connect Auth devices;
> +  >                        2. Identify auto logon user.
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerBeforeConsole (
> +  VOID
> +  )
> +{
> +//  EFI_HANDLE    Handle;
> +//  EFI_STATUS    Status;
> +
> +  DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
> +  InstallDevicePathCallback ();
> +
> +  VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
> +    ConnectRootBridge, NULL);
> +  //
> +  // Enable LPC
> +  //
> +  PciOr16(POWER_MGMT_REGISTER_ICH10(0x04),
> +           BIT0 | BIT1 | BIT2);
> +  //
> +  // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
> +  // the preparation of S3 system information. That logic has a hard
> dependency
> +  // on the presence of the FACS ACPI table. Since our ACPI tables are only
> +  // installed after PCI enumeration completes, we must not trigger the S3 save
> +  // earlier, hence we can't signal End-of-Dxe earlier.
> +  //
> +  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
> +
> +  PlatformInitializeConsole (gPlatformConsole);
> +
> +  PlatformRegisterOptionsAndKeys ();
> +}
> +
> +
> +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((
> +      EFI_D_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((
> +      EFI_D_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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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((
> +//        EFI_D_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 ((EFI_D_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.
> +
> + at param[in]  Mask       low byte for master PIC mask register,
> +high byte for slave PIC mask register.
> + at 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 (
> +  )
> +{
> +  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 ((EFI_D_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((
> +        EFI_D_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 ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
> +  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 ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
> +
> +  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 ((EFI_D_INFO, "EfiBootManagerConnectAll\n"));
> +  EfiBootManagerConnectAll ();
> +
> +  PciAcpiInitialization ();
> +}
> +
> +/**
> +  Save the S3 boot script.
> +
> +  Note that DxeSmmReadyToLock must be signaled after this function returns;
> +  otherwise the script wouldn't be saved actually.
> +**/
> +STATIC
> +VOID
> +SaveS3BootScript (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
> +  STATIC CONST UINT8         Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
> +
> +  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
> +                  (VOID **) &BootScript);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Despite the opcode documentation in the PI spec, the protocol
> +  // implementation embeds a deep copy of the info in the boot script, rather
> +  // than storing just a pointer to runtime or NVS storage.
> +  //
> +  Status = BootScript->Write(BootScript,
> EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
> +                         (UINT32) sizeof Info,
> +                         (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
> +  ASSERT_EFI_ERROR (Status);
> +}
> +
> +
> +/**
> +  Do the platform specific action after the console is ready
> +
> +  Possible things that can be done in PlatformBootManagerAfterConsole:
> +
> +  > Console post action:
> +    > Dynamically switch output mode from 100x31 to 80x25 for certain
> senarino
> +    > Signal console ready platform customized event
> +  > Run diagnostics like memory testing
> +  > Connect certain devices
> +  > Dispatch aditional option roms
> +  > Special boot: e.g.: USB boot, enter UI
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerAfterConsole (
> +  VOID
> +  )
> +{
> +  EFI_BOOT_MODE                      BootMode;
> +  EFI_HANDLE                         Handle;
> +  EFI_STATUS                         Status;
> +
> +  DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
> +
> +  //
> +  // Prevent further changes to LockBoxes or SMRAM.
> +  //
> +  Handle = NULL;
> +  Status = gBS->InstallProtocolInterface(&Handle,
> +    &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
> +      NULL);
> +  ASSERT_EFI_ERROR(Status);
> +
> +  if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
> +    DEBUG ((EFI_D_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 ((EFI_D_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
> +  //
> +  BootLogoEnableLogo();
> +
> +  EfiBootManagerRefreshAllBootOption ();
> +
> +  //
> +  // Register UEFI Shell
> +  //
> +  PlatformRegisterFvBootOption (
> +    PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
> +    );
> +
> +  RemoveStaleFvFileOptions ();
> +}
> +
> +/**
> +  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 ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
> +  mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
> +                          &gEfiDevicePathProtocolGuid,
> +                          TPL_CALLBACK,
> +                          NotifyDevPath,
> +                          NULL,
> +                          &mEfiDevPathNotifyReg
> +                          );
> +}
> +
> +/**
> +  This function is called each second during the boot manager waits the
> +  timeout.
> +
> +  @param TimeoutRemain  The remaining timeout.
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerWaitCallback (
> +  UINT16          TimeoutRemain
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
> +  UINT16                              Timeout;
> +
> +  Timeout = PcdGet16 (PcdPlatformBootTimeOut);
> +
> +  Black.Raw = 0x00000000;
> +  White.Raw = 0x00FFFFFF;
> +
> +  BootLogoUpdateProgress (
> +    White.Pixel,
> +    Black.Pixel,
> +    L"Start boot option",
> +    White.Pixel,
> +    (Timeout - TimeoutRemain) * 100 / Timeout,
> +    0
> +    );
> +}
> +
> +/**
> +  The function is called when no boot option could be launched,
> +  including platform recovery options and options pointing to applications
> +  built into firmware volumes.
> +
> +  If this function returns, BDS attempts to enter an infinite loop.
> +**/
> +VOID
> +EFIAPI
> +PlatformBootManagerUnableToBoot (
> +  VOID
> +  )
> +{
> +  // BUGBUG- will do it if need
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/PlatformData.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/PlatformData.c
> new file mode 100644
> index 0000000000..5f1b16dd56
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/PlatformData.c
> @@ -0,0 +1,35 @@
> +/** @file
> +  Defined the platform specific device path which will be used by
> +  platform Bbd to perform the platform policy connect.
> +
> +  Copyright (c) 2004 - 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "BdsPlatform.h"
> +
> +ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  =
> gPnpPs2Keyboard;
> +ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode =
> gPnp16550ComPort;
> +UART_DEVICE_PATH           gUartDeviceNode            = gUart;
> +VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    = gPcAnsiTerminal;
> +
> +//
> +// Platform specific keyboard device path
> +//
> +
> +//
> +// Predefined platform default console device path
> +//
> +PLATFORM_CONSOLE_CONNECT_ENTRY   gPlatformConsole[] = {
> +  {
> +    NULL,
> +    0
> +  }
> +};
> +
> +//
> +// Predefined platform connect sequence
> +//
> +EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.c
> new file mode 100644
> index 0000000000..d4a75ad140
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.c
> @@ -0,0 +1,154 @@
> +/** @file
> +  Logo DXE Driver, install Edkii Platform Logo protocol.
> +
> +  Copyright (c) 2016 - 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/HiiImageEx.h>
> +#include <Protocol/PlatformLogo.h>
> +#include <Protocol/HiiPackageList.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +
> +typedef struct {
> +  EFI_IMAGE_ID                          ImageId;
> +  EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute;
> +  INTN                                  OffsetX;
> +  INTN                                  OffsetY;
> +} LOGO_ENTRY;
> +
> +EFI_HII_IMAGE_EX_PROTOCOL *mHiiImageEx;
> +EFI_HII_HANDLE            mHiiHandle;
> +LOGO_ENTRY                mLogos[] = {
> +  {
> +    IMAGE_TOKEN (IMG_LOGO),
> +    EdkiiPlatformLogoDisplayAttributeCenter,
> +    0,
> +    0
> +  }
> +};
> +
> +/**
> +  Load a platform logo image and return its data and attributes.
> +
> +  @param This              The pointer to this protocol instance.
> +  @param Instance          The visible image instance is found.
> +  @param Image             Points to the image.
> +  @param Attribute         The display attributes of the image returned.
> +  @param OffsetX           The X offset of the image regarding the Attribute.
> +  @param OffsetY           The Y offset of the image regarding the Attribute.
> +
> +  @retval EFI_SUCCESS      The image was fetched successfully.
> +  @retval EFI_NOT_FOUND    The specified image could not be found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetImage (
> +  IN     EDKII_PLATFORM_LOGO_PROTOCOL          *This,
> +  IN OUT UINT32                                *Instance,
> +     OUT EFI_IMAGE_INPUT                       *Image,
> +     OUT EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE *Attribute,
> +     OUT INTN                                  *OffsetX,
> +     OUT INTN                                  *OffsetY
> +  )
> +{
> +  UINT32 Current;
> +  if (Instance == NULL || Image == NULL ||
> +      Attribute == NULL || OffsetX == NULL || OffsetY == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Current = *Instance;
> +  if (Current >= ARRAY_SIZE (mLogos)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  (*Instance)++;
> +  *Attribute = mLogos[Current].Attribute;
> +  *OffsetX   = mLogos[Current].OffsetX;
> +  *OffsetY   = mLogos[Current].OffsetY;
> +  return mHiiImageEx->GetImageEx (mHiiImageEx, mHiiHandle,
> mLogos[Current].ImageId, Image);
> +}
> +
> +EDKII_PLATFORM_LOGO_PROTOCOL mPlatformLogo = {
> +  GetImage
> +};
> +
> +/**
> +  Entrypoint of this module.
> +
> +  This function is the entrypoint of this module. It installs the Edkii
> +  Platform Logo protocol.
> +
> +  @param  ImageHandle       The firmware allocated handle for the EFI image.
> +  @param  SystemTable       A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS       The entry point is executed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeLogo (
> +  IN EFI_HANDLE               ImageHandle,
> +  IN EFI_SYSTEM_TABLE         *SystemTable
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
> +  EFI_HII_DATABASE_PROTOCOL   *HiiDatabase;
> +  EFI_HANDLE                  Handle;
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiDatabaseProtocolGuid,
> +                  NULL,
> +                  (VOID **) &HiiDatabase
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiImageExProtocolGuid,
> +                  NULL,
> +                  (VOID **) &mHiiImageEx
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Retrieve HII package list from ImageHandle
> +  //
> +  Status = gBS->OpenProtocol (
> +                  ImageHandle,
> +                  &gEfiHiiPackageListProtocolGuid,
> +                  (VOID **) &PackageList,
> +                  ImageHandle,
> +                  NULL,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "HII Image Package with logo not found in
> PE/COFF resource section\n"));
> +    return Status;
> +  }
> +
> +  //
> +  // Publish HII package list to HII Database.
> +  //
> +  Status = HiiDatabase->NewPackageList (
> +                          HiiDatabase,
> +                          PackageList,
> +                          NULL,
> +                          &mHiiHandle
> +                          );
> +  if (!EFI_ERROR (Status)) {
> +    Handle = NULL;
> +    Status = gBS->InstallMultipleProtocolInterfaces (
> +                    &Handle,
> +                    &gEdkiiPlatformLogoProtocolGuid, &mPlatformLogo,
> +                    NULL
> +                    );
> +  }
> +  return Status;
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf
> 8/PciLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf
> 8/PciLib.c
> new file mode 100644
> index 0000000000..7544117a03
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf
> 8/PciLib.c
> @@ -0,0 +1,1221 @@
> +/** @file
> +  PCI Library functions that use
> +  (a) I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles, layering
> +      on top of one PCI CF8 Library instance; or
> +  (b) PCI Library functions that use the 256 MB PCI Express MMIO window to
> +      perform PCI Configuration cycles, layering on PCI Express Library.
> +
> +  The decision is made in the entry point function, based on the OVMF platform
> +  type, and then adhered to during the lifetime of the client module.
> +
> +  Copyright (C) 2016, Red Hat, Inc.
> +  Copyright (c) 2006 - 2012 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Base.h>
> +
> +#include <IndustryStandard/X58Ich10.h>
> +
> +#include <Library/PciLib.h>
> +#include <Library/PciCf8Lib.h>
> +#include <Library/PciExpressLib.h>
> +#include <Library/PcdLib.h>
> +
> +STATIC BOOLEAN mRunningOnIch10;
> +
> +RETURN_STATUS
> +EFIAPI
> +InitializeConfigAccessMethod (
> +  VOID
> +  )
> +{
> +  mRunningOnIch10 = (PcdGet16 (PcdSimicsX58HostBridgePciDevId) ==
> +                   INTEL_ICH10_DEVICE_ID);
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Registers a PCI device so PCI configuration registers may be accessed after
> +  SetVirtualAddressMap().
> +
> +  Registers the PCI device specified by Address so all the PCI configuration
> registers
> +  associated with that PCI device may be accessed after SetVirtualAddressMap()
> is called.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @retval RETURN_SUCCESS           The PCI device was registered for runtime
> access.
> +  @retval RETURN_UNSUPPORTED       An attempt was made to call this
> function
> +                                   after ExitBootServices().
> +  @retval RETURN_UNSUPPORTED       The resources required to access the PCI
> device
> +                                   at runtime could not be mapped.
> +  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources
> available to
> +                                   complete the registration.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +PciRegisterForRuntimeAccess (
> +  IN UINTN  Address
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressRegisterForRuntimeAccess (Address) :
> +         PciCf8RegisterForRuntimeAccess (Address);
> +}
> +
> +/**
> +  Reads an 8-bit PCI configuration register.
> +
> +  Reads and returns the 8-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciRead8 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressRead8 (Address) :
> +         PciCf8Read8 (Address);
> +}
> +
> +/**
> +  Writes an 8-bit PCI configuration register.
> +
> +  Writes the 8-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciWrite8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     Value
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressWrite8 (Address, Value) :
> +         PciCf8Write8 (Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of an 8-bit PCI configuration register with
> +  an 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressOr8 (Address, OrData) :
> +         PciCf8Or8 (Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> +  value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciAnd8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     AndData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressAnd8 (Address, AndData) :
> +         PciCf8And8 (Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> +  value, followed a  bitwise OR with another 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciAndThenOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     AndData,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressAndThenOr8 (Address, AndData, OrData) :
> +         PciCf8AndThenOr8 (Address, AndData, OrData);
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in an 8-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciBitFieldRead8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldRead8 (Address, StartBit, EndBit) :
> +         PciCf8BitFieldRead8 (Address, StartBit, EndBit);
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  8-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit,
> then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciBitFieldWrite8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     Value
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value) :
> +         PciCf8BitFieldWrite8 (Address, StartBit, EndBit, Value);
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciBitFieldOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData) :
> +         PciCf8BitFieldOr8 (Address, StartBit, EndBit, OrData);
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 8-bit register.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciBitFieldAnd8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     AndData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData) :
> +         PciCf8BitFieldAnd8 (Address, StartBit, EndBit, AndData);
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciBitFieldAndThenOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     AndData,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData,
> OrData) :
> +         PciCf8BitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData);
> +}
> +
> +/**
> +  Reads a 16-bit PCI configuration register.
> +
> +  Reads and returns the 16-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciRead16 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressRead16 (Address) :
> +         PciCf8Read16 (Address);
> +}
> +
> +/**
> +  Writes a 16-bit PCI configuration register.
> +
> +  Writes the 16-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    Value
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressWrite16 (Address, Value) :
> +         PciCf8Write16 (Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 16-bit PCI configuration register with
> +  a 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressOr16 (Address, OrData) :
> +         PciCf8Or16 (Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> +  value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 16-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressAnd16 (Address, AndData) :
> +         PciCf8And16 (Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> +  value, followed a  bitwise OR with another 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressAndThenOr16 (Address, AndData, OrData) :
> +         PciCf8AndThenOr16 (Address, AndData, OrData);
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 16-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciBitFieldRead16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldRead16 (Address, StartBit, EndBit) :
> +         PciCf8BitFieldRead16 (Address, StartBit, EndBit);
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  16-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit,
> then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciBitFieldWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    Value
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value) :
> +         PciCf8BitFieldWrite16 (Address, StartBit, EndBit, Value);
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciBitFieldOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData) :
> +         PciCf8BitFieldOr16 (Address, StartBit, EndBit, OrData);
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 16-bit register.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 16-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciBitFieldAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData) :
> +         PciCf8BitFieldAnd16 (Address, StartBit, EndBit, AndData);
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciBitFieldAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData,
> OrData) :
> +         PciCf8BitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData);
> +}
> +
> +/**
> +  Reads a 32-bit PCI configuration register.
> +
> +  Reads and returns the 32-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciRead32 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressRead32 (Address) :
> +         PciCf8Read32 (Address);
> +}
> +
> +/**
> +  Writes a 32-bit PCI configuration register.
> +
> +  Writes the 32-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    Value
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressWrite32 (Address, Value) :
> +         PciCf8Write32 (Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 32-bit PCI configuration register with
> +  a 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressOr32 (Address, OrData) :
> +         PciCf8Or32 (Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> +  value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 32-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressAnd32 (Address, AndData) :
> +         PciCf8And32 (Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> +  value, followed a  bitwise OR with another 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressAndThenOr32 (Address, AndData, OrData) :
> +         PciCf8AndThenOr32 (Address, AndData, OrData);
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 32-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciBitFieldRead32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldRead32 (Address, StartBit, EndBit) :
> +         PciCf8BitFieldRead32 (Address, StartBit, EndBit);
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  32-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit,
> then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciBitFieldWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    Value
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value) :
> +         PciCf8BitFieldWrite32 (Address, StartBit, EndBit, Value);
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciBitFieldOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData) :
> +         PciCf8BitFieldOr32 (Address, StartBit, EndBit, OrData);
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 32-bit register.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 32-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciBitFieldAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData) :
> +         PciCf8BitFieldAnd32 (Address, StartBit, EndBit, AndData);
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and
> EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciBitFieldAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData,
> OrData) :
> +         PciCf8BitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData);
> +}
> +
> +/**
> +  Reads a range of PCI configuration registers into a caller supplied buffer.
> +
> +  Reads the range of PCI configuration registers specified by StartAddress and
> +  Size into the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be read. Size is
> +  returned. When possible 32-bit PCI configuration read cycles are used to read
> +  from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
> +  and 16-bit PCI configuration read cycles may be used at the beginning and the
> +  end of the range.
> +
> +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> +                        Function and Register.
> +  @param  Size          The size in bytes of the transfer.
> +  @param  Buffer        The pointer to a buffer receiving the data read.
> +
> +  @return Size
> +
> +**/
> +UINTN
> +EFIAPI
> +PciReadBuffer (
> +  IN      UINTN                     StartAddress,
> +  IN      UINTN                     Size,
> +  OUT     VOID                      *Buffer
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressReadBuffer (StartAddress, Size, Buffer) :
> +         PciCf8ReadBuffer (StartAddress, Size, Buffer);
> +}
> +
> +/**
> +  Copies the data in a caller supplied buffer to a specified range of PCI
> +  configuration space.
> +
> +  Writes the range of PCI configuration registers specified by StartAddress and
> +  Size from the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be written. Size is
> +  returned. When possible 32-bit PCI configuration write cycles are used to
> +  write from StartAdress to StartAddress + Size. Due to alignment restrictions,
> +  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
> +  and the end of the range.
> +
> +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> +                        Function and Register.
> +  @param  Size          The size in bytes of the transfer.
> +  @param  Buffer        The pointer to a buffer containing the data to write.
> +
> +  @return Size written to StartAddress.
> +
> +**/
> +UINTN
> +EFIAPI
> +PciWriteBuffer (
> +  IN      UINTN                     StartAddress,
> +  IN      UINTN                     Size,
> +  IN      VOID                      *Buffer
> +  )
> +{
> +  return mRunningOnIch10 ?
> +         PciExpressWriteBuffer (StartAddress, Size, Buffer) :
> +         PciCf8WriteBuffer (StartAddress, Size, Buffer);
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.c
> new file mode 100644
> index 0000000000..b1d7552792
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.c
> @@ -0,0 +1,1579 @@
> +/** @file
> +  ACPI Platform Driver
> +
> +  Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "AcpiPlatform.h"
> +
> +#define MAX_CPU_NUM (FixedPcdGet32(PcdMaxCpuThreadCount) *
> FixedPcdGet32(PcdMaxCpuCoreCount) *
> FixedPcdGet32(PcdMaxCpuSocketCount))
> +
> +#pragma pack(1)
> +
> +typedef struct {
> +  UINT32   AcpiProcessorId;
> +  UINT32   ApicId;
> +  UINT32   Flags;
> +  UINT32   SwProcApicId;
> +  UINT32   SocketNum;
> +} EFI_CPU_ID_ORDER_MAP;
> +
> +//
> +// Private Driver Data
> +//
> +//
> +// Define Union of IO APIC & Local APIC structure;
> +//
> +typedef union {
> +  EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
> +  EFI_ACPI_4_0_IO_APIC_STRUCTURE              AcpiIoApic;
> +  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE AcpiLocalx2Apic;
> +  struct {
> +    UINT8 Type;
> +    UINT8 Length;
> +  } AcpiApicCommon;
> +} ACPI_APIC_STRUCTURE_PTR;
> +
> +#pragma pack()
> +
> +extern EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  Facs;
> +extern EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt;
> +extern EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER  Hpet;
> +extern EFI_ACPI_WSMT_TABLE Wsmt;
> +
> +VOID  *mLocalTable[] = {
> +  &Facs,
> +  &Fadt,
> +  &Hpet,
> +  &Wsmt,
> +};
> +
> +EFI_ACPI_TABLE_PROTOCOL       *mAcpiTable;
> +
> +UINT32                      mNumOfBitShift = 6;
> +BOOLEAN                     mForceX2ApicId;
> +BOOLEAN                     mX2ApicEnabled;
> +
> +EFI_MP_SERVICES_PROTOCOL    *mMpService;
> +BOOLEAN                     mCpuOrderSorted;
> +EFI_CPU_ID_ORDER_MAP        mCpuApicIdOrderTable[MAX_CPU_NUM];
> +UINTN                       mNumberOfCPUs = 0;
> +UINTN                       mNumberOfEnabledCPUs = 0;
> +//
> +// following are possible APICID Map for SKX
> +//
> +static const UINT32 ApicIdMapA[] = {  //for SKUs have number of core > 16
> +  //it is 14 + 14 + 14 + 14 format
> +  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004,
> 0x00000005, 0x00000006, 0x00000007,
> +  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C,
> 0x0000000D, 0x00000010, 0x00000011,
> +  0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016,
> 0x00000017, 0x00000018, 0x00000019,
> +  0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x00000020,
> 0x00000021, 0x00000022, 0x00000023,
> +  0x00000024, 0x00000025, 0x00000026, 0x00000027, 0x00000028,
> 0x00000029, 0x0000002A, 0x0000002B,
> +  0x0000002C, 0x0000002D, 0x00000030, 0x00000031, 0x00000032,
> 0x00000033, 0x00000034, 0x00000035,
> +  0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000003A,
> 0x0000003B, 0x0000003C, 0x0000003D
> +};
> +
> +static const UINT32 ApicIdMapB[] = { //for SKUs have number of cores <= 16
> use 32 ID space
> +  //
> +  //it is 16+16 format
> +  //
> +  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004,
> 0x00000005, 0x00000006, 0x00000007,
> +  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C,
> 0x0000000D, 0x0000000E, 0x0000000F,
> +  0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014,
> 0x00000015, 0x00000016, 0x00000017,
> +  0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C,
> 0x0000001D, 0x0000001E, 0x0000001F,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF
> +};
> +
> +
> +static const UINT32 ApicIdMapC[] = { //for SKUs have number of cores <= 16
> use 64 ID space
> +  //
> +  //it is 16+0+16+0 format
> +  //
> +  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004,
> 0x00000005, 0x00000006, 0x00000007,
> +  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C,
> 0x0000000D, 0x0000000E, 0x0000000F,
> +  0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024,
> 0x00000025, 0x00000026, 0x00000027,
> +  0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C,
> 0x0000002D, 0x0000002E, 0x0000002F,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF
> +};
> +
> +static const UINT32 ApicIdMapD[] = { //for SKUs have number of cores <= 8
> use 16 ID space
> +  //
> +  //it is 16 format
> +  //
> +  0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004,
> 0x00000005, 0x00000006, 0x00000007,
> +  0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C,
> 0x0000000D, 0x0000000E, 0x0000000F,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF,
> +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> 0xFFFFFFFF, 0xFFFFFFFF
> +};
> +
> +const UINT32 *mApicIdMap = NULL;
> +
> +/**
> +  This function detect the APICID map and update ApicID Map pointer
> +
> +  @param None
> +
> +  @retval VOID
> +
> +**/
> +VOID DetectApicIdMap(VOID)
> +{
> +  UINTN                  CoreCount;
> +
> +  CoreCount = 0;
> +
> +  if(mApicIdMap != NULL) {
> +    return;   //aleady initialized
> +  }
> +
> +  mApicIdMap = ApicIdMapA;  // default to > 16C SKUs
> +
> +  CoreCount = mNumberOfEnabledCPUs / 2;
> +  DEBUG ((DEBUG_INFO, "CoreCount - %d\n", CoreCount));
> +
> +  if(CoreCount <= 16) {
> +
> +    if(mNumOfBitShift == 4) {
> +      mApicIdMap = ApicIdMapD;
> +    }
> +
> +    if(mNumOfBitShift == 5) {
> +      mApicIdMap = ApicIdMapB;
> +    }
> +
> +    if(mNumOfBitShift == 6) {
> +      mApicIdMap = ApicIdMapC;
> +    }
> +
> +  }
> +
> +  return;
> +}
> +
> +/**
> +  This function return the CoreThreadId of ApicId from ACPI ApicId Map array
> +
> +  @param ApicId
> +
> +  @retval Index of ACPI ApicId Map array
> +
> +**/
> +UINT32
> +GetIndexFromApicId (
> +  UINT32 ApicId
> +  )
> +{
> +  UINT32 CoreThreadId;
> +  UINT32 i;
> +
> +  ASSERT (mApicIdMap != NULL);
> +
> +  CoreThreadId = ApicId & ((1 << mNumOfBitShift) - 1);
> +
> +  for(i = 0; i < (FixedPcdGet32(PcdMaxCpuCoreCount) *
> FixedPcdGet32(PcdMaxCpuThreadCount)); i++) {
> +    if(mApicIdMap[i] == CoreThreadId) {
> +      break;
> +    }
> +  }
> +
> +  ASSERT (i <= (FixedPcdGet32(PcdMaxCpuCoreCount) *
> FixedPcdGet32(PcdMaxCpuThreadCount)));
> +
> +  return i;
> +}
> +
> +UINT32
> +ApicId2SwProcApicId (
> +  UINT32 ApicId
> +  )
> +{
> +  UINT32 Index;
> +
> +  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
> +    if ((mCpuApicIdOrderTable[Index].Flags == 1) &&
> (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
> +      return Index;
> +    }
> +  }
> +
> +  return (UINT32) -1;
> +
> +}
> +
> +VOID
> +DebugDisplayReOrderTable(
> +  VOID
> +  )
> +{
> +  UINT32 Index;
> +
> +  DEBUG ((EFI_D_ERROR, "Index  AcpiProcId  ApicId  Flags  SwApicId  Skt\n"));
> +  for (Index=0; Index<MAX_CPU_NUM; Index++) {
> +    DEBUG ((EFI_D_ERROR, " %02d       0x%02X      0x%02X      %d      0x%02X
> %d\n",
> +                           Index, mCpuApicIdOrderTable[Index].AcpiProcessorId,
> +                           mCpuApicIdOrderTable[Index].ApicId,
> +                           mCpuApicIdOrderTable[Index].Flags,
> +                           mCpuApicIdOrderTable[Index].SwProcApicId,
> +                           mCpuApicIdOrderTable[Index].SocketNum));
> +  }
> +}
> +
> +EFI_STATUS
> +AppendCpuMapTableEntry (
> +    IN VOID   *ApicPtr,
> +    IN UINT32 LocalApicCounter
> +  )
> +{
> +  EFI_STATUS    Status;
> +  EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApicPtr;
> +  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *LocalX2ApicPtr;
> +  UINT8         Type;
> +
> +  Status = EFI_SUCCESS;
> +  Type = ((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiApicCommon.Type;
> +  LocalApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE
> *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalApic);
> +  LocalX2ApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE
> *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalx2Apic);
> +
> +  if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC) {
> +    if(!mX2ApicEnabled) {
> +      LocalApicPtr->Flags           =
> (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
> +      LocalApicPtr->ApicId          =
> (UINT8)mCpuApicIdOrderTable[LocalApicCounter].ApicId;
> +      LocalApicPtr->AcpiProcessorId =
> (UINT8)mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
> +    } else {
> +      LocalApicPtr->Flags           = 0;
> +      LocalApicPtr->ApicId          = 0xFF;
> +      LocalApicPtr->AcpiProcessorId = (UINT8)0xFF;
> +      Status = EFI_UNSUPPORTED;
> +    }
> +  } else if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC) {
> +    if(mX2ApicEnabled) {
> +      LocalX2ApicPtr->Flags            =
> (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
> +      LocalX2ApicPtr->X2ApicId         =
> mCpuApicIdOrderTable[LocalApicCounter].ApicId;
> +      LocalX2ApicPtr->AcpiProcessorUid =
> mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
> +    } else {
> +      LocalX2ApicPtr->Flags            = 0;
> +      LocalX2ApicPtr->X2ApicId         = (UINT32)-1;
> +      LocalX2ApicPtr->AcpiProcessorUid = (UINT32)-1;
> +      Status = EFI_UNSUPPORTED;
> +    }
> +  } else {
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +  return Status;
> +
> +}
> +
> +EFI_STATUS
> +SortCpuLocalApicInTable (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                Status;
> +  EFI_PROCESSOR_INFORMATION                 ProcessorInfoBuffer;
> +  UINT32                                    Index;
> +  UINT32                                    CurrProcessor;
> +  UINT32                                    BspApicId;
> +  UINT32                                    TempVal = 0;
> +  EFI_CPU_ID_ORDER_MAP                      *CpuIdMapPtr;
> +  UINT32                                    CoreThreadMask;
> +
> +  Index      = 0;
> +  Status     = EFI_SUCCESS;
> +
> +  CoreThreadMask = (UINT32) ((1 << mNumOfBitShift) - 1);
> +
> +  if(!mCpuOrderSorted) {
> +
> +    Index  = 0;
> +
> +    for (CurrProcessor = 0; CurrProcessor < mNumberOfCPUs; CurrProcessor++)
> {
> +      Status = mMpService->GetProcessorInfo (
> +                                            mMpService,
> +                                            CurrProcessor,
> +                                            &ProcessorInfoBuffer
> +                                            );
> +
> +      if ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0) {
> +        if(ProcessorInfoBuffer.ProcessorId & 1) { //is 2nd thread
> +          CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP
> *)&mCpuApicIdOrderTable[(Index - 1) + MAX_CPU_NUM / 2];
> +        } else { //is primary thread
> +          CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP
> *)&mCpuApicIdOrderTable[Index];
> +          Index++;
> +        }
> +        CpuIdMapPtr->ApicId  = (UINT32)ProcessorInfoBuffer.ProcessorId;
> +        CpuIdMapPtr->Flags   = ((ProcessorInfoBuffer.StatusFlag &
> PROCESSOR_ENABLED_BIT) != 0);
> +        CpuIdMapPtr->SocketNum =
> (UINT32)ProcessorInfoBuffer.Location.Package;
> +        CpuIdMapPtr->AcpiProcessorId = (CpuIdMapPtr->SocketNum *
> FixedPcdGet32(PcdMaxCpuCoreCount) *
> FixedPcdGet32(PcdMaxCpuThreadCount)) +
> GetIndexFromApicId(CpuIdMapPtr->ApicId); //CpuIdMapPtr->ApicId;
> +        CpuIdMapPtr->SwProcApicId =
> ((UINT32)(ProcessorInfoBuffer.Location.Package << mNumOfBitShift) +
> (((UINT32)ProcessorInfoBuffer.ProcessorId) & CoreThreadMask));
> +        if(mX2ApicEnabled) { //if X2Apic, re-order the socket # so it starts from
> base 0 and contiguous
> +          //may not necessory!!!!!
> +        }
> +
> +        //update processorbitMask
> +        if (CpuIdMapPtr->Flags == 1) {
> +
> +          if(mForceX2ApicId) {
> +            CpuIdMapPtr->SocketNum &= 0x7;
> +            CpuIdMapPtr->AcpiProcessorId &= 0xFF; //keep lower 8bit due to use
> Proc obj in dsdt
> +            CpuIdMapPtr->SwProcApicId &= 0xFF;
> +          }
> +        }
> +      } else {  //not enabled
> +        CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP
> *)&mCpuApicIdOrderTable[Index];
> +        CpuIdMapPtr->ApicId  = (UINT32)-1;
> +        CpuIdMapPtr->Flags   = 0;
> +        CpuIdMapPtr->AcpiProcessorId = (UINT32)-1;
> +        CpuIdMapPtr->SwProcApicId = (UINT32)-1;
> +        CpuIdMapPtr->SocketNum = (UINT32)-1;
> +      } //end if PROC ENABLE
> +    } //end for CurrentProcessor
> +    //
> +    //keep for debug purpose
> +	//
> +    DEBUG(( EFI_D_ERROR, "::ACPI::  APIC ID Order Table Init.
> CoreThreadMask = %x,  mNumOfBitShift = %x\n", CoreThreadMask,
> mNumOfBitShift));
> +    DebugDisplayReOrderTable();
> +    //
> +    //make sure 1st entry is BSP
> +	//
> +    if(mX2ApicEnabled) {
> +      BspApicId = (UINT32)AsmReadMsr64(0x802);
> +    } else {
> +      BspApicId = (*(volatile UINT32 *)(UINTN)0xFEE00020) >> 24;
> +    }
> +    DEBUG ((EFI_D_INFO, "BspApicId - 0x%x\n", BspApicId));
> +
> +    if(mCpuApicIdOrderTable[0].ApicId != BspApicId) {
> +      //
> +      //check to see if 1st entry is BSP, if not swap it
> +	  //
> +      Index = ApicId2SwProcApicId(BspApicId);
> +
> +      if(MAX_CPU_NUM <= Index) {
> +        DEBUG ((EFI_D_ERROR, "Asserting the SortCpuLocalApicInTable Index
> Bufferflow\n"));
> +        ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
> +      }
> +
> +      TempVal = mCpuApicIdOrderTable[Index].ApicId;
> +      mCpuApicIdOrderTable[Index].ApicId = mCpuApicIdOrderTable[0].ApicId;
> +      mCpuApicIdOrderTable[0].ApicId = TempVal;
> +      mCpuApicIdOrderTable[Index].Flags = mCpuApicIdOrderTable[0].Flags;
> +      mCpuApicIdOrderTable[0].Flags = 1;
> +      TempVal = mCpuApicIdOrderTable[Index].SwProcApicId;
> +      mCpuApicIdOrderTable[Index].SwProcApicId =
> mCpuApicIdOrderTable[0].SwProcApicId;
> +      mCpuApicIdOrderTable[0].SwProcApicId = TempVal;
> +      //
> +      //swap AcpiProcId
> +	  //
> +      TempVal = mCpuApicIdOrderTable[Index].AcpiProcessorId;
> +      mCpuApicIdOrderTable[Index].AcpiProcessorId =
> mCpuApicIdOrderTable[0].AcpiProcessorId;
> +      mCpuApicIdOrderTable[0].AcpiProcessorId = TempVal;
> +
> +    }
> +    //
> +    //Make sure no holes between enabled threads
> +	//
> +    for(CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
> +
> +      if(mCpuApicIdOrderTable[CurrProcessor].Flags == 0) {
> +        //
> +        //make sure disabled entry has ProcId set to FFs
> +		//
> +        mCpuApicIdOrderTable[CurrProcessor].ApicId = (UINT32)-1;
> +        mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = (UINT32)-1;
> +        mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = (UINT32)-1;
> +
> +        for(Index = CurrProcessor+1; Index < MAX_CPU_NUM; Index++) {
> +          if(mCpuApicIdOrderTable[Index].Flags == 1) {
> +            //
> +            //move enabled entry up
> +			//
> +            mCpuApicIdOrderTable[CurrProcessor].Flags = 1;
> +            mCpuApicIdOrderTable[CurrProcessor].ApicId =
> mCpuApicIdOrderTable[Index].ApicId;
> +            mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId =
> mCpuApicIdOrderTable[Index].AcpiProcessorId;
> +            mCpuApicIdOrderTable[CurrProcessor].SwProcApicId =
> mCpuApicIdOrderTable[Index].SwProcApicId;
> +            mCpuApicIdOrderTable[CurrProcessor].SocketNum =
> mCpuApicIdOrderTable[Index].SocketNum;
> +            //
> +            //disable moved entry
> +            //
> +            mCpuApicIdOrderTable[Index].Flags = 0;
> +            mCpuApicIdOrderTable[Index].ApicId = (UINT32)-1;
> +            mCpuApicIdOrderTable[Index].AcpiProcessorId = (UINT32)-1;
> +            mCpuApicIdOrderTable[Index].SwProcApicId = (UINT32)-1;
> +            break;
> +          }
> +        }
> +      }
> +    }
> +    //
> +    //keep for debug purpose
> +    //
> +    DEBUG ((EFI_D_ERROR, "APIC ID Order Table ReOrdered\n"));
> +    DebugDisplayReOrderTable();
> +
> +    mCpuOrderSorted = TRUE;
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/** Structure of a sub-structure of the ACPI header.
> +
> +  This structure contains the type and length fields, which are common to every
> +  sub-structure of the ACPI tables. A pointer to any structure can be cast as this.
> +**/
> +typedef struct {
> +  UINT8 Type;
> +  UINT8 Length;
> +} STRUCTURE_HEADER;
> +
> +STRUCTURE_HEADER mMadtStructureTable[] = {
> +  {EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC,          sizeof
> (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE)},
> +  {EFI_ACPI_4_0_IO_APIC,                       sizeof
> (EFI_ACPI_4_0_IO_APIC_STRUCTURE)},
> +  {EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE,     sizeof
> (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE)},
> +  {EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE, sizeof
> (EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE)},
> +  {EFI_ACPI_4_0_LOCAL_APIC_NMI,                sizeof
> (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE)},
> +  {EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE,   sizeof
> (EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE)},
> +  {EFI_ACPI_4_0_IO_SAPIC,                      sizeof
> (EFI_ACPI_4_0_IO_SAPIC_STRUCTURE)},
> +  {EFI_ACPI_4_0_LOCAL_SAPIC,                   sizeof
> (EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE)},
> +  {EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES,    sizeof
> (EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE)},
> +  {EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC,        sizeof
> (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE)},
> +  {EFI_ACPI_4_0_LOCAL_X2APIC_NMI,              sizeof
> (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE)}
> +};
> +
> +/**
> +  Get the size of the ACPI table.
> +
> +  This function calculates the size needed for the ACPI Table based on the
> number and
> +  size of the sub-structures that will compose it.
> +
> +  @param[in]  TableSpecificHdrLength  Size of the table specific header, not the
> ACPI standard header size.
> +  @param[in]  Structures              Pointer to an array of sub-structure pointers.
> +  @param[in]  StructureCount          Number of structure pointers in the array.
> +
> +  @return     Total size needed for the ACPI table.
> +**/
> +UINT32
> +GetTableSize (
> +  IN  UINTN                 TableSpecificHdrLength,
> +  IN  STRUCTURE_HEADER      **Structures,
> +  IN  UINTN                 StructureCount
> +  )
> +{
> +  UINT32  TableLength;
> +  UINT32  Index;
> +
> +  //
> +  // Compute size of the ACPI table; header plus all structures needed.
> +  //
> +  TableLength = (UINT32) TableSpecificHdrLength;
> +
> +  for (Index = 0; Index < StructureCount; Index++) {
> +    ASSERT (Structures[Index] != NULL);
> +    if (Structures[Index] == NULL) {
> +      return 0;
> +    }
> +
> +    TableLength += Structures[Index]->Length;
> +  }
> +
> +  return TableLength;
> +}
> +
> +/**
> +  Allocate the ACPI Table.
> +
> +  This function allocates space for the ACPI table based on the number and size
> of
> +  the sub-structures that will compose it.
> +
> +  @param[in]  TableSpecificHdrLength  Size of the table specific header, not the
> ACPI standard header size.
> +  @param[in]  Structures  Pointer to an array of sub-structure pointers.
> +  @param[in]  StructureCount  Number of structure pointers in the array.
> +  @param[out] Table            Newly allocated ACPI Table pointer.
> +
> +  @retval EFI_SUCCESS           Successfully allocated the Table.
> +  @retval EFI_OUT_OF_RESOURCES  Space for the Table could not be
> allocated.
> +**/
> +EFI_STATUS
> +AllocateTable (
> +  IN  UINTN                        TableSpecificHdrLength,
> +  IN  STRUCTURE_HEADER             **Structures,
> +  IN  UINTN                        StructureCount,
> +  OUT EFI_ACPI_DESCRIPTION_HEADER  **Table
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32      Size;
> +  EFI_ACPI_DESCRIPTION_HEADER *InternalTable;
> +
> +  //
> +  // Get the size of the ACPI table and allocate memory.
> +  //
> +  Size = GetTableSize (TableSpecificHdrLength, Structures, StructureCount);
> +  InternalTable = (EFI_ACPI_DESCRIPTION_HEADER *) AllocatePool (Size);
> +
> +  if (InternalTable == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "Failed to allocate %d bytes for ACPI Table\n",
> +      Size
> +      ));
> +  } else {
> +    Status = EFI_SUCCESS;
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "Successfully allocated %d bytes for ACPI Table at 0x%p\n",
> +      Size,
> +      InternalTable
> +      ));
> +    *Table = InternalTable;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Initialize the header.
> +
> +  This function fills in the standard table header with correct values,
> +  except for the length and checksum fields, which are filled in later.
> +
> +  @param[in,out]  Header        Pointer to the header structure.
> +
> +  @retval EFI_SUCCESS           Successfully initialized the header.
> +  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
> +**/
> +EFI_STATUS
> +InitializeHeader (
> +  IN OUT  EFI_ACPI_DESCRIPTION_HEADER *Header,
> +  IN      UINT32                      Signature,
> +  IN      UINT8                       Revision,
> +  IN      UINT32                      OemRevision
> +  )
> +{
> +  UINT64 AcpiTableOemId;
> +
> +  if (Header == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Header pointer is NULL\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Header->Signature  = Signature;
> +  Header->Length     = 0; // filled in by Build function
> +  Header->Revision   = Revision;
> +  Header->Checksum   = 0; // filled in by InstallAcpiTable
> +
> +  CopyMem (
> +    (VOID *) &Header->OemId,
> +    PcdGetPtr (PcdAcpiDefaultOemId),
> +    sizeof (Header->OemId)
> +    );
> +
> +  AcpiTableOemId = PcdGet64 (PcdAcpiDefaultOemTableId);
> +  CopyMem (
> +    (VOID *) &Header->OemTableId,
> +    (VOID *) &AcpiTableOemId,
> +    sizeof (Header->OemTableId)
> +    );
> +
> +  Header->OemRevision     = OemRevision;
> +  Header->CreatorId       = 0;
> +  Header->CreatorRevision = 0;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Initialize the MADT header.
> +
> +  This function fills in the MADT's standard table header with correct values,
> +  except for the length and checksum fields, which are filled in later.
> +
> +  @param[in,out]  MadtHeader    Pointer to the MADT header structure.
> +
> +  @retval EFI_SUCCESS           Successfully initialized the MADT header.
> +  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
> +**/
> +EFI_STATUS
> +InitializeMadtHeader (
> +  IN OUT EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
> *MadtHeader
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  if (MadtHeader == NULL) {
> +    DEBUG ((DEBUG_ERROR, "MADT header pointer is NULL\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = InitializeHeader (
> +    &MadtHeader->Header,
> +    EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
> +    EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
> +    0
> +    );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  MadtHeader->LocalApicAddress       = PcdGet32(PcdLocalApicAddress);
> +  MadtHeader->Flags                  = EFI_ACPI_4_0_PCAT_COMPAT;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Copy an ACPI sub-structure; MADT and SRAT supported
> +
> +  This function validates the structure type and size of a sub-structure
> +  and returns a newly allocated copy of it.
> +
> +  @param[in]  Header            Pointer to the header of the table.
> +  @param[in]  Structure         Pointer to the structure to copy.
> +  @param[in]  NewStructure      Newly allocated copy of the structure.
> +
> +  @retval EFI_SUCCESS           Successfully copied the structure.
> +  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
> +  @retval EFI_INVALID_PARAMETER Structure type was unknown.
> +  @retval EFI_INVALID_PARAMETER Structure length was wrong for its type.
> +  @retval EFI_UNSUPPORTED       Header passed in is not supported.
> +**/
> +EFI_STATUS
> +CopyStructure (
> +  IN  EFI_ACPI_DESCRIPTION_HEADER *Header,
> +  IN  STRUCTURE_HEADER *Structure,
> +  OUT STRUCTURE_HEADER **NewStructure
> +  )
> +{
> +  STRUCTURE_HEADER      *NewStructureInternal;
> +  STRUCTURE_HEADER      *StructureTable;
> +  UINTN                 TableNumEntries;
> +  BOOLEAN               EntryFound;
> +  UINT8                 Index;
> +
> +  //
> +  // Initialize the number of table entries and the table based on the table
> header passed in.
> +  //
> +  if (Header->Signature ==
> EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
> +    TableNumEntries = sizeof (mMadtStructureTable) / sizeof
> (STRUCTURE_HEADER);
> +    StructureTable = mMadtStructureTable;
> +  } else {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Check the incoming structure against the table of supported structures.
> +  //
> +  EntryFound = FALSE;
> +  for (Index = 0; Index < TableNumEntries; Index++) {
> +    if (Structure->Type == StructureTable[Index].Type) {
> +      if (Structure->Length == StructureTable[Index].Length) {
> +        EntryFound = TRUE;
> +      } else {
> +        DEBUG ((
> +          DEBUG_ERROR,
> +          "Invalid length for structure type %d: expected %d, actually %d\n",
> +          Structure->Type,
> +          StructureTable[Index].Length,
> +          Structure->Length
> +          ));
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +  }
> +
> +  //
> +  // If no entry in the table matches the structure type and length passed in
> +  // then return invalid parameter.
> +  //
> +  if (!EntryFound) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "Unknown structure type: %d\n",
> +      Structure->Type
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  NewStructureInternal = (STRUCTURE_HEADER *) AllocatePool (Structure-
> >Length);
> +  if (NewStructureInternal == NULL) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "Failed to allocate %d bytes for type %d structure\n",
> +      Structure->Length,
> +      Structure->Type
> +      ));
> +    return EFI_OUT_OF_RESOURCES;
> +  } else {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "Successfully allocated %d bytes for type %d structure at 0x%p\n",
> +      Structure->Length,
> +      Structure->Type,
> +      NewStructureInternal
> +      ));
> +  }
> +
> +  CopyMem (
> +    (VOID *) NewStructureInternal,
> +    (VOID *) Structure,
> +    Structure->Length
> +    );
> +
> +  *NewStructure = NewStructureInternal;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Build ACPI Table. MADT tables supported.
> +
> +  This function builds the ACPI table from the header plus the list of sub-
> structures
> +  passed in. The table returned by this function is ready to be installed using
> +  the ACPI table protocol's InstallAcpiTable function, which copies it into
> +  ACPI memory. After that, the caller should free the memory returned by this
> +  function.
> +
> +  @param[in]  AcpiHeader             Pointer to the header structure.
> +  @param[in]  TableSpecificHdrLength Size of the table specific header, not the
> ACPI standard header size.
> +  @param[in]  Structures             Pointer to an array of sub-structure pointers.
> +  @param[in]  StructureCount         Number of structure pointers in the array.
> +  @param[out] NewTable               Newly allocated and initialized pointer to the
> ACPI Table.
> +
> +  @retval EFI_SUCCESS           Successfully built the ACPI table.
> +  @retval EFI_INVALID_PARAMETER Pointer parameter was null.
> +  @retval EFI_INVALID_PARAMETER Header parameter had the wrong
> signature.
> +  @retval EFI_OUT_OF_RESOURCES  Space for the ACPI Table could not be
> allocated.
> +**/
> +EFI_STATUS
> +BuildAcpiTable (
> +  IN  EFI_ACPI_DESCRIPTION_HEADER  *AcpiHeader,
> +  IN  UINTN                        TableSpecificHdrLength,
> +  IN  STRUCTURE_HEADER             **Structures,
> +  IN  UINTN                        StructureCount,
> +  OUT UINT8                        **NewTable
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_ACPI_DESCRIPTION_HEADER *InternalTable;
> +  UINTN                       Index;
> +  UINT8                       *CurrPtr;
> +  UINT8                       *EndOfTablePtr;
> +
> +  if (AcpiHeader == NULL) {
> +    DEBUG ((DEBUG_ERROR, "AcpiHeader pointer is NULL\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (AcpiHeader->Signature !=
> EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "MADT header signature is expected, actually 0x%08x\n",
> +      AcpiHeader->Signature
> +      ));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Structures == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Structure array pointer is NULL\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  for (Index = 0; Index < StructureCount; Index++) {
> +    if (Structures[Index] == NULL) {
> +      DEBUG ((DEBUG_ERROR, "Structure pointer %d is NULL\n", Index));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  }
> +
> +  //
> +  // Allocate the memory needed for the table.
> +  //
> +  Status = AllocateTable (
> +    TableSpecificHdrLength,
> +    Structures,
> +    StructureCount,
> +    &InternalTable
> +    );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Copy Header and patch in structure length, checksum is programmed later
> +  // after all structures are populated.
> +  //
> +  CopyMem (
> +    (VOID *) InternalTable,
> +    (VOID *) AcpiHeader,
> +    TableSpecificHdrLength
> +    );
> +
> +  InternalTable->Length = GetTableSize (TableSpecificHdrLength, Structures,
> StructureCount);
> +
> +  //
> +  // Copy all the sub structures to the table.
> +  //
> +  CurrPtr = ((UINT8 *) InternalTable) + TableSpecificHdrLength;
> +  EndOfTablePtr = ((UINT8 *) InternalTable) + InternalTable->Length;
> +
> +  for (Index = 0; Index < StructureCount; Index++) {
> +    ASSERT (Structures[Index] != NULL);
> +    if (Structures[Index] == NULL) {
> +      break;
> +    }
> +
> +    CopyMem (
> +      (VOID *) CurrPtr,
> +      (VOID *) Structures[Index],
> +      Structures[Index]->Length
> +      );
> +
> +    CurrPtr += Structures[Index]->Length;
> +    ASSERT (CurrPtr <= EndOfTablePtr);
> +    if (CurrPtr > EndOfTablePtr) {
> +      break;
> +    }
> +  }
> +
> +  //
> +  // Update the return pointer.
> +  //
> +  *NewTable = (UINT8 *) InternalTable;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Build from scratch and install the MADT.
> +
> +  @retval EFI_SUCCESS           The MADT was installed successfully.
> +  @retval EFI_OUT_OF_RESOURCES  Could not allocate required structures.
> +**/
> +EFI_STATUS
> +InstallMadtFromScratch (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                          Status;
> +  UINTN                                               Index;
> +  EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
> *NewMadtTable;
> +  UINTN                                               TableHandle;
> +  EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
> MadtTableHeader;
> +  EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE
> ProcLocalApicStruct;
> +  EFI_ACPI_4_0_IO_APIC_STRUCTURE                      IoApicStruct;
> +  EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE
> IntSrcOverrideStruct;
> +  EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE               LocalApciNmiStruct;
> +  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE
> ProcLocalX2ApicStruct;
> +  EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE
> LocalX2ApicNmiStruct;
> +  STRUCTURE_HEADER                                    **MadtStructs;
> +  UINTN                                               MaxMadtStructCount;
> +  UINTN                                               MadtStructsIndex;
> +  UINT32                                              CurrentIoApicAddress =
> (UINT32)(PcdGet32(PcdPcIoApicAddressBase));
> +  UINT32                                              PcIoApicEnable;
> +  UINT32                                              PcIoApicMask;
> +  UINTN                                               PcIoApicIndex;
> +
> +  DetectApicIdMap();
> +
> +  // Call for Local APIC ID Reorder
> +  SortCpuLocalApicInTable ();
> +
> +  NewMadtTable = NULL;
> +
> +  MaxMadtStructCount = (UINT32) (
> +    MAX_CPU_NUM +    // processor local APIC structures
> +    MAX_CPU_NUM +    // processor local x2APIC structures
> +    1 + PcdGet8(PcdPcIoApicCount) +   // I/O APIC structures
> +    2 +              // interrupt source override structures
> +    1 +              // local APIC NMI structures
> +    1                // local x2APIC NMI structures
> +    );               // other structures are not used
> +
> +  MadtStructs = (STRUCTURE_HEADER **) AllocateZeroPool
> (MaxMadtStructCount * sizeof (STRUCTURE_HEADER *));
> +  if (MadtStructs == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Could not allocate MADT structure pointer
> array\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Initialize the next index into the structure pointer array. It is
> +  // incremented every time a structure of any type is copied to the array.
> +  //
> +  MadtStructsIndex = 0;
> +
> +  //
> +  // Initialize MADT Header Structure
> +  //
> +  Status = InitializeMadtHeader (&MadtTableHeader);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "InitializeMadtHeader failed: %r\n", Status));
> +    goto Done;
> +  }
> +
> +  DEBUG ((EFI_D_INFO, "Number of CPUs detected = %d \n",
> mNumberOfCPUs));
> +
> +  //
> +  // Build Processor Local APIC Structures and Processor Local X2APIC
> Structures
> +  //
> +  ProcLocalApicStruct.Type = EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC;
> +  ProcLocalApicStruct.Length = sizeof
> (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE);
> +
> +  ProcLocalX2ApicStruct.Type = EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC;
> +  ProcLocalX2ApicStruct.Length = sizeof
> (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE);
> +  ProcLocalX2ApicStruct.Reserved[0] = 0;
> +  ProcLocalX2ApicStruct.Reserved[1] = 0;
> +
> +  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
> +    //
> +    // If x2APIC mode is not enabled, and if it is possible to express the
> +    // APIC ID as a UINT8, use a processor local APIC structure. Otherwise,
> +    // use a processor local x2APIC structure.
> +    //
> +    if (!mX2ApicEnabled && mCpuApicIdOrderTable[Index].ApicId <
> MAX_UINT8) {
> +      ProcLocalApicStruct.Flags           = (UINT8)
> mCpuApicIdOrderTable[Index].Flags;
> +      ProcLocalApicStruct.ApicId          = (UINT8)
> mCpuApicIdOrderTable[Index].ApicId;
> +      ProcLocalApicStruct.AcpiProcessorId = (UINT8)
> mCpuApicIdOrderTable[Index].AcpiProcessorId;
> +
> +      ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +      Status = CopyStructure (
> +        &MadtTableHeader.Header,
> +        (STRUCTURE_HEADER *) &ProcLocalApicStruct,
> +        &MadtStructs[MadtStructsIndex++]
> +        );
> +    } else if (mCpuApicIdOrderTable[Index].ApicId != 0xFFFFFFFF) {
> +      ProcLocalX2ApicStruct.Flags            = (UINT8)
> mCpuApicIdOrderTable[Index].Flags;
> +      ProcLocalX2ApicStruct.X2ApicId         =
> mCpuApicIdOrderTable[Index].ApicId;
> +      ProcLocalX2ApicStruct.AcpiProcessorUid =
> mCpuApicIdOrderTable[Index].AcpiProcessorId;
> +
> +      ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +      Status = CopyStructure (
> +        &MadtTableHeader.Header,
> +        (STRUCTURE_HEADER *) &ProcLocalX2ApicStruct,
> +        &MadtStructs[MadtStructsIndex++]
> +        );
> +    }
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "CopyMadtStructure (local APIC/x2APIC) failed:
> %r\n", Status));
> +      goto Done;
> +    }
> +  }
> +
> +  //
> +  // Build I/O APIC Structures
> +  //
> +  IoApicStruct.Type = EFI_ACPI_4_0_IO_APIC;
> +  IoApicStruct.Length = sizeof (EFI_ACPI_4_0_IO_APIC_STRUCTURE);
> +  IoApicStruct.Reserved = 0;
> +
> +  PcIoApicEnable = PcdGet32(PcdPcIoApicEnable);
> +
> +  if (FixedPcdGet32(PcdMaxCpuSocketCount) <= 4) {
> +    IoApicStruct.IoApicId                  = PcdGet8(PcdIoApicId);
> +    IoApicStruct.IoApicAddress             = PcdGet32(PcdIoApicAddress);
> +    IoApicStruct.GlobalSystemInterruptBase = 0;
> +    ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +    Status = CopyStructure (
> +      &MadtTableHeader.Header,
> +      (STRUCTURE_HEADER *) &IoApicStruct,
> +      &MadtStructs[MadtStructsIndex++]
> +      );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((EFI_D_ERROR, "CopyMadtStructure (I/O APIC) failed: %r\n",
> Status));
> +      goto Done;
> +    }
> +  }
> +
> +  for (PcIoApicIndex = 0; PcIoApicIndex < PcdGet8(PcdPcIoApicCount);
> PcIoApicIndex++) {
> +      PcIoApicMask = (1 << PcIoApicIndex);
> +      if ((PcIoApicEnable & PcIoApicMask) == 0) {
> +        continue;
> +      }
> +
> +      IoApicStruct.IoApicId                  = (UINT8)(PcdGet8(PcdPcIoApicIdBase) +
> PcIoApicIndex);
> +      IoApicStruct.IoApicAddress             = CurrentIoApicAddress;
> +      CurrentIoApicAddress                   = (CurrentIoApicAddress & 0xFFFF8000) +
> 0x8000;
> +      IoApicStruct.GlobalSystemInterruptBase = (UINT32)(24 + (PcIoApicIndex *
> 8));
> +      ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +      Status = CopyStructure (
> +        &MadtTableHeader.Header,
> +        (STRUCTURE_HEADER *) &IoApicStruct,
> +        &MadtStructs[MadtStructsIndex++]
> +        );
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((EFI_D_ERROR, "CopyMadtStructure (I/O APIC) failed: %r\n",
> Status));
> +        goto Done;
> +      }
> +  }
> +
> +  //
> +  // Build Interrupt Source Override Structures
> +  //
> +  IntSrcOverrideStruct.Type = EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE;
> +  IntSrcOverrideStruct.Length = sizeof
> (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
> +
> +  //
> +  // IRQ0=>IRQ2 Interrupt Source Override Structure
> +  //
> +  IntSrcOverrideStruct.Bus = 0x0;                   // Bus - ISA
> +  IntSrcOverrideStruct.Source = 0x0;                // Source - IRQ0
> +  IntSrcOverrideStruct.GlobalSystemInterrupt = 0x2; // Global System Interrupt
> - IRQ2
> +  IntSrcOverrideStruct.Flags = 0x0;                 // Flags - Conforms to specifications
> of the bus
> +
> +  ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +  Status = CopyStructure (
> +    &MadtTableHeader.Header,
> +    (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
> +    &MadtStructs[MadtStructsIndex++]
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (IRQ2 source override) failed:
> %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // IRQ9 (SCI Active High) Interrupt Source Override Structure
> +  //
> +  IntSrcOverrideStruct.Bus = 0x0;                   // Bus - ISA
> +  IntSrcOverrideStruct.Source = 0x9;                // Source - IRQ9
> +  IntSrcOverrideStruct.GlobalSystemInterrupt = 0x9; // Global System Interrupt
> - IRQ9
> +  IntSrcOverrideStruct.Flags = 0xD;                 // Flags - Level-tiggered, Active
> High
> +
> +  ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +  Status = CopyStructure (
> +    &MadtTableHeader.Header,
> +    (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
> +    &MadtStructs[MadtStructsIndex++]
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (IRQ9 source override) failed:
> %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // Build Local APIC NMI Structures
> +  //
> +  LocalApciNmiStruct.Type   = EFI_ACPI_4_0_LOCAL_APIC_NMI;
> +  LocalApciNmiStruct.Length = sizeof
> (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE);
> +  LocalApciNmiStruct.AcpiProcessorId = 0xFF;      // Applies to all processors
> +  LocalApciNmiStruct.Flags           = 0x000D;    // Flags - Level-tiggered, Active
> High
> +  LocalApciNmiStruct.LocalApicLint   = 0x1;
> +
> +  ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +  Status = CopyStructure (
> +    &MadtTableHeader.Header,
> +    (STRUCTURE_HEADER *) &LocalApciNmiStruct,
> +    &MadtStructs[MadtStructsIndex++]
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (APIC NMI) failed: %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // Build Local x2APIC NMI Structure
> +  //
> +  LocalX2ApicNmiStruct.Type   = EFI_ACPI_4_0_LOCAL_X2APIC_NMI;
> +  LocalX2ApicNmiStruct.Length = sizeof
> (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE);
> +  LocalX2ApicNmiStruct.Flags  = 0x000D;                // Flags - Level-tiggered,
> Active High
> +  LocalX2ApicNmiStruct.AcpiProcessorUid = 0xFFFFFFFF;  // Applies to all
> processors
> +  LocalX2ApicNmiStruct.LocalX2ApicLint  = 0x01;
> +  LocalX2ApicNmiStruct.Reserved[0] = 0x00;
> +  LocalX2ApicNmiStruct.Reserved[1] = 0x00;
> +  LocalX2ApicNmiStruct.Reserved[2] = 0x00;
> +
> +  ASSERT (MadtStructsIndex < MaxMadtStructCount);
> +  Status = CopyStructure (
> +    &MadtTableHeader.Header,
> +    (STRUCTURE_HEADER *) &LocalX2ApicNmiStruct,
> +    &MadtStructs[MadtStructsIndex++]
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "CopyMadtStructure (x2APIC NMI) failed: %r\n",
> Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // Build Madt Structure from the Madt Header and collection of pointers in
> MadtStructs[]
> +  //
> +  Status = BuildAcpiTable (
> +    (EFI_ACPI_DESCRIPTION_HEADER *) &MadtTableHeader,
> +    sizeof (EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER),
> +    MadtStructs,
> +    MadtStructsIndex,
> +    (UINT8 **)&NewMadtTable
> +    );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_ERROR, "BuildAcpiTable failed: %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // Publish Madt Structure to ACPI
> +  //
> +  Status = mAcpiTable->InstallAcpiTable (
> +    mAcpiTable,
> +    NewMadtTable,
> +    NewMadtTable->Header.Length,
> +    &TableHandle
> +    );
> +
> +Done:
> +  //
> +  // Free memory
> +  //
> +  for (MadtStructsIndex = 0; MadtStructsIndex < MaxMadtStructCount;
> MadtStructsIndex++) {
> +    if (MadtStructs[MadtStructsIndex] != NULL) {
> +      FreePool (MadtStructs[MadtStructsIndex]);
> +    }
> +  }
> +
> +  FreePool (MadtStructs);
> +
> +  if (NewMadtTable != NULL) {
> +    FreePool (NewMadtTable);
> +  }
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +InstallMcfgFromScratch (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                                                                            Status;
> +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEA
> DER                        *McfgTable;
> +
> EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_AD
> DRESS_ALLOCATION_STRUCTURE *Segment;
> +  UINTN                                                                                 Index;
> +  UINTN                                                                                 SegmentCount;
> +  PCI_SEGMENT_INFO                                                                      *PciSegmentInfo;
> +  UINTN                                                                                 TableHandle;
> +
> +  PciSegmentInfo = GetPciSegmentInfo (&SegmentCount);
> +
> +  McfgTable = AllocateZeroPool (
> +
> sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE
> _HEADER) +
> +
> sizeof(EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BA
> SE_ADDRESS_ALLOCATION_STRUCTURE) * SegmentCount
> +                );
> +  if (McfgTable == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Could not allocate MCFG structure\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = InitializeHeader (
> +    &McfgTable->Header,
> +
> EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_B
> ASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVIS
> ION,
> +    0
> +    );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Set MCFG table "Length" field based on the number of PCIe segments
> enumerated so far
> +  //
> +  McfgTable->Header.Length = (UINT32)(sizeof
> (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEA
> DER) +
> +                                      sizeof
> (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_A
> DDRESS_ALLOCATION_STRUCTURE) * SegmentCount);
> +
> +  Segment = (VOID *)(McfgTable + 1);
> +
> +  for (Index = 0; Index < SegmentCount; Index++) {
> +    Segment[Index].PciSegmentGroupNumber  =
> PciSegmentInfo[Index].SegmentNumber;
> +    Segment[Index].BaseAddress    = PciSegmentInfo[Index].BaseAddress;
> +    Segment[Index].StartBusNumber = PciSegmentInfo[Index].StartBusNumber;
> +    Segment[Index].EndBusNumber   = PciSegmentInfo[Index].EndBusNumber;
> +  }
> +
> +  //
> +  // Publish Madt Structure to ACPI
> +  //
> +  Status = mAcpiTable->InstallAcpiTable (
> +    mAcpiTable,
> +    McfgTable,
> +    McfgTable->Header.Length,
> +    &TableHandle
> +    );
> +
> +  return Status;
> +}
> +
> +/**
> +  This function will update any runtime platform specific information.
> +  This currently includes:
> +    Setting OEM table values, ID, table ID, creator ID and creator revision.
> +    Enabling the proper processor entries in the APIC tables
> +  It also indicates with which ACPI table version the table belongs.
> +
> +  @param[in] Table        The table to update
> +  @param[in] Version      Where to install this table
> +
> +  @retval EFI_SUCCESS     Updated tables commplete.
> +**/
> +EFI_STATUS
> +PlatformUpdateTables (
> +  IN OUT EFI_ACPI_COMMON_HEADER       *Table,
> +  IN OUT EFI_ACPI_TABLE_VERSION       *Version
> +  )
> +{
> +  EFI_ACPI_DESCRIPTION_HEADER               *TableHeader;
> +  UINT8                                     *TempOemId;
> +  UINT64                                    TempOemTableId;
> +  EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader;
> +  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTable;
> +  UINT32                                           HpetBaseAddress;
> +  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID     HpetBlockId;
> +  UINT32                                           HpetCapabilitiesData;
> +  HPET_GENERAL_CAPABILITIES_ID_REGISTER            HpetCapabilities;
> +
> +  TableHeader             = NULL;
> +
> +  //
> +  // By default, a table belongs in all ACPI table versions published.
> +  // Some tables will override this because they have different versions of the
> table.
> +  //
> +  TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
> +
> +  //
> +  // Update the OEM and creator information for every table except FACS.
> +  //
> +  if (Table->Signature !=
> EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
> +    TempOemId = (UINT8 *)PcdGetPtr(PcdAcpiDefaultOemId);
> +    CopyMem (&TableHeader->OemId, TempOemId, 6);
> +
> +    //
> +    // Skip OEM table ID and creator information for DSDT, SSDT and PSDT
> tables, since these are
> +    // created by an ASL compiler and the creator information is useful.
> +    //
> +    if (Table->Signature !=
> EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
> &&
> +        Table->Signature !=
> EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
> +        Table->Signature !=
> EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
> +        ) {
> +      TempOemTableId = PcdGet64(PcdAcpiDefaultOemTableId);
> +      CopyMem (&TableHeader->OemTableId, &TempOemTableId, 8);
> +
> +      //
> +      // Update the creator ID
> +      //
> +      TableHeader->CreatorId = PcdGet32(PcdAcpiDefaultCreatorId);
> +
> +      //
> +      // Update the creator revision
> +      //
> +      TableHeader->CreatorRevision =
> PcdGet32(PcdAcpiDefaultCreatorRevision);
> +    }
> +  }
> +
> +
> +  //
> +  // By default, a table belongs in all ACPI table versions published.
> +  // Some tables will override this because they have different versions of the
> table.
> +  //
> +  *Version = EFI_ACPI_TABLE_VERSION_1_0B |
> EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
> +
> +  //
> +  // Update the various table types with the necessary updates
> +  //
> +  switch (Table->Signature) {
> +
> +  case EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
> +    ASSERT(FALSE);
> +    break;
> +
> +  case EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
> +    FadtHeader    = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
> +
> +    FadtHeader->PreferredPmProfile = PcdGet8 (PcdFadtPreferredPmProfile);
> +    FadtHeader->IaPcBootArch       = PcdGet16 (PcdFadtIaPcBootArch);
> +    FadtHeader->Flags              = PcdGet32 (PcdFadtFlags);
> +
> +    FadtHeader->AcpiEnable  = PcdGet8 (PcdAcpiEnableSwSmi);
> +    FadtHeader->AcpiDisable = PcdGet8 (PcdAcpiDisableSwSmi);
> +
> +    FadtHeader->Pm1aEvtBlk = PcdGet16 (PcdAcpiPm1AEventBlockAddress);
> +    FadtHeader->Pm1bEvtBlk = PcdGet16 (PcdAcpiPm1BEventBlockAddress);
> +    FadtHeader->Pm1aCntBlk = PcdGet16 (PcdAcpiPm1AControlBlockAddress);
> +    FadtHeader->Pm1bCntBlk = PcdGet16 (PcdAcpiPm1BControlBlockAddress);
> +    FadtHeader->Pm2CntBlk  = PcdGet16 (PcdAcpiPm2ControlBlockAddress);
> +    FadtHeader->PmTmrBlk   = PcdGet16 (PcdAcpiPmTimerBlockAddress);
> +    FadtHeader->Gpe0Blk    = PcdGet16 (PcdAcpiGpe0BlockAddress);
> +    FadtHeader->Gpe1Blk    = PcdGet16 (PcdAcpiGpe1BlockAddress);
> +
> +    FadtHeader->XPm1aEvtBlk.Address = PcdGet16
> (PcdAcpiPm1AEventBlockAddress);
> +    FadtHeader->XPm1bEvtBlk.Address = PcdGet16
> (PcdAcpiPm1BEventBlockAddress);
> +    if (FadtHeader->XPm1bEvtBlk.Address == 0) {
> +      FadtHeader->XPm1bEvtBlk.AccessSize = 0;
> +    }
> +    FadtHeader->XPm1aCntBlk.Address = PcdGet16
> (PcdAcpiPm1AControlBlockAddress);
> +    FadtHeader->XPm1bCntBlk.Address = PcdGet16
> (PcdAcpiPm1BControlBlockAddress);
> +    if (FadtHeader->XPm1bCntBlk.Address == 0) {
> +      FadtHeader->XPm1bCntBlk.AccessSize = 0;
> +    }
> +    FadtHeader->XPm2CntBlk.Address  = PcdGet16
> (PcdAcpiPm2ControlBlockAddress);
> +    //if (FadtHeader->XPm2CntBlk.Address == 0) {
> +      FadtHeader->XPm2CntBlk.AccessSize = 0;
> +    //}
> +    FadtHeader->XPmTmrBlk.Address   = PcdGet16
> (PcdAcpiPmTimerBlockAddress);
> +    FadtHeader->XGpe0Blk.Address    = PcdGet16 (PcdAcpiGpe0BlockAddress);
> +    FadtHeader->XGpe1Blk.Address    = PcdGet16 (PcdAcpiGpe1BlockAddress);
> +    if (FadtHeader->XGpe1Blk.Address == 0) {
> +      FadtHeader->XGpe1Blk.AccessSize = 0;
> +    }
> +
> +    DEBUG(( EFI_D_ERROR, "ACPI FADT table @ address 0x%x\n", Table ));
> +    DEBUG(( EFI_D_ERROR, "  IaPcBootArch 0x%x\n", FadtHeader-
> >IaPcBootArch ));
> +    DEBUG(( EFI_D_ERROR, "  Flags 0x%x\n", FadtHeader->Flags ));
> +    break;
> +
> +  case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
> +    HpetTable = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER
> *)Table;
> +    HpetBaseAddress = PcdGet32 (PcdHpetBaseAddress);
> +    HpetTable->BaseAddressLower32Bit.Address = HpetBaseAddress;
> +    HpetTable->BaseAddressLower32Bit.RegisterBitWidth = 0;
> +    HpetCapabilitiesData     = MmioRead32 (HpetBaseAddress +
> HPET_GENERAL_CAPABILITIES_ID_OFFSET);
> +    HpetCapabilities.Uint64  = HpetCapabilitiesData;
> +    HpetCapabilitiesData     = MmioRead32 (HpetBaseAddress +
> HPET_GENERAL_CAPABILITIES_ID_OFFSET + 4);
> +    HpetCapabilities.Uint64 |= LShiftU64 (HpetCapabilitiesData, 32);
> +    HpetBlockId.Bits.Revision       = HpetCapabilities.Bits.Revision;
> +    HpetBlockId.Bits.NumberOfTimers = HpetCapabilities.Bits.NumberOfTimers;
> +    HpetBlockId.Bits.CounterSize    = HpetCapabilities.Bits.CounterSize;
> +    HpetBlockId.Bits.Reserved       = 0;
> +    HpetBlockId.Bits.LegacyRoute    = HpetCapabilities.Bits.LegacyRoute;
> +    HpetBlockId.Bits.VendorId       = HpetCapabilities.Bits.VendorId;
> +    HpetTable->EventTimerBlockId    = HpetBlockId.Uint32;
> +    HpetTable->MainCounterMinimumClockTickInPeriodicMode =
> (UINT16)HpetCapabilities.Bits.CounterClockPeriod;
> +    DEBUG(( EFI_D_ERROR, "ACPI HPET table @ address 0x%x\n", Table ));
> +    DEBUG(( EFI_D_ERROR, "  HPET base 0x%x\n", PcdGet32
> (PcdHpetBaseAddress) ));
> +    break;
> +
> +  case
> EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_B
> ASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
> +    ASSERT(FALSE);
> +    break;
> +
> +  default:
> +    break;
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function calculates RCR based on PCI Device ID and Vendor ID from the
> devices
> +  available on the platform.
> +  It also includes other instances of BIOS change to calculate CRC and provides
> as
> +  HWSignature filed in FADT table.
> +**/
> +VOID
> +IsHardwareChange (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         Index;
> +  UINTN                         HandleCount;
> +  EFI_HANDLE                    *HandleBuffer;
> +  EFI_PCI_IO_PROTOCOL           *PciIo;
> +  UINT32                        CRC;
> +  UINT32                        *HWChange;
> +  UINTN                         HWChangeSize;
> +  UINT32                        PciId;
> +  UINTN                         Handle;
> +  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsPtr;
> +  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE    *pFADT;
> +
> +  HandleCount  = 0;
> +  HandleBuffer = NULL;
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiPciIoProtocolGuid,
> +                  NULL,
> +                  &HandleCount,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return; // PciIO protocol not installed yet!
> +  }
> +
> +  //
> +  // Allocate memory for HWChange and add additional entrie for
> +  // pFADT->XDsdt
> +  //
> +  HWChangeSize = HandleCount + 1;
> +  HWChange = AllocateZeroPool( sizeof(UINT32) * HWChangeSize );
> +  ASSERT( HWChange != NULL );
> +
> +  if (HWChange == NULL) return;
> +
> +  //
> +  // add HWChange inputs: PCI devices
> +  //
> +  for (Index = 0; HandleCount > 0; HandleCount--) {
> +    PciId = 0;
> +    Status = gBS->HandleProtocol (HandleBuffer[Index],
> &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
> +    if (!EFI_ERROR (Status)) {
> +      Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &PciId);
> +      if (EFI_ERROR (Status)) {
> +        continue;
> +      }
> +      HWChange[Index++] = PciId;
> +    }
> +  }
> +
> +  //
> +  // Locate FACP Table
> +  //
> +  Handle = 0;
> +  Status = LocateAcpiTableBySignature (
> +              EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +              (EFI_ACPI_DESCRIPTION_HEADER **) &pFADT,
> +              &Handle
> +              );
> +  if (EFI_ERROR (Status) || (pFADT == NULL)) {
> +    return;  //Table not found or out of memory resource for pFADT table
> +  }
> +
> +  //
> +  // add HWChange inputs: others
> +  //
> +  HWChange[Index++] = (UINT32)pFADT->XDsdt;
> +
> +  //
> +  // Calculate CRC value with HWChange data.
> +  //
> +  Status = gBS->CalculateCrc32(HWChange, HWChangeSize, &CRC);
> +  DEBUG((DEBUG_INFO, "CRC = %x and Status = %r\n", CRC, Status));
> +
> +  //
> +  // Set HardwareSignature value based on CRC value.
> +  //
> +  FacsPtr = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
> *)(UINTN)pFADT->FirmwareCtrl;
> +  FacsPtr->HardwareSignature = CRC;
> +  FreePool( HWChange );
> +}
> +
> +VOID
> +UpdateLocalTable (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_ACPI_COMMON_HEADER        *CurrentTable;
> +  EFI_ACPI_TABLE_VERSION        Version;
> +  UINTN                         TableHandle;
> +  UINTN                         Index;
> +
> +  for (Index = 0; Index < sizeof(mLocalTable)/sizeof(mLocalTable[0]); Index++) {
> +    CurrentTable = mLocalTable[Index];
> +
> +    PlatformUpdateTables (CurrentTable, &Version);
> +
> +    TableHandle = 0;
> +
> +    if (Version != EFI_ACPI_TABLE_VERSION_NONE) {
> +      Status = mAcpiTable->InstallAcpiTable (
> +                              mAcpiTable,
> +                              CurrentTable,
> +                              CurrentTable->Length,
> +                              &TableHandle
> +                              );
> +      ASSERT_EFI_ERROR (Status);
> +    }
> +  }
> +}
> +
> +
> +VOID
> +EFIAPI
> +AcpiEndOfDxeEvent (
> +  EFI_EVENT           Event,
> +  VOID                *ParentImageHandle
> +  )
> +{
> +
> +  if (Event != NULL) {
> +    gBS->CloseEvent(Event);
> +  }
> +
> +
> +  //
> +  // Calculate Hardware Signature value based on current platform
> configurations
> +  //
> +  IsHardwareChange();
> +}
> +
> +/**
> +  ACPI Platform driver installation function.
> +
> +  @param[in] ImageHandle     Handle for this drivers loaded image protocol.
> +  @param[in] SystemTable     EFI system table.
> +
> +  @retval EFI_SUCCESS        The driver installed without error.
> +  @retval EFI_ABORTED        The driver encountered an error and could not
> complete installation of
> +                             the ACPI tables.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallAcpiPlatform (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_EVENT                     EndOfDxeEvent;
> +
> +
> +  Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID
> **)&mMpService);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID
> **)&mAcpiTable);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Create an End of DXE event.
> +  //
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  AcpiEndOfDxeEvent,
> +                  NULL,
> +                  &gEfiEndOfDxeEventGroupGuid,
> +                  &EndOfDxeEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Determine the number of processors
> +  //
> +  mMpService->GetNumberOfProcessors (
> +              mMpService,
> +              &mNumberOfCPUs,
> +              &mNumberOfEnabledCPUs
> +              );
> +  ASSERT (mNumberOfCPUs <= MAX_CPU_NUM && mNumberOfEnabledCPUs
> >= 1);
> +  DEBUG ((DEBUG_INFO, "mNumberOfCPUs - %d\n", mNumberOfCPUs));
> +  DEBUG ((DEBUG_INFO, "mNumberOfEnabledCPUs - %d\n",
> mNumberOfEnabledCPUs));
> +
> +  DEBUG ((DEBUG_INFO, "mX2ApicEnabled - 0x%x\n", mX2ApicEnabled));
> +  DEBUG ((DEBUG_INFO, "mForceX2ApicId - 0x%x\n", mForceX2ApicId));
> +
> +  // support up to 64 threads/socket
> +  AsmCpuidEx(CPUID_EXTENDED_TOPOLOGY, 1, &mNumOfBitShift, NULL,
> NULL, NULL);
> +  mNumOfBitShift &= 0x1F;
> +  DEBUG ((DEBUG_INFO, "mNumOfBitShift - 0x%x\n", mNumOfBitShift));
> +
> +  UpdateLocalTable ();
> +
> +  InstallMadtFromScratch ();
> +  InstallMcfgFromScratch ();
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Facs/Facs.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Facs/Facs.c
> new file mode 100644
> index 0000000000..a16c13466a
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Facs/Facs.c
> @@ -0,0 +1,84 @@
> +/** @file
> +  This file contains a structure definition for the ACPI 5.0 Firmware ACPI
> +  Control Structure (FACS).  The contents of this file should only be modified
> +  for bug fixes, no porting is required.
> +
> +  Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +//
> +// Statements that include other files
> +//
> +
> +#include <IndustryStandard/Acpi.h>
> +
> +//
> +// FACS Definitions
> +//
> +#define EFI_ACPI_FIRMWARE_WAKING_VECTOR 0x00000000
> +#define EFI_ACPI_GLOBAL_LOCK            0x00000000
> +
> +//
> +// Firmware Control Structure Feature Flags are defined in AcpiX.0.h
> +//
> +#define EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS 0x00000000
> +
> +#define EFI_ACPI_X_FIRMWARE_WAKING_VECTOR
> 0x0000000000000000
> +
> +#define EFI_ACPI_OSPM_FLAGS                       0x00000000
> +
> +
> +//
> +// Firmware ACPI Control Structure
> +// Please modify all values in Facs.h only.
> +//
> +
> +EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs = {
> +  EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
> +  sizeof (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
> +
> +  //
> +  // Hardware Signature will be updated at runtime
> +  //
> +  0x00000000,
> +
> +  EFI_ACPI_FIRMWARE_WAKING_VECTOR,
> +  EFI_ACPI_GLOBAL_LOCK,
> +  EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS,
> +  EFI_ACPI_X_FIRMWARE_WAKING_VECTOR,
> +  EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
> +  {
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE
> +  },
> +  EFI_ACPI_OSPM_FLAGS,
> +  {
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE
> +  }
> +};
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Fadt/Fadt.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Fadt/Fadt.c
> new file mode 100644
> index 0000000000..8aa10a4a5b
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Fadt/Fadt.c
> @@ -0,0 +1,359 @@
> +/** @file
> +  This file contains a structure definition for the ACPI 5.0 Fixed ACPI
> +  Description Table (FADT).  The contents of this file should only be modified
> +  for bug fixes, no porting is required.
> +
> +  Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +//
> +// Statements that include other files
> +//
> +#include <IndustryStandard/Acpi.h>
> +
> +//
> +// FADT Definitions
> +//
> +#define EFI_ACPI_OEM_FADT_REVISION    0x00000000
> +
> +#define EFI_ACPI_PREFERRED_PM_PROFILE 0x00 // To be fixed
> +
> +#define EFI_ACPI_SCI_INT              0x0009
> +#define EFI_ACPI_SMI_CMD              0x000000B2
> +
> +#define EFI_ACPI_ACPI_ENABLE          0 // To be fixed
> +#define EFI_ACPI_ACPI_DISABLE         0 // To be fixed
> +#define EFI_ACPI_S4_BIOS_REQ          0x00
> +#define EFI_ACPI_CST_CNT              0x00
> +
> +#define EFI_ACPI_PSTATE_CNT           0x00
> +#define EFI_ACPI_GPE1_BASE            (EFI_ACPI_GPE1_BLK_BIT_WIDTH / 2)
> +#define EFI_ACPI_P_LVL2_LAT           0x0065 // 101
> +#define EFI_ACPI_P_LVL3_LAT           0x03E9 // 1001
> +#define EFI_ACPI_FLUSH_SIZE           0x0000
> +#define EFI_ACPI_FLUSH_STRIDE         0x0000
> +#define EFI_ACPI_DUTY_OFFSET          0x01
> +#define EFI_ACPI_DUTY_WIDTH           0x00
> +
> +#define EFI_ACPI_DAY_ALRM             0x0D
> +#define EFI_ACPI_MON_ALRM             0x00
> +#define EFI_ACPI_CENTURY              0x32
> +
> +//
> +// IA-PC Boot Architecture Flags
> +//
> +
> +#define EFI_ACPI_IAPC_BOOT_ARCH       0 // To be fixed
> +
> +//
> +// Fixed Feature Flags
> +//
> +#define EFI_ACPI_FIXED_FEATURE_FLAGS  0 // To be fixed
> +
> +//
> +// PM1A Event Register Block Generic Address Information
> +//
> +#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH         0x20
> +#define EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET        0x00
> +#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS           0 // To be fixed
> +
> +//
> +// PM1B Event Register Block Generic Address Information
> +//
> +#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH         0x00
> +#define EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET        0x00
> +#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS           0 // To be fixed
> +
> +//
> +// PM1A Control Register Block Generic Address Information
> +//
> +#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH         0x10
> +#define EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET        0x00
> +#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS           0 // To be fixed
> +
> +//
> +// PM1B Control Register Block Generic Address Information
> +//
> +#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH         0x00
> +#define EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET        0x00
> +#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS           0 // To be fixed
> +
> +//
> +// PM2 Control Register Block Generic Address Information
> +//
> +#define EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH        0x08
> +#define EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET       0x00
> +#define EFI_ACPI_PM2_CNT_BLK_ADDRESS          0 // To be fixed
> +
> +//
> +// Power Management Timer Control Register Block Generic Address
> +// Information
> +//
> +#define EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_PM_TMR_BLK_BIT_WIDTH         0x20
> +#define EFI_ACPI_PM_TMR_BLK_BIT_OFFSET        0x00
> +#define EFI_ACPI_PM_TMR_BLK_ADDRESS           0 // To be fixed
> +
> +//
> +// General Purpose Event 0 Register Block Generic Address
> +// Information
> +//
> +#define EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_GPE0_BLK_BIT_WIDTH         0  // size of
> R_PCH_ACPI_GPE0_STS_127_96 + R_PCH_ACPI_GPE0_EN_127_96
> +#define EFI_ACPI_GPE0_BLK_BIT_OFFSET        0x00
> +#define EFI_ACPI_GPE0_BLK_ADDRESS           0 // To be fixed
> +
> +//
> +// General Purpose Event 1 Register Block Generic Address
> +// Information
> +//
> +#define EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_GPE1_BLK_BIT_WIDTH         0x0
> +#define EFI_ACPI_GPE1_BLK_BIT_OFFSET        0x0
> +#define EFI_ACPI_GPE1_BLK_ADDRESS           0 // To be fixed
> +//
> +// Reset Register Generic Address Information
> +//
> +#define EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID
> EFI_ACPI_2_0_SYSTEM_IO
> +#define EFI_ACPI_RESET_REG_BIT_WIDTH        0x08
> +#define EFI_ACPI_RESET_REG_BIT_OFFSET       0x00
> +#define EFI_ACPI_RESET_REG_ADDRESS          0x00000CF9
> +#define EFI_ACPI_RESET_VALUE                0x06
> +
> +//
> +// Number of bytes decoded by PM1 event blocks (a and b)
> +//
> +#define EFI_ACPI_PM1_EVT_LEN  ((EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH +
> EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH) / 8)
> +
> +//
> +// Number of bytes decoded by PM1 control blocks (a and b)
> +//
> +#define EFI_ACPI_PM1_CNT_LEN  ((EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH +
> EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH) / 8)
> +
> +//
> +// Number of bytes decoded by PM2 control block
> +//
> +#define EFI_ACPI_PM2_CNT_LEN  (EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH / 8)
> +
> +//
> +// Number of bytes decoded by PM timer block
> +//
> +#define EFI_ACPI_PM_TMR_LEN (EFI_ACPI_PM_TMR_BLK_BIT_WIDTH / 8)
> +
> +//
> +// Number of bytes decoded by GPE0 block
> +//
> +#define EFI_ACPI_GPE0_BLK_LEN (EFI_ACPI_GPE0_BLK_BIT_WIDTH / 8)
> +
> +//
> +// Number of bytes decoded by GPE1 block
> +//
> +#define EFI_ACPI_GPE1_BLK_LEN (EFI_ACPI_GPE1_BLK_BIT_WIDTH / 8)
> +
> +//
> +// Fixed ACPI Description Table
> +// Please modify all values in Fadt.h only.
> +//
> +
> +EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt = {
> +  {
> +    EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE),
> +    EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
> +
> +    //
> +    // Checksum will be updated at runtime
> +    //
> +    0x00,
> +
> +    //
> +    // It is expected that these values will be updated at runtime
> +    //
> +    { ' ', ' ', ' ', ' ', ' ', ' ' },
> +
> +    0,
> +    EFI_ACPI_OEM_FADT_REVISION,
> +    0,
> +    0
> +  },
> +
> +  //
> +  // These addresses will be updated at runtime
> +  //
> +  0x00000000,
> +  0x00000000,
> +
> +  EFI_ACPI_RESERVED_BYTE,
> +  EFI_ACPI_PREFERRED_PM_PROFILE,
> +  EFI_ACPI_SCI_INT,
> +  EFI_ACPI_SMI_CMD,
> +  EFI_ACPI_ACPI_ENABLE,
> +  EFI_ACPI_ACPI_DISABLE,
> +  EFI_ACPI_S4_BIOS_REQ,
> +  EFI_ACPI_PSTATE_CNT,
> +
> +  EFI_ACPI_PM1A_EVT_BLK_ADDRESS,
> +  EFI_ACPI_PM1B_EVT_BLK_ADDRESS,
> +  EFI_ACPI_PM1A_CNT_BLK_ADDRESS,
> +  EFI_ACPI_PM1B_CNT_BLK_ADDRESS,
> +  EFI_ACPI_PM2_CNT_BLK_ADDRESS,
> +  EFI_ACPI_PM_TMR_BLK_ADDRESS,
> +  EFI_ACPI_GPE0_BLK_ADDRESS,
> +  EFI_ACPI_GPE1_BLK_ADDRESS,
> +  EFI_ACPI_PM1_EVT_LEN,
> +  EFI_ACPI_PM1_CNT_LEN,
> +  EFI_ACPI_PM2_CNT_LEN,
> +  EFI_ACPI_PM_TMR_LEN,
> +  EFI_ACPI_GPE0_BLK_LEN,
> +  EFI_ACPI_GPE1_BLK_LEN,
> +  EFI_ACPI_GPE1_BASE,
> +
> +  //
> +  // Latest OS have C-State capability and CST_CNT SMI doesn't need to be
> defined.
> +  // CST_CNT SMI is not handled in BIOS and it can be removed safely.
> +  //
> +  EFI_ACPI_CST_CNT,
> +  EFI_ACPI_P_LVL2_LAT,
> +  EFI_ACPI_P_LVL3_LAT,
> +  EFI_ACPI_FLUSH_SIZE,
> +  EFI_ACPI_FLUSH_STRIDE,
> +  EFI_ACPI_DUTY_OFFSET,
> +  EFI_ACPI_DUTY_WIDTH,
> +  EFI_ACPI_DAY_ALRM,
> +  EFI_ACPI_MON_ALRM,
> +  EFI_ACPI_CENTURY,
> +  EFI_ACPI_IAPC_BOOT_ARCH,
> +  EFI_ACPI_RESERVED_BYTE,
> +  EFI_ACPI_FIXED_FEATURE_FLAGS,
> +
> +  //
> +  // Reset Register Block
> +  //
> +  {
> +    EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID,
> +    EFI_ACPI_RESET_REG_BIT_WIDTH,
> +    EFI_ACPI_RESET_REG_BIT_OFFSET,
> +    EFI_ACPI_5_0_BYTE,
> +    EFI_ACPI_RESET_REG_ADDRESS
> +  },
> +  EFI_ACPI_RESET_VALUE,
> +  {
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE,
> +    EFI_ACPI_RESERVED_BYTE
> +  },
> +
> +  //
> +  // These addresses will be updated at runtime
> +  //
> +  0x0000000000000000, // X_FIRMWARE_CTRL
> +  0x0000000000000000, // X_DSDT
> +
> +  {
> +    //
> +    // X_PM1a Event Register Block
> +    //
> +    EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH,
> +    EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_WORD,
> +    EFI_ACPI_PM1A_EVT_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_PM1b Event Register Block
> +    //
> +    EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH,
> +    EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_WORD,
> +    EFI_ACPI_PM1B_EVT_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_PM1a Control Register Block
> +    //
> +    EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH,
> +    EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_WORD,
> +    EFI_ACPI_PM1A_CNT_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_PM1b Control Register Block
> +    //
> +    EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH,
> +    EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_WORD,
> +    EFI_ACPI_PM1B_CNT_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_PM2 Control Register Block
> +    //
> +    EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH,
> +    EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_BYTE,
> +    EFI_ACPI_PM2_CNT_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_PM Timer Control Register Block
> +    //
> +    EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_PM_TMR_BLK_BIT_WIDTH,
> +    EFI_ACPI_PM_TMR_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_DWORD,
> +    EFI_ACPI_PM_TMR_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_General Purpose Event 0 Register Block
> +    //
> +    EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_GPE0_BLK_BIT_WIDTH,
> +    EFI_ACPI_GPE0_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_BYTE,
> +    EFI_ACPI_GPE0_BLK_ADDRESS
> +  },
> +  {
> +    //
> +    // X_General Purpose Event 1 Register Block
> +    //
> +    EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_GPE1_BLK_BIT_WIDTH,
> +    EFI_ACPI_GPE1_BLK_BIT_OFFSET,
> +    EFI_ACPI_5_0_BYTE,
> +    EFI_ACPI_GPE1_BLK_ADDRESS
> +  },
> +  {
> +  //
> +  // Sleep Control Reg - update in DXE driver
> +  //
> +    0,
> +    0,
> +    0,
> +    0,
> +    0
> +  },
> +  {
> +  //
> +  // Sleep Status Reg - update in DXE driver
> +  //
> +    0,
> +    0,
> +    0,
> +    0,
> +    0
> +  }
> +};
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Hpet/Hpet.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Hpet/Hpet.c
> new file mode 100644
> index 0000000000..aa386ba149
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Hpet/Hpet.c
> @@ -0,0 +1,78 @@
> +/** @file
> +  This file contains a structure definition for the ACPI 1.0 High Precision Event
> Timer
> +  Description Table (HPET).  The contents of this file should only be modified
> +  for bug fixes, no porting is required.
> +
> +  Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +//
> +// Statements that include other files
> +//
> +
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/HighPrecisionEventTimerTable.h>
> +
> +//
> +// HPET Definitions
> +//
> +#define EFI_ACPI_OEM_HPET_REVISION    0x00000001
> +
> +#define EFI_ACPI_EVENT_TIMER_BLOCK_ID                   0x0 // To be filled
> +
> +//
> +// Event Timer Block Base Address Information
> +//
> +#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID
> EFI_ACPI_3_0_SYSTEM_MEMORY
> +#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH        0x40
> +#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET       0x00
> +#define EFI_ACPI_EVENT_TIMER_ACCESS_SIZE            0x00
> +#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS          0x0 // To be filled
> +
> +#define EFI_ACPI_HPET_NUMBER                        0x00
> +
> +#define EFI_ACPI_MIN_CLOCK_TICK                     0x0080
> +
> +#define EFI_ACPI_HPET_ATTRIBUTES                    0x00
> +
> +//
> +// High Precision Event Timer Table
> +// Please modify all values in Hpet.h only.
> +//
> +
> +EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet = {
> +  {
> +    EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER),
> +    EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,
> +
> +    //
> +    // Checksum will be updated at runtime
> +    //
> +    0x00,
> +
> +    //
> +    // It is expected that these values will be updated at runtime
> +    //
> +    { ' ', ' ', ' ', ' ', ' ', ' ' },
> +
> +    0,
> +    EFI_ACPI_OEM_HPET_REVISION,
> +    0,
> +    0
> +  },
> +
> +  EFI_ACPI_EVENT_TIMER_BLOCK_ID,
> +  {
> +    EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID,
> +    EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH,
> +    EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET,
> +    EFI_ACPI_EVENT_TIMER_ACCESS_SIZE,
> +    EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS
> +  },
> +  EFI_ACPI_HPET_NUMBER,
> +  EFI_ACPI_MIN_CLOCK_TICK,
> +  EFI_ACPI_HPET_ATTRIBUTES
> +};
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Wsmt/Wsmt.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Wsmt/Wsmt.c
> new file mode 100644
> index 0000000000..12e2feacb4
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/Wsmt/Wsmt.c
> @@ -0,0 +1,46 @@
> +/** @file
> +  ACPI WSMT table
> +
> +  Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +//
> +// Statements that include other files
> +//
> +
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
> +#include <Library/PcdLib.h>
> +
> +//
> +// WSMT Definitions
> +//
> +
> +#define EFI_ACPI_OEM_WSMT_REVISION                      0x00000001
> +
> +EFI_ACPI_WSMT_TABLE Wsmt = {
> +  {
> +    EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE,
> +    sizeof (EFI_ACPI_WSMT_TABLE),
> +    EFI_WSMT_TABLE_REVISION,
> +
> +    //
> +    // Checksum will be updated at runtime
> +    //
> +    0x00,
> +
> +    //
> +    // It is expected that these values will be updated at runtime
> +    //
> +    { ' ', ' ', ' ', ' ', ' ', ' ' },
> +
> +    0,
> +    EFI_ACPI_OEM_WSMT_REVISION,
> +    0,
> +    0
> +  },
> +
> +  FixedPcdGet32(PcdWsmtProtectionFlags)
> +};
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Co
> mponentName.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Co
> mponentName.c
> new file mode 100644
> index 0000000000..dd9cc80e42
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Co
> mponentName.c
> @@ -0,0 +1,205 @@
> +/** @file
> +  Component name for the QEMU video controller.
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "Qemu.h"
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL
> gQemuVideoComponentName = {
> +  QemuVideoComponentNameGetDriverName,
> +  QemuVideoComponentNameGetControllerName,
> +  "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
> gQemuVideoComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
> QemuVideoComponentNameGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> QemuVideoComponentNameGetControllerName,
> +  "en"
> +};
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mQemuVideoDriverNameTable[] = {
> +  { "eng;en", L"QEMU Video Driver" },
> +  { NULL , NULL }
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mQemuVideoControllerNameTable[] = {
> +  { "eng;en", L"QEMU Video PCI Adapter" },
> +  { NULL , NULL }
> +};
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language. This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
> +                                This and the language specified by Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoComponentNameGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mQemuVideoDriverNameTable,
> +           DriverName,
> +           (BOOLEAN)(This == &gQemuVideoComponentName)
> +           );
> +}
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This handle
> +                                specifies the controller whose name is to be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to retrieve
> +                                the name of.  This is an optional parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified in
> +                                RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in
> +                                the language specified by Language for the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
> EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoComponentNameGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHandle,
> +  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT CHAR16                                          **ControllerName
> +  )
> +{
> +  EFI_STATUS                      Status;
> +
> +  //
> +  // This is a device driver, so ChildHandle must be NULL.
> +  //
> +  if (ChildHandle != NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Make sure this driver is currently managing ControllHandle
> +  //
> +  Status = EfiTestManagedDevice (
> +             ControllerHandle,
> +             gQemuVideoDriverBinding.DriverBindingHandle,
> +             &gEfiPciIoProtocolGuid
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Get the QEMU Video's Device structure
> +  //
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mQemuVideoControllerNameTable,
> +           ControllerName,
> +           (BOOLEAN)(This == &gQemuVideoComponentName)
> +           );
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Dri
> ver.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Dri
> ver.c
> new file mode 100644
> index 0000000000..e49e7a465c
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Dri
> ver.c
> @@ -0,0 +1,1011 @@
> +/** @file
> +  This driver is a sample implementation of the Graphics Output Protocol for
> +  the QEMU (Cirrus Logic 5446) video controller.
> +
> +  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "Qemu.h"
> +#include <IndustryStandard/Acpi.h>
> +
> +EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
> +  QemuVideoControllerDriverSupported,
> +  QemuVideoControllerDriverStart,
> +  QemuVideoControllerDriverStop,
> +  0x10,
> +  NULL,
> +  NULL
> +};
> +
> +QEMU_VIDEO_CARD gQemuVideoCardList[] = {
> +    {
> +        PCI_CLASS_DISPLAY_VGA,
> +        CIRRUS_LOGIC_VENDOR_ID,
> +        CIRRUS_LOGIC_5430_DEVICE_ID,
> +        QEMU_VIDEO_CIRRUS_5430,
> +        L"Cirrus 5430"
> +    },{
> +        PCI_CLASS_DISPLAY_VGA,
> +        CIRRUS_LOGIC_VENDOR_ID,
> +        CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,
> +        QEMU_VIDEO_CIRRUS_5430,
> +        L"Cirrus 5430"
> +    },{
> +        PCI_CLASS_DISPLAY_VGA,
> +        CIRRUS_LOGIC_VENDOR_ID,
> +        CIRRUS_LOGIC_5446_DEVICE_ID,
> +        QEMU_VIDEO_CIRRUS_5446,
> +        L"Cirrus 5446"
> +    },{
> +        PCI_CLASS_DISPLAY_VGA,
> +        0x4321,
> +        0x1111,
> +        QEMU_VIDEO_BOCHS_MMIO,
> +        L"QEMU Standard VGA"
> +    },{
> +        PCI_CLASS_DISPLAY_OTHER,
> +        0x1234,
> +        0x1111,
> +        QEMU_VIDEO_BOCHS_MMIO,
> +        L"QEMU Standard VGA (secondary)"
> +    },{
> +        PCI_CLASS_DISPLAY_VGA,
> +        0x1b36,
> +        0x0100,
> +        QEMU_VIDEO_BOCHS,
> +        L"QEMU QXL VGA"
> +    },{
> +        PCI_CLASS_DISPLAY_VGA,
> +        0x1af4,
> +        0x1050,
> +        QEMU_VIDEO_BOCHS_MMIO,
> +        L"QEMU VirtIO VGA"
> +    },{
> +        0 /* end of list */
> +    }
> +};
> +
> +static QEMU_VIDEO_CARD*
> +QemuVideoDetect(
> +  IN UINT8 SubClass,
> +  IN UINT16 VendorId,
> +  IN UINT16 DeviceId
> +  )
> +{
> +  UINTN Index = 0;
> +
> +  while (gQemuVideoCardList[Index].VendorId != 0) {
> +    if (gQemuVideoCardList[Index].SubClass == SubClass &&
> +        gQemuVideoCardList[Index].VendorId == VendorId &&
> +        gQemuVideoCardList[Index].DeviceId == DeviceId) {
> +      return gQemuVideoCardList + Index;
> +    }
> +    Index++;
> +  }
> +  return NULL;
> +}
> +
> +/**
> +  Check if this device is supported.
> +
> +  @param  This                   The driver binding protocol.
> +  @param  Controller             The controller handle to check.
> +  @param  RemainingDevicePath    The remaining device path.
> +
> +  @retval EFI_SUCCESS            The bus supports this controller.
> +  @retval EFI_UNSUPPORTED        This device isn't supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoControllerDriverSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
> +  IN EFI_HANDLE                     Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS          Status;
> +  EFI_PCI_IO_PROTOCOL *PciIo;
> +  PCI_TYPE00          Pci;
> +  QEMU_VIDEO_CARD     *Card;
> +
> +  //
> +  // Open the PCI I/O Protocol
> +  //
> +  Status = gBS->OpenProtocol (
> +                  Controller,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **) &PciIo,
> +                  This->DriverBindingHandle,
> +                  Controller,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Read the PCI Configuration Header from the PCI Device
> +  //
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint32,
> +                        0,
> +                        sizeof (Pci) / sizeof (UINT32),
> +                        &Pci
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  Status = EFI_UNSUPPORTED;
> +  if (!IS_PCI_DISPLAY (&Pci)) {
> +    goto Done;
> +  }
> +  Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId,
> Pci.Hdr.DeviceId);
> +  if (Card != NULL) {
> +    DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));
> +    Status = EFI_SUCCESS;
> +  }
> +
> +Done:
> +  //
> +  // Close the PCI I/O Protocol
> +  //
> +  gBS->CloseProtocol (
> +        Controller,
> +        &gEfiPciIoProtocolGuid,
> +        This->DriverBindingHandle,
> +        Controller
> +        );
> +
> +  return Status;
> +}
> +
> +/**
> +  Start to process the controller.
> +
> +  @param  This                   The USB bus driver binding instance.
> +  @param  Controller             The controller to check.
> +  @param  RemainingDevicePath    The remaining device patch.
> +
> +  @retval EFI_SUCCESS            The controller is controlled by the usb bus.
> +  @retval EFI_ALREADY_STARTED    The controller is already controlled by the
> usb
> +                                 bus.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoControllerDriverStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
> +  IN EFI_HANDLE                     Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
> +  )
> +{
> +  EFI_TPL                           OldTpl;
> +  EFI_STATUS                        Status;
> +  QEMU_VIDEO_PRIVATE_DATA           *Private;
> +  BOOLEAN                           IsQxl;
> +  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
> +  ACPI_ADR_DEVICE_PATH              AcpiDeviceNode;
> +  PCI_TYPE00                        Pci;
> +  QEMU_VIDEO_CARD                   *Card;
> +  EFI_PCI_IO_PROTOCOL               *ChildPciIo;
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  //
> +  // Allocate Private context data for GOP inteface.
> +  //
> +  Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));
> +  if (Private == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto RestoreTpl;
> +  }
> +
> +  //
> +  // Set up context record
> +  //
> +  Private->Signature  = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;
> +
> +  //
> +  // Open PCI I/O Protocol
> +  //
> +  Status = gBS->OpenProtocol (
> +                  Controller,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **) &Private->PciIo,
> +                  This->DriverBindingHandle,
> +                  Controller,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto FreePrivate;
> +  }
> +
> +  //
> +  // Read the PCI Configuration Header from the PCI Device
> +  //
> +  Status = Private->PciIo->Pci.Read (
> +                        Private->PciIo,
> +                        EfiPciIoWidthUint32,
> +                        0,
> +                        sizeof (Pci) / sizeof (UINT32),
> +                        &Pci
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto ClosePciIo;
> +  }
> +
> +  //
> +  // Determine card variant.
> +  //
> +  Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId,
> Pci.Hdr.DeviceId);
> +  if (Card == NULL) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto ClosePciIo;
> +  }
> +  Private->Variant = Card->Variant;
> +
> +  //
> +  // IsQxl is based on the detected Card->Variant, which at a later point might
> +  // not match Private->Variant.
> +  //
> +  IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);
> +
> +  //
> +  // Save original PCI attributes
> +  //
> +  Status = Private->PciIo->Attributes (
> +                    Private->PciIo,
> +                    EfiPciIoAttributeOperationGet,
> +                    0,
> +                    &Private->OriginalPciAttributes
> +                    );
> +
> +  if (EFI_ERROR (Status)) {
> +    goto ClosePciIo;
> +  }
> +
> +  //
> +  // Set new PCI attributes
> +  //
> +  Status = Private->PciIo->Attributes (
> +                            Private->PciIo,
> +                            EfiPciIoAttributeOperationEnable,
> +                            EFI_PCI_DEVICE_ENABLE |
> EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
> +                            NULL
> +                            );
> +  if (EFI_ERROR (Status)) {
> +    goto ClosePciIo;
> +  }
> +
> +  //
> +  // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).
> +  //
> +  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
> +    EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;
> +
> +    Status = Private->PciIo->GetBarAttributes (
> +                        Private->PciIo,
> +                        PCI_BAR_IDX2,
> +                        NULL,
> +                        (VOID**) &MmioDesc
> +                        );
> +    if (EFI_ERROR (Status) ||
> +        MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +      DEBUG ((EFI_D_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));
> +      Private->Variant = QEMU_VIDEO_BOCHS;
> +    } else {
> +      DEBUG ((EFI_D_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n",
> +              MmioDesc->AddrRangeMin));
> +    }
> +
> +    if (!EFI_ERROR (Status)) {
> +      FreePool (MmioDesc);
> +    }
> +  }
> +
> +  //
> +  // Check if accessing the bochs interface works.
> +  //
> +  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
> +      Private->Variant == QEMU_VIDEO_BOCHS) {
> +    UINT16 BochsId;
> +    BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);
> +    if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {
> +      DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n",
> BochsId));
> +      Status = EFI_DEVICE_ERROR;
> +      goto RestoreAttributes;
> +    }
> +  }
> +
> +  //
> +  // Get ParentDevicePath
> +  //
> +  Status = gBS->HandleProtocol (
> +                  Controller,
> +                  &gEfiDevicePathProtocolGuid,
> +                  (VOID **) &ParentDevicePath
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto RestoreAttributes;
> +  }
> +
> +  //
> +  // Set Gop Device Path
> +  //
> +  ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
> +  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
> +  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
> +  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0,
> ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
> +  SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof
> (ACPI_ADR_DEVICE_PATH));
> +
> +  Private->GopDevicePath = AppendDevicePathNode (
> +                                      ParentDevicePath,
> +                                      (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
> +                                      );
> +  if (Private->GopDevicePath == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto RestoreAttributes;
> +  }
> +
> +  //
> +  // Create new child handle and install the device path protocol on it.
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &Private->Handle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  Private->GopDevicePath,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeGopDevicePath;
> +  }
> +
> +  //
> +  // Construct video mode buffer
> +  //
> +  switch (Private->Variant) {
> +  case QEMU_VIDEO_CIRRUS_5430:
> +  case QEMU_VIDEO_CIRRUS_5446:
> +    Status = QemuVideoCirrusModeSetup (Private);
> +    break;
> +  case QEMU_VIDEO_BOCHS_MMIO:
> +  case QEMU_VIDEO_BOCHS:
> +    Status = QemuVideoBochsModeSetup (Private, IsQxl);
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    Status = EFI_DEVICE_ERROR;
> +    break;
> +  }
> +  if (EFI_ERROR (Status)) {
> +    goto UninstallGopDevicePath;
> +  }
> +
> +  //
> +  // Start the GOP software stack.
> +  //
> +  Status = QemuVideoGraphicsOutputConstructor (Private);
> +  if (EFI_ERROR (Status)) {
> +    goto FreeModeData;
> +  }
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &Private->Handle,
> +                  &gEfiGraphicsOutputProtocolGuid,
> +                  &Private->GraphicsOutput,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto DestructQemuVideoGraphics;
> +  }
> +
> +  //
> +  // Reference parent handle from child handle.
> +  //
> +  Status = gBS->OpenProtocol (
> +                Controller,
> +                &gEfiPciIoProtocolGuid,
> +                (VOID **) &ChildPciIo,
> +                This->DriverBindingHandle,
> +                Private->Handle,
> +                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> +                );
> +  if (EFI_ERROR (Status)) {
> +    goto UninstallGop;
> +  }
> +
> +#if defined MDE_CPU_IA32 || defined MDE_CPU_X64
> +  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
> +      Private->Variant == QEMU_VIDEO_BOCHS) {
> +    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode-
> >FrameBufferBase);
> +  }
> +#endif
> +
> +  gBS->RestoreTPL (OldTpl);
> +  return EFI_SUCCESS;
> +
> +UninstallGop:
> +  gBS->UninstallProtocolInterface (Private->Handle,
> +         &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);
> +
> +DestructQemuVideoGraphics:
> +  QemuVideoGraphicsOutputDestructor (Private);
> +
> +FreeModeData:
> +  FreePool (Private->ModeData);
> +
> +UninstallGopDevicePath:
> +  gBS->UninstallProtocolInterface (Private->Handle,
> +         &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
> +
> +FreeGopDevicePath:
> +  FreePool (Private->GopDevicePath);
> +
> +RestoreAttributes:
> +  Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,
> +                    Private->OriginalPciAttributes, NULL);
> +
> +ClosePciIo:
> +  gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle, Controller);
> +
> +FreePrivate:
> +  FreePool (Private);
> +
> +RestoreTpl:
> +  gBS->RestoreTPL (OldTpl);
> +
> +  return Status;
> +}
> +
> +/**
> +  Stop this device
> +
> +  @param  This                   The USB bus driver binding protocol.
> +  @param  Controller             The controller to release.
> +  @param  NumberOfChildren       The number of children of this device that
> +                                 opened the controller BY_CHILD.
> +  @param  ChildHandleBuffer      The array of child handle.
> +
> +  @retval EFI_SUCCESS            The controller or children are stopped.
> +  @retval EFI_DEVICE_ERROR       Failed to stop the driver.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoControllerDriverStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
> +  IN EFI_HANDLE                     Controller,
> +  IN UINTN                          NumberOfChildren,
> +  IN EFI_HANDLE                     *ChildHandleBuffer
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
> +
> +  EFI_STATUS                      Status;
> +  QEMU_VIDEO_PRIVATE_DATA  *Private;
> +
> +  if (NumberOfChildren == 0) {
> +    //
> +    // Close the PCI I/O Protocol
> +    //
> +    gBS->CloseProtocol (
> +          Controller,
> +          &gEfiPciIoProtocolGuid,
> +          This->DriverBindingHandle,
> +          Controller
> +          );
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // free all resources for whose access we need the child handle, because the
> +  // child handle is going away
> +  //
> +  ASSERT (NumberOfChildren == 1);
> +  Status = gBS->OpenProtocol (
> +                  ChildHandleBuffer[0],
> +                  &gEfiGraphicsOutputProtocolGuid,
> +                  (VOID **) &GraphicsOutput,
> +                  This->DriverBindingHandle,
> +                  Controller,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Get our private context information
> +  //
> +  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS
> (GraphicsOutput);
> +  ASSERT (Private->Handle == ChildHandleBuffer[0]);
> +
> +  QemuVideoGraphicsOutputDestructor (Private);
> +  //
> +  // Remove the GOP protocol interface from the system
> +  //
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> +                  Private->Handle,
> +                  &gEfiGraphicsOutputProtocolGuid,
> +                  &Private->GraphicsOutput,
> +                  NULL
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Restore original PCI attributes
> +  //
> +  Private->PciIo->Attributes (
> +                  Private->PciIo,
> +                  EfiPciIoAttributeOperationSet,
> +                  Private->OriginalPciAttributes,
> +                  NULL
> +                  );
> +
> +  gBS->CloseProtocol (
> +        Controller,
> +        &gEfiPciIoProtocolGuid,
> +        This->DriverBindingHandle,
> +        Private->Handle
> +        );
> +
> +  FreePool (Private->ModeData);
> +  gBS->UninstallProtocolInterface (Private->Handle,
> +         &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
> +  FreePool (Private->GopDevicePath);
> +
> +  //
> +  // Free our instance data
> +  //
> +  gBS->FreePool (Private);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +  @param  Address TODO: add argument description
> +  @param  Data TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +outb (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address,
> +  UINT8                           Data
> +  )
> +{
> +  EFI_STATUS          Status;
> +  VOID                *Interface;
> +  Private->PciIo->Io.Write (
> +                      Private->PciIo,
> +                      EfiPciIoWidthUint8,
> +                      EFI_PCI_IO_PASS_THROUGH_BAR,
> +                      Address,
> +                      1,
> +                      &Data
> +                      );
> +  Status = gBS->LocateProtocol(&gEfiDxeSmmReadyToLockProtocolGuid,
> NULL, &Interface);
> +  if (!EFI_ERROR(Status)) {
> +    return;
> +  }
> +
> +  Status = S3BootScriptSaveIoWrite(
> +      S3BootScriptWidthUint8,
> +      Address,
> +      (UINTN)1,
> +      &Data
> +  );
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +  @param  Address TODO: add argument description
> +  @param  Data TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +outw (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address,
> +  UINT16                          Data
> +  )
> +{
> +  EFI_STATUS          Status;
> +  VOID                *Interface;
> +
> +  Private->PciIo->Io.Write (
> +                      Private->PciIo,
> +                      EfiPciIoWidthUint16,
> +                      EFI_PCI_IO_PASS_THROUGH_BAR,
> +                      Address,
> +                      1,
> +                      &Data
> +                      );
> +
> +  Status = gBS->LocateProtocol(&gEfiDxeSmmReadyToLockProtocolGuid,
> NULL, &Interface);
> +  if (!EFI_ERROR(Status)) {
> +    return;
> +  }
> +  Status = S3BootScriptSaveIoWrite(
> +      S3BootScriptWidthUint16,
> +      Address,
> +      1,
> +      &Data
> +  );
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +  @param  Address TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +UINT8
> +inb (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address
> +  )
> +{
> +  UINT8 Data;
> +
> +  Private->PciIo->Io.Read (
> +                      Private->PciIo,
> +                      EfiPciIoWidthUint8,
> +                      EFI_PCI_IO_PASS_THROUGH_BAR,
> +                      Address,
> +                      1,
> +                      &Data
> +                      );
> +  return Data;
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +  @param  Address TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +UINT16
> +inw (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address
> +  )
> +{
> +  UINT16  Data;
> +
> +  Private->PciIo->Io.Read (
> +                      Private->PciIo,
> +                      EfiPciIoWidthUint16,
> +                      EFI_PCI_IO_PASS_THROUGH_BAR,
> +                      Address,
> +                      1,
> +                      &Data
> +                      );
> +  return Data;
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +  @param  Index TODO: add argument description
> +  @param  Red TODO: add argument description
> +  @param  Green TODO: add argument description
> +  @param  Blue TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +SetPaletteColor (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Index,
> +  UINT8                           Red,
> +  UINT8                           Green,
> +  UINT8                           Blue
> +  )
> +{
> +  VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
> +  VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
> +  VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
> +  VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +SetDefaultPalette (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  )
> +{
> +  UINTN Index;
> +  UINTN RedIndex;
> +  UINTN GreenIndex;
> +  UINTN BlueIndex;
> +
> +  Index = 0;
> +  for (RedIndex = 0; RedIndex < 8; RedIndex++) {
> +    for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
> +      for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
> +        SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8)
> (GreenIndex << 5), (UINT8) (BlueIndex << 6));
> +        Index++;
> +      }
> +    }
> +  }
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +ClearScreen (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  )
> +{
> +  UINT32  Color;
> +
> +  Color = 0;
> +  Private->PciIo->Mem.Write (
> +                        Private->PciIo,
> +                        EfiPciIoWidthFillUint32,
> +                        0,
> +                        0,
> +                        0x400000 >> 2,
> +                        &Color
> +                        );
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +DrawLogo (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           ScreenWidth,
> +  UINTN                           ScreenHeight
> +  )
> +{
> +}
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  Private TODO: add argument description
> +  @param  ModeData TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +VOID
> +InitializeCirrusGraphicsMode (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  QEMU_VIDEO_CIRRUS_MODES  *ModeData
> +  )
> +{
> +  UINT8 Byte;
> +  UINTN Index;
> +
> +  outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
> +  outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
> +
> +  for (Index = 0; Index < 15; Index++) {
> +    outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
> +  }
> +
> +  if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
> +    outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
> +    Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
> +    outb (Private, SEQ_DATA_REGISTER, Byte);
> +  }
> +
> +  outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
> +  outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
> +  outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
> +  outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
> +
> +  for (Index = 0; Index < 28; Index++) {
> +    outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData-
> >CrtcSettings[Index] << 8) | Index));
> +  }
> +
> +  for (Index = 0; Index < 9; Index++) {
> +    outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16)
> ((GraphicsController[Index] << 8) | Index));
> +  }
> +
> +  inb (Private, INPUT_STATUS_1_REGISTER);
> +
> +  for (Index = 0; Index < 21; Index++) {
> +    outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
> +    outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
> +  }
> +
> +  outb (Private, ATT_ADDRESS_REGISTER, 0x20);
> +
> +  outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
> +  outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
> +  outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
> +  outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
> +
> +  SetDefaultPalette (Private);
> +  ClearScreen (Private);
> +}
> +
> +VOID
> +BochsWrite (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINT16                   Reg,
> +  UINT16                   Data
> +  )
> +{
> +  EFI_STATUS   Status;
> +
> +  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
> +    Status = Private->PciIo->Mem.Write (
> +        Private->PciIo,
> +        EfiPciIoWidthUint16,
> +        PCI_BAR_IDX2,
> +        0x500 + (Reg << 1),
> +        1,
> +        &Data
> +        );
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
> +    outw (Private, VBE_DISPI_IOPORT_DATA,  Data);
> +  }
> +}
> +
> +UINT16
> +BochsRead (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINT16                   Reg
> +  )
> +{
> +  EFI_STATUS   Status;
> +  UINT16       Data;
> +
> +  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
> +    Status = Private->PciIo->Mem.Read (
> +        Private->PciIo,
> +        EfiPciIoWidthUint16,
> +        PCI_BAR_IDX2,
> +        0x500 + (Reg << 1),
> +        1,
> +        &Data
> +        );
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
> +    Data = inw (Private, VBE_DISPI_IOPORT_DATA);
> +  }
> +  return Data;
> +}
> +
> +VOID
> +VgaOutb (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                    Reg,
> +  UINT8                    Data
> +  )
> +{
> +  EFI_STATUS   Status;
> +
> +  if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
> +    Status = Private->PciIo->Mem.Write (
> +        Private->PciIo,
> +        EfiPciIoWidthUint8,
> +        PCI_BAR_IDX2,
> +        0x400 - 0x3c0 + Reg,
> +        1,
> +        &Data
> +        );
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    outb (Private, Reg, Data);
> +  }
> +}
> +
> +VOID
> +InitializeBochsGraphicsMode (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  QEMU_VIDEO_BOCHS_MODES  *ModeData
> +  )
> +{
> +  DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
> +          ModeData->Width, ModeData->Height, ModeData->ColorDepth));
> +
> +  /* unblank */
> +  VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
> +
> +  BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,      0);
> +  BochsWrite (Private, VBE_DISPI_INDEX_BANK,        0);
> +  BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET,    0);
> +  BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET,    0);
> +
> +  BochsWrite (Private, VBE_DISPI_INDEX_BPP,         (UINT16) ModeData-
> >ColorDepth);
> +  BochsWrite (Private, VBE_DISPI_INDEX_XRES,        (UINT16) ModeData-
> >Width);
> +  BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH,  (UINT16) ModeData-
> >Width);
> +  BochsWrite (Private, VBE_DISPI_INDEX_YRES,        (UINT16) ModeData-
> >Height);
> +  BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData-
> >Height);
> +
> +  BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
> +              VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
> +
> +  SetDefaultPalette (Private);
> +  ClearScreen (Private);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeQemuVideo (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  EFI_STATUS              Status;
> +
> +  Status = EfiLibInstallDriverBindingComponentName2 (
> +             ImageHandle,
> +             SystemTable,
> +             &gQemuVideoDriverBinding,
> +             ImageHandle,
> +             &gQemuVideoComponentName,
> +             &gQemuVideoComponentName2
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Install EFI Driver Supported EFI Version Protocol required for
> +  // EFI drivers that are on PCI and other plug in cards.
> +  //
> +  gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32
> (PcdDriverSupportedEfiVersion);
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &ImageHandle,
> +                  &gEfiDriverSupportedEfiVersionProtocolGuid,
> +                  &gQemuVideoDriverSupportedEfiVersion,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Dri
> verSupportedEfiVersion.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Dri
> verSupportedEfiVersion.c
> new file mode 100644
> index 0000000000..c2d82e7324
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Dri
> verSupportedEfiVersion.c
> @@ -0,0 +1,15 @@
> +/** @file
> +  Driver supported version protocol for the QEMU video driver.
> +
> +  Copyright (c) 2007 - 2010 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "Qemu.h"
> +
> +EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL
> gQemuVideoDriverSupportedEfiVersion = {
> +  sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of
> Protocol structure.
> +  0                                                   // Version number to be filled at start up.
> +};
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Go
> p.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Go
> p.c
> new file mode 100644
> index 0000000000..19ff5209d2
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Go
> p.c
> @@ -0,0 +1,417 @@
> +/** @file
> +  Graphics Output Protocol functions for the QEMU video controller.
> +
> +  Copyright (c) 2007 - 2018 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Qemu.h"
> +
> +STATIC
> +VOID
> +QemuVideoCompleteModeInfo (
> +  IN  QEMU_VIDEO_MODE_DATA           *ModeData,
> +  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
> +  )
> +{
> +  Info->Version = 0;
> +  if (ModeData->ColorDepth == 8) {
> +    Info->PixelFormat = PixelBitMask;
> +    Info->PixelInformation.RedMask = PIXEL_RED_MASK;
> +    Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
> +    Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
> +    Info->PixelInformation.ReservedMask = 0;
> +  } else if (ModeData->ColorDepth == 24) {
> +    Info->PixelFormat = PixelBitMask;
> +    Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
> +    Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
> +    Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
> +    Info->PixelInformation.ReservedMask = 0;
> +  } else if (ModeData->ColorDepth == 32) {
> +    DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
> +    Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
> +  }
> +  Info->PixelsPerScanLine = Info->HorizontalResolution;
> +}
> +
> +
> +STATIC
> +EFI_STATUS
> +QemuVideoCompleteModeData (
> +  IN  QEMU_VIDEO_PRIVATE_DATA           *Private,
> +  OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
> +  )
> +{
> +  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;
> +  QEMU_VIDEO_MODE_DATA           *ModeData;
> +
> +  ModeData = &Private->ModeData[Mode->Mode];
> +  Info = Mode->Info;
> +  QemuVideoCompleteModeInfo (ModeData, Info);
> +
> +  Private->PciIo->GetBarAttributes (
> +                        Private->PciIo,
> +                        0,
> +                        NULL,
> +                        (VOID**) &FrameBufDesc
> +                        );
> +
> +  Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
> +  Mode->FrameBufferSize = Info->HorizontalResolution * Info-
> >VerticalResolution;
> +  Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData-
> >ColorDepth + 7) / 8);
> +  Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (
> +                            EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)
> +                            );
> +  DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
> +    Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));
> +
> +  FreePool (FrameBufDesc);
> +  return EFI_SUCCESS;
> +}
> +
> +//
> +// Graphics Output Protocol Member Functions
> +//
> +EFI_STATUS
> +EFIAPI
> +QemuVideoGraphicsOutputQueryMode (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
> +  IN  UINT32                                ModeNumber,
> +  OUT UINTN                                 *SizeOfInfo,
> +  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Graphics Output protocol interface to query video mode
> +
> +  Arguments:
> +    This                  - Protocol instance pointer.
> +    ModeNumber            - The mode number to return information on.
> +    Info                  - Caller allocated buffer that returns information about
> ModeNumber.
> +    SizeOfInfo            - A pointer to the size, in bytes, of the Info buffer.
> +
> +  Returns:
> +    EFI_SUCCESS           - Mode information returned.
> +    EFI_BUFFER_TOO_SMALL  - The Info buffer was too small.
> +    EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the
> video mode.
> +    EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()
> +    EFI_INVALID_PARAMETER - One of the input args was NULL.
> +
> +--*/
> +{
> +  QEMU_VIDEO_PRIVATE_DATA  *Private;
> +  QEMU_VIDEO_MODE_DATA     *ModeData;
> +
> +  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS
> (This);
> +
> +  if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode-
> >MaxMode) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Info = AllocatePool (sizeof
> (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
> +  if (*Info == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
> +
> +  ModeData = &Private->ModeData[ModeNumber];
> +  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
> +  (*Info)->VerticalResolution   = ModeData->VerticalResolution;
> +  QemuVideoCompleteModeInfo (ModeData, *Info);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +QemuVideoGraphicsOutputSetMode (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
> +  IN  UINT32                       ModeNumber
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Graphics Output protocol interface to set video mode
> +
> +  Arguments:
> +    This             - Protocol instance pointer.
> +    ModeNumber       - The mode number to be set.
> +
> +  Returns:
> +    EFI_SUCCESS      - Graphics mode was changed.
> +    EFI_DEVICE_ERROR - The device had an error and could not complete the
> request.
> +    EFI_UNSUPPORTED  - ModeNumber is not supported by this device.
> +
> +--*/
> +{
> +  QEMU_VIDEO_PRIVATE_DATA       *Private;
> +  QEMU_VIDEO_MODE_DATA          *ModeData;
> +  RETURN_STATUS                 Status;
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
> +
> +  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS
> (This);
> +
> +  if (ModeNumber >= This->Mode->MaxMode) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ModeData = &Private->ModeData[ModeNumber];
> +
> +  switch (Private->Variant) {
> +  case QEMU_VIDEO_CIRRUS_5430:
> +  case QEMU_VIDEO_CIRRUS_5446:
> +    InitializeCirrusGraphicsMode (Private,
> &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
> +    break;
> +  case QEMU_VIDEO_BOCHS_MMIO:
> +  case QEMU_VIDEO_BOCHS:
> +    InitializeBochsGraphicsMode (Private,
> &QemuVideoBochsModes[ModeData->InternalModeIndex]);
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  This->Mode->Mode = ModeNumber;
> +  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
> +  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
> +  This->Mode->SizeOfInfo =
> sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
> +
> +  QemuVideoCompleteModeData (Private, This->Mode);
> +
> +  //
> +  // Re-initialize the frame buffer configure when mode changes.
> +  //
> +  Status = FrameBufferBltConfigure (
> +             (VOID*) (UINTN) This->Mode->FrameBufferBase,
> +             This->Mode->Info,
> +             Private->FrameBufferBltConfigure,
> +             &Private->FrameBufferBltConfigureSize
> +             );
> +  if (Status == RETURN_BUFFER_TOO_SMALL) {
> +    //
> +    // Frame buffer configure may be larger in new mode.
> +    //
> +    if (Private->FrameBufferBltConfigure != NULL) {
> +      FreePool (Private->FrameBufferBltConfigure);
> +    }
> +    Private->FrameBufferBltConfigure =
> +      AllocatePool (Private->FrameBufferBltConfigureSize);
> +    ASSERT (Private->FrameBufferBltConfigure != NULL);
> +
> +    //
> +    // Create the configuration for FrameBufferBltLib
> +    //
> +    Status = FrameBufferBltConfigure (
> +                (VOID*) (UINTN) This->Mode->FrameBufferBase,
> +                This->Mode->Info,
> +                Private->FrameBufferBltConfigure,
> +                &Private->FrameBufferBltConfigureSize
> +                );
> +  }
> +  ASSERT (Status == RETURN_SUCCESS);
> +
> +  //
> +  // Per UEFI Spec, need to clear the visible portions of the output display to
> black.
> +  //
> +  ZeroMem (&Black, sizeof (Black));
> +  Status = FrameBufferBlt (
> +             Private->FrameBufferBltConfigure,
> +             &Black,
> +             EfiBltVideoFill,
> +             0, 0,
> +             0, 0,
> +             This->Mode->Info->HorizontalResolution, This->Mode->Info-
> >VerticalResolution,
> +             0
> +             );
> +  ASSERT_RETURN_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +QemuVideoGraphicsOutputBlt (
> +  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
> +  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
> +  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
> +  IN  UINTN                                 SourceX,
> +  IN  UINTN                                 SourceY,
> +  IN  UINTN                                 DestinationX,
> +  IN  UINTN                                 DestinationY,
> +  IN  UINTN                                 Width,
> +  IN  UINTN                                 Height,
> +  IN  UINTN                                 Delta
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Graphics Output protocol instance to block transfer for CirrusLogic device
> +
> +Arguments:
> +
> +  This          - Pointer to Graphics Output protocol instance
> +  BltBuffer     - The data to transfer to screen
> +  BltOperation  - The operation to perform
> +  SourceX       - The X coordinate of the source for BltOperation
> +  SourceY       - The Y coordinate of the source for BltOperation
> +  DestinationX  - The X coordinate of the destination for BltOperation
> +  DestinationY  - The Y coordinate of the destination for BltOperation
> +  Width         - The width of a rectangle in the blt rectangle in pixels
> +  Height        - The height of a rectangle in the blt rectangle in pixels
> +  Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
> +                  If a Delta of 0 is used, the entire BltBuffer will be operated on.
> +                  If a subrectangle of the BltBuffer is used, then Delta represents
> +                  the number of bytes in a row of the BltBuffer.
> +
> +Returns:
> +
> +  EFI_INVALID_PARAMETER - Invalid parameter passed in
> +  EFI_SUCCESS - Blt operation success
> +
> +--*/
> +{
> +  EFI_STATUS                      Status;
> +  EFI_TPL                         OriginalTPL;
> +  QEMU_VIDEO_PRIVATE_DATA         *Private;
> +
> +  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS
> (This);
> +  //
> +  // We have to raise to TPL Notify, so we make an atomic write the frame
> buffer.
> +  // We would not want a timer based event (Cursor, ...) to come in while we
> are
> +  // doing this operation.
> +  //
> +  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
> +
> +  switch (BltOperation) {
> +  case EfiBltVideoToBltBuffer:
> +  case EfiBltBufferToVideo:
> +  case EfiBltVideoFill:
> +  case EfiBltVideoToVideo:
> +    Status = FrameBufferBlt (
> +      Private->FrameBufferBltConfigure,
> +      BltBuffer,
> +      BltOperation,
> +      SourceX,
> +      SourceY,
> +      DestinationX,
> +      DestinationY,
> +      Width,
> +      Height,
> +      Delta
> +      );
> +    break;
> +
> +  default:
> +    Status = EFI_INVALID_PARAMETER;
> +    break;
> +  }
> +
> +  gBS->RestoreTPL (OriginalTPL);
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +QemuVideoGraphicsOutputConstructor (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
> +
> +
> +  GraphicsOutput            = &Private->GraphicsOutput;
> +  GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
> +  GraphicsOutput->SetMode   = QemuVideoGraphicsOutputSetMode;
> +  GraphicsOutput->Blt       = QemuVideoGraphicsOutputBlt;
> +
> +  //
> +  // Initialize the private data
> +  //
> +  Status = gBS->AllocatePool (
> +                  EfiBootServicesData,
> +                  sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
> +                  (VOID **) &Private->GraphicsOutput.Mode
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = gBS->AllocatePool (
> +                  EfiBootServicesData,
> +                  sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
> +                  (VOID **) &Private->GraphicsOutput.Mode->Info
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeMode;
> +  }
> +  Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
> +  Private->GraphicsOutput.Mode->Mode    =
> GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
> +  Private->FrameBufferBltConfigure      = NULL;
> +  Private->FrameBufferBltConfigureSize  = 0;
> +
> +  //
> +  // Initialize the hardware
> +  //
> +  Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
> +  if (EFI_ERROR (Status)) {
> +    goto FreeInfo;
> +  }
> +
> +  DrawLogo (
> +    Private,
> +    Private->ModeData[Private->GraphicsOutput.Mode-
> >Mode].HorizontalResolution,
> +    Private->ModeData[Private->GraphicsOutput.Mode-
> >Mode].VerticalResolution
> +    );
> +
> +  return EFI_SUCCESS;
> +
> +FreeInfo:
> +  FreePool (Private->GraphicsOutput.Mode->Info);
> +
> +FreeMode:
> +  FreePool (Private->GraphicsOutput.Mode);
> +  Private->GraphicsOutput.Mode = NULL;
> +
> +  return Status;
> +}
> +
> +EFI_STATUS
> +QemuVideoGraphicsOutputDestructor (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  )
> +/*++
> +
> +Routine Description:
> +
> +Arguments:
> +
> +Returns:
> +
> +  None
> +
> +--*/
> +{
> +  if (Private->FrameBufferBltConfigure != NULL) {
> +    FreePool (Private->FrameBufferBltConfigure);
> +  }
> +
> +  if (Private->GraphicsOutput.Mode != NULL) {
> +    if (Private->GraphicsOutput.Mode->Info != NULL) {
> +      gBS->FreePool (Private->GraphicsOutput.Mode->Info);
> +    }
> +    gBS->FreePool (Private->GraphicsOutput.Mode);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Ini
> tialize.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Ini
> tialize.c
> new file mode 100644
> index 0000000000..fbf40e9eaf
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Ini
> tialize.c
> @@ -0,0 +1,341 @@
> +/** @file
> +  Graphics Output Protocol functions for the QEMU video controller.
> +
> +  Copyright (c) 2007 - 2010 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "Qemu.h"
> +
> +
> +///
> +/// Generic Attribute Controller Register Settings
> +///
> +UINT8  AttributeController[21] = {
> +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
> +  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
> +  0x41, 0x00, 0x0F, 0x00, 0x00
> +};
> +
> +///
> +/// Generic Graphics Controller Register Settings
> +///
> +UINT8 GraphicsController[9] = {
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
> +};
> +
> +//
> +// 640 x 480 x 256 color @ 60 Hertz
> +//
> +UINT8 Crtc_640_480_256_60[28] = {
> +  0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
> +  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
> +  0xff, 0x00, 0x00, 0x22
> +};
> +
> +UINT8 Crtc_640_480_32bpp_60[28] = {
> +  0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
> +  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,
> +  0xff, 0x00, 0x00, 0x32
> +};
> +
> +UINT16 Seq_640_480_256_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
> +};
> +
> +UINT16 Seq_640_480_32bpp_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
> +};
> +
> +//
> +// 800 x 600 x 256 color @ 60 Hertz
> +//
> +UINT8 Crtc_800_600_256_60[28] = {
> +  0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
> +  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
> +  0xFF, 0x00, 0x00, 0x22
> +};
> +
> +UINT8 Crtc_800_600_32bpp_60[28] = {
> +  0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
> +  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,
> +  0xFF, 0x00, 0x00, 0x32
> +};
> +
> +UINT16 Seq_800_600_256_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
> +};
> +
> +UINT16 Seq_800_600_32bpp_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
> +};
> +
> +UINT8 Crtc_960_720_32bpp_60[28] = {
> +  0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
> +  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
> +  0xFF, 0x4A, 0x00, 0x32
> +};
> +
> +UINT16 Seq_960_720_32bpp_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
> +};
> +
> +//
> +// 1024 x 768 x 256 color @ 60 Hertz
> +//
> +UINT8 Crtc_1024_768_256_60[28] = {
> +  0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
> +  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
> +  0xFF, 0x4A, 0x00, 0x22
> +};
> +
> +UINT16 Seq_1024_768_256_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
> +};
> +
> +//
> +// 1024 x 768 x 24-bit color @ 60 Hertz
> +//
> +UINT8 Crtc_1024_768_24bpp_60[28] = {
> +  0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
> +  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
> +  0xFF, 0x4A, 0x00, 0x32
> +};
> +
> +UINT16 Seq_1024_768_24bpp_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
> +};
> +
> +UINT8 Crtc_1024_768_32bpp_60[28] = {
> +  0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
> +  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
> +  0xFF, 0x4A, 0x00, 0x32
> +};
> +
> +UINT16 Seq_1024_768_32bpp_60[15] = {
> +  0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
> +  0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
> +};
> +
> +///
> +/// Table of supported video modes
> +///
> +QEMU_VIDEO_CIRRUS_MODES  QemuVideoCirrusModes[] = {
> +//  {  640, 480, 8, Crtc_640_480_256_60,  Seq_640_480_256_60,  0xe3 },
> +//  {  800, 600, 8, Crtc_800_600_256_60,  Seq_800_600_256_60,  0xef },
> +  {  640, 480, 32, Crtc_640_480_32bpp_60,  Seq_640_480_32bpp_60,  0xef },
> +  {  800, 600, 32, Crtc_800_600_32bpp_60,  Seq_800_600_32bpp_60,  0xef },
> +//  { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }
> +  { 1024, 768, 24, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60,
> 0xef }
> +//  { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60,
> 0xef }
> +//  { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef
> }
> +};
> +
> +#define QEMU_VIDEO_CIRRUS_MODE_COUNT \
> +  (ARRAY_SIZE (QemuVideoCirrusModes))
> +
> +/**
> +  Construct the valid video modes for QemuVideo.
> +
> +**/
> +EFI_STATUS
> +QemuVideoCirrusModeSetup (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  )
> +{
> +  UINT32                                 Index;
> +  QEMU_VIDEO_MODE_DATA                   *ModeData;
> +  QEMU_VIDEO_CIRRUS_MODES                *VideoMode;
> +
> +  //
> +  // Setup Video Modes
> +  //
> +  Private->ModeData = AllocatePool (
> +                        sizeof (Private->ModeData[0]) *
> QEMU_VIDEO_CIRRUS_MODE_COUNT
> +                        );
> +  if (Private->ModeData == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ModeData = Private->ModeData;
> +  VideoMode = &QemuVideoCirrusModes[0];
> +  for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) {
> +    ModeData->InternalModeIndex = Index;
> +    ModeData->HorizontalResolution          = VideoMode->Width;
> +    ModeData->VerticalResolution            = VideoMode->Height;
> +    ModeData->ColorDepth                    = VideoMode->ColorDepth;
> +    DEBUG ((EFI_D_INFO,
> +      "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",
> +      (INT32) (ModeData - Private->ModeData),
> +      ModeData->InternalModeIndex,
> +      ModeData->HorizontalResolution,
> +      ModeData->VerticalResolution,
> +      ModeData->ColorDepth
> +      ));
> +
> +    ModeData ++ ;
> +    VideoMode ++;
> +  }
> +  Private->MaxMode = ModeData - Private->ModeData;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +///
> +/// Table of supported video modes
> +///
> +QEMU_VIDEO_BOCHS_MODES  QemuVideoBochsModes[] = {
> +  {  640,  480, 32 },
> +  {  800,  480, 32 },
> +  {  800,  600, 32 },
> +  {  832,  624, 32 },
> +  {  960,  640, 32 },
> +  { 1024,  600, 32 },
> +  { 1024,  768, 32 },
> +  { 1152,  864, 32 },
> +  { 1152,  870, 32 },
> +  { 1280,  720, 32 },
> +  { 1280,  760, 32 },
> +  { 1280,  768, 32 },
> +  { 1280,  800, 32 },
> +  { 1280,  960, 32 },
> +  { 1280, 1024, 32 },
> +  { 1360,  768, 32 },
> +  { 1366,  768, 32 },
> +  { 1400, 1050, 32 },
> +  { 1440,  900, 32 },
> +  { 1600,  900, 32 },
> +  { 1600, 1200, 32 },
> +  { 1680, 1050, 32 },
> +  { 1920, 1080, 32 },
> +  { 1920, 1200, 32 },
> +  { 1920, 1440, 32 },
> +  { 2000, 2000, 32 },
> +  { 2048, 1536, 32 },
> +  { 2048, 2048, 32 },
> +  { 2560, 1440, 32 },
> +  { 2560, 1600, 32 },
> +  { 2560, 2048, 32 },
> +  { 2800, 2100, 32 },
> +  { 3200, 2400, 32 },
> +  { 3840, 2160, 32 },
> +  { 4096, 2160, 32 },
> +  { 7680, 4320, 32 },
> +  { 8192, 4320, 32 }
> +};
> +
> +#define QEMU_VIDEO_BOCHS_MODE_COUNT \
> +  (ARRAY_SIZE (QemuVideoBochsModes))
> +
> +EFI_STATUS
> +QemuVideoBochsModeSetup (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  BOOLEAN                  IsQxl
> +  )
> +{
> +  UINT32                                 AvailableFbSize;
> +  UINT32                                 Index;
> +  QEMU_VIDEO_MODE_DATA                   *ModeData;
> +  QEMU_VIDEO_BOCHS_MODES                 *VideoMode;
> +
> +  //
> +  // Fetch the available framebuffer size.
> +  //
> +  // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of
> the
> +  // drawable framebuffer. Up to and including qemu-2.1 however it used to
> +  // return the size of PCI BAR 0 (ie. the full video RAM size).
> +  //
> +  // On stdvga the two concepts coincide with each other; the full memory size
> +  // is usable for drawing.
> +  //
> +  // On QXL however, only a leading segment, "surface 0", can be used for
> +  // drawing; the rest of the video memory is used for the QXL guest-host
> +  // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size
> of
> +  // "surface 0", but since it doesn't (up to and including qemu-2.1), we
> +  // retrieve the size of the drawable portion from a field in the QXL ROM BAR,
> +  // where it is also available.
> +  //
> +  if (IsQxl) {
> +    UINT32 Signature;
> +    UINT32 DrawStart;
> +
> +    Signature = 0;
> +    DrawStart = 0xFFFFFFFF;
> +    AvailableFbSize = 0;
> +    if (EFI_ERROR (
> +          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
> +                                PCI_BAR_IDX2, 0, 1, &Signature)) ||
> +        Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||
> +        EFI_ERROR (
> +          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
> +                                PCI_BAR_IDX2, 36, 1, &DrawStart)) ||
> +        DrawStart != 0 ||
> +        EFI_ERROR (
> +          Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
> +                                PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {
> +      DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "
> +        "ROM\n", __FUNCTION__));
> +      return EFI_NOT_FOUND;
> +    }
> +  } else {
> +    AvailableFbSize  = BochsRead (Private,
> VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
> +    AvailableFbSize *= SIZE_64KB;
> +  }
> +  DEBUG ((EFI_D_INFO, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,
> +    AvailableFbSize));
> +
> +  //
> +  // Setup Video Modes
> +  //
> +  Private->ModeData = AllocatePool (
> +                        sizeof (Private->ModeData[0]) *
> QEMU_VIDEO_BOCHS_MODE_COUNT
> +                        );
> +  if (Private->ModeData == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  ModeData = Private->ModeData;
> +  VideoMode = &QemuVideoBochsModes[0];
> +  for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {
> +    UINTN RequiredFbSize;
> +
> +    ASSERT (VideoMode->ColorDepth % 8 == 0);
> +    RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *
> +                     (VideoMode->ColorDepth / 8);
> +    if (RequiredFbSize <= AvailableFbSize) {
> +      ModeData->InternalModeIndex    = Index;
> +      ModeData->HorizontalResolution = VideoMode->Width;
> +      ModeData->VerticalResolution   = VideoMode->Height;
> +      ModeData->ColorDepth           = VideoMode->ColorDepth;
> +      DEBUG ((EFI_D_INFO,
> +        "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit\n",
> +        (INT32) (ModeData - Private->ModeData),
> +        ModeData->InternalModeIndex,
> +        ModeData->HorizontalResolution,
> +        ModeData->VerticalResolution,
> +        ModeData->ColorDepth
> +        ));
> +
> +      ModeData ++ ;
> +    }
> +    VideoMode ++;
> +  }
> +  Private->MaxMode = ModeData - Private->ModeData;
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.c
> new file mode 100644
> index 0000000000..aa4648f813
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.c
> @@ -0,0 +1,302 @@
> +/** @file
> +  Install a fake VGABIOS service handler (real mode Int10h) for the buggy
> +  Windows 2008 R2 SP1 UEFI guest.
> +
> +  The handler is never meant to be directly executed by a VCPU; it's there for
> +  the internal real mode emulator of Windows 2008 R2 SP1.
> +
> +  The code is based on Ralf Brown's Interrupt List:
> +  <http://www.cs.cmu.edu/~ralf/files.html>
> +  <http://www.ctyme.com/rbrown.htm>
> +
> +  Copyright (C) 2014, Red Hat, Inc.
> +  Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <IndustryStandard/LegacyVgaBios.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/PrintLib.h>
> +#include <SimicsPlatforms.h>
> +
> +#include "Qemu.h"
> +#include "VbeShim.h"
> +
> +#pragma pack (1)
> +typedef struct {
> +  UINT16 Offset;
> +  UINT16 Segment;
> +} IVT_ENTRY;
> +#pragma pack ()
> +
> +//
> +// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
> +// Advanced Settings dialog. It should be short.
> +//
> +STATIC CONST CHAR8 mProductRevision[] = "OVMF Int10h (fake)";
> +
> +/**
> +  Install the VBE Info and VBE Mode Info structures, and the VBE service
> +  handler routine in the C segment. Point the real-mode Int10h interrupt vector
> +  to the handler. The only advertised mode is 1024x768x32.
> +
> +  @param[in] CardName         Name of the video card to be exposed in the
> +                              Product Name field of the VBE Info structure. The
> +                              parameter must originate from a
> +                              QEMU_VIDEO_CARD.Name field.
> +  @param[in] FrameBufferBase  Guest-physical base address of the video card's
> +                              frame buffer.
> +**/
> +VOID
> +InstallVbeShim (
> +  IN CONST CHAR16         *CardName,
> +  IN EFI_PHYSICAL_ADDRESS FrameBufferBase
> +  )
> +{
> +  EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
> +  UINTN                Segment0Pages;
> +  IVT_ENTRY            *Int0x10;
> +  EFI_STATUS           Segment0AllocationStatus;
> +  UINT16               HostBridgeDevId;
> +  UINTN                SegmentCPages;
> +  VBE_INFO             *VbeInfoFull;
> +  VBE_INFO_BASE        *VbeInfo;
> +  UINT8                *Ptr;
> +  UINTN                Printed;
> +  VBE_MODE_INFO        *VbeModeInfo;
> +
> +  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> {
> +    DEBUG ((
> +      DEBUG_WARN,
> +      "%a: page 0 protected, not installing VBE shim\n",
> +      __FUNCTION__
> +      ));
> +    DEBUG ((
> +      DEBUG_WARN,
> +      "%a: page 0 protection prevents Windows 7 from booting anyway\n",
> +      __FUNCTION__
> +      ));
> +    return;
> +  }
> +
> +  Segment0 = 0x00000;
> +  SegmentC = 0xC0000;
> +  SegmentF = 0xF0000;
> +
> +  //
> +  // Attempt to cover the real mode IVT with an allocation. This is a UEFI
> +  // driver, hence the arch protocols have been installed previously. Among
> +  // those, the CPU arch protocol has configured the IDT, so we can overwrite
> +  // the IVT used in real mode.
> +  //
> +  // The allocation request may fail, eg. if LegacyBiosDxe has already run.
> +  //
> +  Segment0Pages = 1;
> +  Int0x10       = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
> +  Segment0AllocationStatus = gBS->AllocatePages (
> +                                    AllocateAddress,
> +                                    EfiBootServicesCode,
> +                                    Segment0Pages,
> +                                    &Segment0
> +                                    );
> +
> +  if (EFI_ERROR (Segment0AllocationStatus)) {
> +    EFI_PHYSICAL_ADDRESS Handler;
> +
> +    //
> +    // Check if a video BIOS handler has been installed previously -- we
> +    // shouldn't override a real video BIOS with our shim, nor our own shim if
> +    // it's already present.
> +    //
> +    Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
> +    if (Handler >= SegmentC && Handler < SegmentF) {
> +      DEBUG ((EFI_D_INFO, "%a: Video BIOS handler found at %04x:%04x\n",
> +        __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
> +      return;
> +    }
> +
> +    //
> +    // Otherwise we'll overwrite the Int10h vector, even though we may not
> own
> +    // the page at zero.
> +    //
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "%a: failed to allocate page at zero: %r\n",
> +      __FUNCTION__,
> +      Segment0AllocationStatus
> +      ));
> +  } else {
> +    //
> +    // We managed to allocate the page at zero. SVN r14218 guarantees that it
> +    // is NUL-filled.
> +    //
> +    ASSERT (Int0x10->Segment == 0x0000);
> +    ASSERT (Int0x10->Offset  == 0x0000);
> +  }
> +
> +  HostBridgeDevId = PcdGet16(PcdSimicsX58HostBridgePciDevId);
> +  switch (HostBridgeDevId) {
> +    case INTEL_ICH10_DEVICE_ID:
> +      break;
> +    default:
> +      DEBUG((
> +            DEBUG_ERROR,
> +            "%a: unknown host bridge device ID: 0x%04x\n",
> +            __FUNCTION__,
> +            HostBridgeDevId
> +      ));
> +      ASSERT (FALSE);
> +
> +      if (!EFI_ERROR(Segment0AllocationStatus)) {
> +        gBS->FreePages(Segment0, Segment0Pages);
> +      }
> +      return;
> +  }
> +  //
> +  // low nibble covers 0xC0000 to 0xC3FFF
> +  // high nibble covers 0xC4000 to 0xC7FFF
> +  // bit1 in each nibble is Write Enable
> +  // bit0 in each nibble is Read Enable
> +  //
> +
> +  //
> +  // We never added memory space during PEI or DXE for the C segment, so we
> +  // don't need to (and can't) allocate from there. Also, guest operating
> +  // systems will see a hole in the UEFI memory map there.
> +  //
> +  SegmentCPages = 4;
> +
> +  ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
> +  CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim);
> +
> +  //
> +  // Fill in the VBE INFO structure.
> +  //
> +  VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
> +  VbeInfo     = &VbeInfoFull->Base;
> +  Ptr         = VbeInfoFull->Buffer;
> +
> +  CopyMem (VbeInfo->Signature, "VESA", 4);
> +  VbeInfo->VesaVersion = 0x0300;
> +
> +  VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 |
> (UINT16)(UINTN)Ptr;
> +  CopyMem (Ptr, "QEMU", 5);
> +  Ptr += 5;
> +
> +  VbeInfo->Capabilities = BIT0; // DAC can be switched into 8-bit mode
> +
> +  VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 |
> (UINT16)(UINTN)Ptr;
> +  *(UINT16*)Ptr = 0x00f1; // mode number
> +  Ptr += 2;
> +  *(UINT16*)Ptr = 0xFFFF; // mode list terminator
> +  Ptr += 2;
> +
> +  VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
> +  VbeInfo->OemSoftwareVersion = 0x0000;
> +
> +  VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 |
> (UINT16)(UINTN)Ptr;
> +  CopyMem (Ptr, "OVMF", 5);
> +  Ptr += 5;
> +
> +  VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 |
> (UINT16)(UINTN)Ptr;
> +  Printed = AsciiSPrint ((CHAR8 *)Ptr,
> +              sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
> +              CardName);
> +  Ptr += Printed + 1;
> +
> +  VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 |
> (UINT16)(UINTN)Ptr;
> +  CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
> +  Ptr += sizeof mProductRevision;
> +
> +  ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
> +  ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
> +
> +  //
> +  // Fil in the VBE MODE INFO structure.
> +  //
> +  VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
> +
> +  //
> +  // bit0: mode supported by present hardware configuration
> +  // bit1: optional information available (must be =1 for VBE v1.2+)
> +  // bit3: set if color, clear if monochrome
> +  // bit4: set if graphics mode, clear if text mode
> +  // bit5: mode is not VGA-compatible
> +  // bit7: linear framebuffer mode supported
> +  //
> +  VbeModeInfo->ModeAttr = BIT7 | BIT5 | BIT4 | BIT3 | BIT1 | BIT0;
> +
> +  //
> +  // bit0: exists
> +  // bit1: bit1: readable
> +  // bit2: writeable
> +  //
> +  VbeModeInfo->WindowAAttr              = BIT2 | BIT1 | BIT0;
> +
> +  VbeModeInfo->WindowBAttr              = 0x00;
> +  VbeModeInfo->WindowGranularityKB      = 0x0040;
> +  VbeModeInfo->WindowSizeKB             = 0x0040;
> +  VbeModeInfo->WindowAStartSegment      = 0xA000;
> +  VbeModeInfo->WindowBStartSegment      = 0x0000;
> +  VbeModeInfo->WindowPositioningAddress = 0x0000;
> +  VbeModeInfo->BytesPerScanLine         = 1024 * 4;
> +
> +  VbeModeInfo->Width                = 1024;
> +  VbeModeInfo->Height               = 768;
> +  VbeModeInfo->CharCellWidth        = 8;
> +  VbeModeInfo->CharCellHeight       = 16;
> +  VbeModeInfo->NumPlanes            = 1;
> +  VbeModeInfo->BitsPerPixel         = 32;
> +  VbeModeInfo->NumBanks             = 1;
> +  VbeModeInfo->MemoryModel          = 6; // direct color
> +  VbeModeInfo->BankSizeKB           = 0;
> +  VbeModeInfo->NumImagePagesLessOne = 0;
> +  VbeModeInfo->Vbe3                 = 0x01;
> +
> +  VbeModeInfo->RedMaskSize      = 8;
> +  VbeModeInfo->RedMaskPos       = 16;
> +  VbeModeInfo->GreenMaskSize    = 8;
> +  VbeModeInfo->GreenMaskPos     = 8;
> +  VbeModeInfo->BlueMaskSize     = 8;
> +  VbeModeInfo->BlueMaskPos      = 0;
> +  VbeModeInfo->ReservedMaskSize = 8;
> +  VbeModeInfo->ReservedMaskPos  = 24;
> +
> +  //
> +  // bit1: Bytes in reserved field may be used by application
> +  //
> +  VbeModeInfo->DirectColorModeInfo = BIT1;
> +
> +  VbeModeInfo->LfbAddress       = (UINT32)FrameBufferBase;
> +  VbeModeInfo->OffScreenAddress = 0;
> +  VbeModeInfo->OffScreenSizeKB  = 0;
> +
> +  VbeModeInfo->BytesPerScanLineLinear = 1024 * 4;
> +  VbeModeInfo->NumImagesLessOneBanked = 0;
> +  VbeModeInfo->NumImagesLessOneLinear = 0;
> +  VbeModeInfo->RedMaskSizeLinear      = 8;
> +  VbeModeInfo->RedMaskPosLinear       = 16;
> +  VbeModeInfo->GreenMaskSizeLinear    = 8;
> +  VbeModeInfo->GreenMaskPosLinear     = 8;
> +  VbeModeInfo->BlueMaskSizeLinear     = 8;
> +  VbeModeInfo->BlueMaskPosLinear      = 0;
> +  VbeModeInfo->ReservedMaskSizeLinear = 8;
> +  VbeModeInfo->ReservedMaskPosLinear  = 24;
> +  VbeModeInfo->MaxPixelClockHz        = 0;
> +
> +  ZeroMem (VbeModeInfo->Reserved, sizeof VbeModeInfo->Reserved);
> +
> +  //
> +  // Clear Write Enable (bit1), keep Read Enable (bit0) set
> +  //
> +
> +  //
> +  // Second, point the Int10h vector at the shim.
> +  //
> +  Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
> +  Int0x10->Offset  = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
> +
> +  DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__));
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.c
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.c
> new file mode 100644
> index 0000000000..b57bacdda4
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.c
> @@ -0,0 +1,622 @@
> +/** @file
> +  This contains the installation function for the driver.
> +
> +  Copyright (c) 2005 - 2018 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "8259.h"
> +
> +//
> +// Global for the Legacy 8259 Protocol that is produced by this driver
> +//
> +EFI_LEGACY_8259_PROTOCOL  mInterrupt8259 = {
> +  Interrupt8259SetVectorBase,
> +  Interrupt8259GetMask,
> +  Interrupt8259SetMask,
> +  Interrupt8259SetMode,
> +  Interrupt8259GetVector,
> +  Interrupt8259EnableIrq,
> +  Interrupt8259DisableIrq,
> +  Interrupt8259GetInterruptLine,
> +  Interrupt8259EndOfInterrupt
> +};
> +
> +//
> +// Global for the handle that the Legacy 8259 Protocol is installed
> +//
> +EFI_HANDLE                m8259Handle             = NULL;
> +
> +UINT8                     mMasterBase             = 0xff;
> +UINT8                     mSlaveBase              = 0xff;
> +EFI_8259_MODE             mMode                   = Efi8259ProtectedMode;
> +UINT16                    mProtectedModeMask      = 0xffff;
> +UINT16                    mLegacyModeMask;
> +UINT16                    mProtectedModeEdgeLevel = 0x0000;
> +UINT16                    mLegacyModeEdgeLevel;
> +
> +//
> +// Worker Functions
> +//
> +
> +/**
> +  Write to mask and edge/level triggered registers of master and slave 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));
> +}
> +
> +/**
> +  Read from mask and edge/level triggered registers of master and slave PICs.
> +
> +  @param[out]  Mask       low byte for master PIC mask register,
> +                          high byte for slave PIC mask register.
> +  @param[out]  EdgeLevel  low byte for master PIC edge/level triggered
> register,
> +                          high byte for slave PIC edge/level triggered register.
> +
> +**/
> +VOID
> +Interrupt8259ReadMask (
> +  OUT UINT16  *Mask,
> +  OUT UINT16  *EdgeLevel
> +  )
> +{
> +  UINT16  MasterValue;
> +  UINT16  SlaveValue;
> +
> +  if (Mask != NULL) {
> +    MasterValue = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);
> +    SlaveValue  = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);
> +
> +    *Mask = (UINT16) (MasterValue | (SlaveValue << 8));
> +  }
> +
> +  if (EdgeLevel != NULL) {
> +    MasterValue = IoRead8
> (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER);
> +    SlaveValue  = IoRead8
> (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE);
> +
> +    *EdgeLevel = (UINT16) (MasterValue | (SlaveValue << 8));
> +  }
> +}
> +
> +//
> +// Legacy 8259 Protocol Interface Functions
> +//
> +
> +/**
> +  Sets the base address for the 8259 master and slave PICs.
> +
> +  @param[in]  This        Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  MasterBase  Interrupt vectors for IRQ0-IRQ7.
> +  @param[in]  SlaveBase   Interrupt vectors for IRQ8-IRQ15.
> +
> +  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
> +  @retval  EFI_DEVICE_ERROR  There was an error while writing to the 8259
> PIC.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259SetVectorBase (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN UINT8                     MasterBase,
> +  IN UINT8                     SlaveBase
> +  )
> +{
> +  UINT8   Mask;
> +  EFI_TPL OriginalTpl;
> +
> +  OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +  //
> +  // Set vector base for slave PIC
> +  //
> +  if (SlaveBase != mSlaveBase) {
> +    mSlaveBase = SlaveBase;
> +
> +    //
> +    // Initialization sequence is needed for setting vector base.
> +    //
> +
> +    //
> +    // Preserve interrtup mask register before initialization sequence
> +    // because it will be cleared during initialization
> +    //
> +    Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE);
> +
> +    //
> +    // ICW1: cascade mode, ICW4 write required
> +    //
> +    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11);
> +
> +    //
> +    // ICW2: new vector base (must be multiple of 8)
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase);
> +
> +    //
> +    // ICW3: slave indentification code must be 2
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02);
> +
> +    //
> +    // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01);
> +
> +    //
> +    // Restore interrupt mask register
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask);
> +  }
> +
> +  //
> +  // Set vector base for master PIC
> +  //
> +  if (MasterBase != mMasterBase) {
> +    mMasterBase = MasterBase;
> +
> +    //
> +    // Initialization sequence is needed for setting vector base.
> +    //
> +
> +    //
> +    // Preserve interrtup mask register before initialization sequence
> +    // because it will be cleared during initialization
> +    //
> +    Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER);
> +
> +    //
> +    // ICW1: cascade mode, ICW4 write required
> +    //
> +    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11);
> +
> +    //
> +    // ICW2: new vector base (must be multiple of 8)
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase);
> +
> +    //
> +    // ICW3: slave PIC is cascaded on IRQ2
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04);
> +
> +    //
> +    // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01);
> +
> +    //
> +    // Restore interrupt mask register
> +    //
> +    IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask);
> +  }
> +
> +  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
> +  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER,
> LEGACY_8259_EOI);
> +
> +  gBS->RestoreTPL (OriginalTpl);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
> +
> +  @param[in]   This                Indicates the EFI_LEGACY_8259_PROTOCOL
> instance.
> +  @param[out]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
> +  @param[out]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-
> IRQ15.
> +  @param[out]  ProtectedMask       32-bit mode interrupt mask for IRQ0-
> IRQ15.
> +  @param[out]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-
> IRQ15.
> +
> +  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
> +  @retval  EFI_DEVICE_ERROR  There was an error while reading the 8259 PIC.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259GetMask (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  OUT UINT16                    *LegacyMask, OPTIONAL
> +  OUT UINT16                    *LegacyEdgeLevel, OPTIONAL
> +  OUT UINT16                    *ProtectedMask, OPTIONAL
> +  OUT UINT16                    *ProtectedEdgeLevel OPTIONAL
> +  )
> +{
> +  if (LegacyMask != NULL) {
> +    *LegacyMask = mLegacyModeMask;
> +  }
> +
> +  if (LegacyEdgeLevel != NULL) {
> +    *LegacyEdgeLevel = mLegacyModeEdgeLevel;
> +  }
> +
> +  if (ProtectedMask != NULL) {
> +    *ProtectedMask = mProtectedModeMask;
> +  }
> +
> +  if (ProtectedEdgeLevel != NULL) {
> +    *ProtectedEdgeLevel = mProtectedModeEdgeLevel;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
> +
> +  @param[in]  This                Indicates the EFI_LEGACY_8259_PROTOCOL
> instance.
> +  @param[in]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
> +  @param[in]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-IRQ15.
> +  @param[in]  ProtectedMask       32-bit mode interrupt mask for IRQ0-IRQ15.
> +  @param[in]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-
> IRQ15.
> +
> +  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
> +  @retval  EFI_DEVICE_ERROR  There was an error while writing the 8259 PIC.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259SetMask (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN UINT16                    *LegacyMask, OPTIONAL
> +  IN UINT16                    *LegacyEdgeLevel, OPTIONAL
> +  IN UINT16                    *ProtectedMask, OPTIONAL
> +  IN UINT16                    *ProtectedEdgeLevel OPTIONAL
> +  )
> +{
> +  if (LegacyMask != NULL) {
> +    mLegacyModeMask = *LegacyMask;
> +  }
> +
> +  if (LegacyEdgeLevel != NULL) {
> +    mLegacyModeEdgeLevel = *LegacyEdgeLevel;
> +  }
> +
> +  if (ProtectedMask != NULL) {
> +    mProtectedModeMask = *ProtectedMask;
> +  }
> +
> +  if (ProtectedEdgeLevel != NULL) {
> +    mProtectedModeEdgeLevel = *ProtectedEdgeLevel;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Sets the mode of the PICs.
> +
> +  @param[in]  This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Mode       16-bit real or 32-bit protected mode.
> +  @param[in]  Mask       The value with which to set the interrupt mask.
> +  @param[in]  EdgeLevel  The value with which to set the edge/level mask.
> +
> +  @retval  EFI_SUCCESS            The mode was set successfully.
> +  @retval  EFI_INVALID_PARAMETER  The mode was not set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259SetMode (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_MODE             Mode,
> +  IN UINT16                    *Mask, OPTIONAL
> +  IN UINT16                    *EdgeLevel OPTIONAL
> +  )
> +{
> +  if (Mode == mMode) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (Mode == Efi8259LegacyMode) {
> +    //
> +    // In Efi8259ProtectedMode, mask and edge/level trigger registers should
> +    // be changed through this protocol, so we can track them in the
> +    // corresponding module variables.
> +    //
> +    Interrupt8259ReadMask (&mProtectedModeMask,
> &mProtectedModeEdgeLevel);
> +
> +    if (Mask != NULL) {
> +      //
> +      // Update the Mask for the new mode
> +      //
> +      mLegacyModeMask = *Mask;
> +    }
> +
> +    if (EdgeLevel != NULL) {
> +      //
> +      // Update the Edge/Level triggered mask for the new mode
> +      //
> +      mLegacyModeEdgeLevel = *EdgeLevel;
> +    }
> +
> +    mMode = Mode;
> +
> +    //
> +    // Write new legacy mode mask/trigger level
> +    //
> +    Interrupt8259WriteMask (mLegacyModeMask, mLegacyModeEdgeLevel);
> +
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (Mode == Efi8259ProtectedMode) {
> +    //
> +    // Save the legacy mode mask/trigger level
> +    //
> +    Interrupt8259ReadMask (&mLegacyModeMask, &mLegacyModeEdgeLevel);
> +    //
> +    // Always force Timer to be enabled after return from 16-bit code.
> +    // This always insures that on next entry, timer is counting.
> +    //
> +    mLegacyModeMask &= 0xFFFE;
> +
> +    if (Mask != NULL) {
> +      //
> +      // Update the Mask for the new mode
> +      //
> +      mProtectedModeMask = *Mask;
> +    }
> +
> +    if (EdgeLevel != NULL) {
> +      //
> +      // Update the Edge/Level triggered mask for the new mode
> +      //
> +      mProtectedModeEdgeLevel = *EdgeLevel;
> +    }
> +
> +    mMode = Mode;
> +
> +    //
> +    // Write new protected mode mask/trigger level
> +    //
> +    Interrupt8259WriteMask (mProtectedModeMask,
> mProtectedModeEdgeLevel);
> +
> +    return EFI_SUCCESS;
> +  }
> +
> +  return EFI_INVALID_PARAMETER;
> +}
> +
> +/**
> +  Translates the IRQ into a vector.
> +
> +  @param[in]   This    Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]   Irq     IRQ0-IRQ15.
> +  @param[out]  Vector  The vector that is assigned to the IRQ.
> +
> +  @retval  EFI_SUCCESS            The Vector that matches Irq was returned.
> +  @retval  EFI_INVALID_PARAMETER  Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259GetVector (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN  EFI_8259_IRQ              Irq,
> +  OUT UINT8                     *Vector
> +  )
> +{
> +  if ((UINT32)Irq > Efi8259Irq15) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Irq <= Efi8259Irq7) {
> +    *Vector = (UINT8) (mMasterBase + Irq);
> +  } else {
> +    *Vector = (UINT8) (mSlaveBase + (Irq - Efi8259Irq8));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Enables the specified IRQ.
> +
> +  @param[in]  This            Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Irq             IRQ0-IRQ15.
> +  @param[in]  LevelTriggered  0 = Edge triggered; 1 = Level triggered.
> +
> +  @retval  EFI_SUCCESS            The Irq was enabled on the 8259 PIC.
> +  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259EnableIrq (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_IRQ              Irq,
> +  IN BOOLEAN                   LevelTriggered
> +  )
> +{
> +  if ((UINT32)Irq > Efi8259Irq15) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  mProtectedModeMask = (UINT16) (mProtectedModeMask & ~(1 << Irq));
> +  if (LevelTriggered) {
> +    mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel | (1 <<
> Irq));
> +  } else {
> +    mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1
> << Irq));
> +  }
> +
> +  Interrupt8259WriteMask (mProtectedModeMask,
> mProtectedModeEdgeLevel);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Disables the specified IRQ.
> +
> +  @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Irq   IRQ0-IRQ15.
> +
> +  @retval  EFI_SUCCESS            The Irq was disabled on the 8259 PIC.
> +  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259DisableIrq (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_IRQ              Irq
> +  )
> +{
> +  if ((UINT32)Irq > Efi8259Irq15) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  mProtectedModeMask = (UINT16) (mProtectedModeMask | (1 << Irq));
> +
> +  mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 <<
> Irq));
> +
> +  Interrupt8259WriteMask (mProtectedModeMask,
> mProtectedModeEdgeLevel);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Reads the PCI configuration space to get the interrupt number that is assigned
> to the card.
> +
> +  @param[in]   This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]   PciHandle  PCI function for which to return the vector.
> +  @param[out]  Vector     IRQ number that corresponds to the interrupt line.
> +
> +  @retval  EFI_SUCCESS  The interrupt line value was read successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259GetInterruptLine (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN  EFI_HANDLE                PciHandle,
> +  OUT UINT8                     *Vector
> +  )
> +{
> +  EFI_PCI_IO_PROTOCOL *PciIo;
> +  UINT8               InterruptLine;
> +  EFI_STATUS          Status;
> +
> +  Status = gBS->HandleProtocol (
> +                  PciHandle,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **) &PciIo
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PciIo->Pci.Read (
> +               PciIo,
> +               EfiPciIoWidthUint8,
> +               PCI_INT_LINE_OFFSET,
> +               1,
> +               &InterruptLine
> +               );
> +  //
> +  // Interrupt line is same location for standard PCI cards, standard
> +  // bridge and CardBus bridge.
> +  //
> +  *Vector = InterruptLine;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Issues the End of Interrupt (EOI) commands to PICs.
> +
> +  @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Irq   The interrupt for which to issue the EOI command.
> +
> +  @retval  EFI_SUCCESS            The EOI command was issued.
> +  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259EndOfInterrupt (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_IRQ              Irq
> +  )
> +{
> +  if ((UINT32)Irq > Efi8259Irq15) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Irq >= Efi8259Irq8) {
> +    IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI);
> +  }
> +
> +  IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER,
> LEGACY_8259_EOI);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Driver Entry point.
> +
> +  @param[in]  ImageHandle  ImageHandle of the loaded driver.
> +  @param[in]  SystemTable  Pointer to the EFI System Table.
> +
> +  @retval  EFI_SUCCESS  One or more of the drivers returned a success code.
> +  @retval  !EFI_SUCCESS  Error installing Legacy 8259 Protocol.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Install8259 (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS   Status;
> +  EFI_8259_IRQ Irq;
> +
> +  //
> +  // Initialze mask values from PCDs
> +  //
> +  mLegacyModeMask      = PcdGet16 (Pcd8259LegacyModeMask);
> +  mLegacyModeEdgeLevel = PcdGet16 (Pcd8259LegacyModeEdgeLevel);
> +
> +  //
> +  // Clear all pending interrupt
> +  //
> +  for (Irq = Efi8259Irq0; Irq <= Efi8259Irq15; Irq++) {
> +    Interrupt8259EndOfInterrupt (&mInterrupt8259, Irq);
> +  }
> +
> +  //
> +  // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70
> +  //
> +  Status = Interrupt8259SetVectorBase (&mInterrupt8259,
> PROTECTED_MODE_BASE_VECTOR_MASTER,
> PROTECTED_MODE_BASE_VECTOR_SLAVE);
> +
> +  //
> +  // Set all 8259 interrupts to edge triggered and disabled
> +  //
> +  Interrupt8259WriteMask (mProtectedModeMask,
> mProtectedModeEdgeLevel);
> +
> +  //
> +  // Install 8259 Protocol onto a new handle
> +  //
> +  Status = gBS->InstallProtocolInterface (
> +                  &m8259Handle,
> +                  &gEfiLegacy8259ProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  &mInterrupt8259
> +                  );
> +  return Status;
> +}
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridge.h
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridge.h
> new file mode 100644
> index 0000000000..3bf31067fa
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridge.h
> @@ -0,0 +1,68 @@
> +/** @file
> +  Header file of OVMF instance of PciHostBridgeLib.
> +
> +  Copyright (c) 2016 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +PCI_ROOT_BRIDGE *
> +ScanForRootBridges (
> +  UINTN      *NumberOfRootBridges
> +);
> +
> +/**
> +  Initialize a PCI_ROOT_BRIDGE structure.
> +
> +  @param[in]  Supports         Supported attributes.
> +
> +  @param[in]  Attributes       Initial attributes.
> +
> +  @param[in]  AllocAttributes  Allocation attributes.
> +
> +  @param[in]  RootBusNumber    The bus number to store in RootBus.
> +
> +  @param[in]  MaxSubBusNumber  The inclusive maximum bus number that
> can be
> +                               assigned to any subordinate bus found behind any
> +                               PCI bridge hanging off this root bus.
> +
> +                               The caller is repsonsible for ensuring that
> +                               RootBusNumber <= MaxSubBusNumber. If
> +                               RootBusNumber equals MaxSubBusNumber, then the
> +                               root bus has no room for subordinate buses.
> +
> +  @param[in]  Io               IO aperture.
> +
> +  @param[in]  Mem              MMIO aperture.
> +
> +  @param[in]  MemAbove4G       MMIO aperture above 4G.
> +
> +  @param[in]  PMem             Prefetchable MMIO aperture.
> +
> +  @param[in]  PMemAbove4G      Prefetchable MMIO aperture above 4G.
> +
> +  @param[out] RootBus          The PCI_ROOT_BRIDGE structure (allocated by
> the
> +                               caller) that should be filled in by this
> +                               function.
> +
> +  @retval EFI_SUCCESS           Initialization successful. A device path
> +                                consisting of an ACPI device path node, with
> +                                UID = RootBusNumber, has been allocated and
> +                                linked into RootBus.
> +
> +  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +**/
> +EFI_STATUS
> +InitRootBridge (
> +  IN  UINT64                   Supports,
> +  IN  UINT64                   Attributes,
> +  IN  UINT64                   AllocAttributes,
> +  IN  UINT8                    RootBusNumber,
> +  IN  UINT8                    MaxSubBusNumber,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *Io,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *Mem,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *PMem,
> +  IN  PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
> +  OUT PCI_ROOT_BRIDGE          *RootBus
> +  );
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridgeLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 0000000000..8c6de3dca6
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/PciH
> ostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,50 @@
> +## @file
> +#  OVMF's instance of the PCI Host Bridge Library.
> +#
> +#  Copyright (C) 2016, Red Hat, Inc.
> +# Copyright (c) 2016 - 2018 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PciHostBridgeLib
> +  FILE_GUID                      = 2F04EC41-C3A0-43EB-AC6A-409F973F4439
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib
> +
> +#
> +# The following information is for reference only and not required by the build
> +# tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +  PciHostBridge.h
> +
> +[Packages]
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  PciLib
> +
> +[Pcd]
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciIoBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciIoSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio32Base
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio32Size
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio64Base
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio64Size
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/BdsPlatform.h
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/BdsPlatform.h
> new file mode 100644
> index 0000000000..1fb031b752
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/BdsPlatform.h
> @@ -0,0 +1,156 @@
> +/** @file
> +  Platform BDS customizations include file.
> +
> +  Copyright (c) 2006 - 2017 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 <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
> +  );
> +
> +#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/PlatformBootManagerLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/PlatformBootManagerLib.inf
> new file mode 100644
> index 0000000000..55da35e87d
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Library/Platf
> ormBootManagerLib/PlatformBootManagerLib.inf
> @@ -0,0 +1,69 @@
> +## @file
> +#  Platform BDS customizations library.
> +#
> +# Copyright (c) 2007 - 2018 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PlatformBootManagerLib
> +  FILE_GUID                      = 8AE4756F-0C71-4C06-84D4-4C71F204D514
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  BdsPlatform.c
> +  PlatformData.c
> +  BdsPlatform.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  BaseMemoryLib
> +  DebugLib
> +  PcdLib
> +  UefiBootManagerLib
> +  BootLogoLib
> +  DevicePathLib
> +  PciLib
> +  NvVarsFileLib
> +  LoadLinuxLib
> +  UefiLib
> +
> +[Pcd]
> +  gSimicsX58PkgTokenSpaceGuid.PcdEmuVariableEvent
> +  gSimicsX58PkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> +  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
> +  gSimicsX58PkgTokenSpaceGuid.PcdShellFile
> +
> +[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
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.b
> mp
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.b
> mp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..86d7030833a096f54539
> 3735d931d9f4f2fbf8c0
> GIT binary patch
> literal 141078
> zcmeHwJ9Hz-kzh at gFoN)Qu|weq&F~F*XbyPdaEHTfE*dKcjU5ohf-
> &!%BU8pXGG)q?
> zD^tc9GS`(UQ>MIoGG)r#cb?2OW$Gd_vnu0Pg~E?y>sT{Q)F&%4G9u%Xk&#)e
> |2h0&
> zn&2`0PLf>1 at BjWNN&Xl7`zYzU`~UYcP5w_masS+n@=v#$bm8A8pL~*ZKm9c
> M6#l(=
> z^C_Iaf!{aDCtrS<d<p+Pc?<u(e4D(*e{bKy^(^^xHcMvkZ-xI>tK`$wx5>BPew+N{
> zCqGF({r0EHo1gqN`6>SUDV+cGXUUiF?`J>zS at QFr|2+Bf=f6mP at rz$1Z-
> 4R2<d?tv
> zW%A`Oeg)^hN`Cb#`2FRtlefS6b at J<9|2p~dSHDSq^PAr!Z-
> 4zC$qfGe$A7@@Z+ at Hn
> z_P4)H-u~uyaQ?gGcfW(*-~K-N{qKLDtbX^0<PU%NLo)l_AL0Cu$shj+zrX)e@~1!j
> zDf#vfe at _1V=RYT_KmKR(E&Th>|AgN^{U!O!U;dK(*MI$2^6j7hn*8;ze@*`Ox4
> )It
> zdHsE*z$*n_Dey{xR|>pR;FSWe6nLe;D+OLD at JfMK3cOO_l>)C6c%=ZLK$`j}9J%
> #+
> z`g{~f- at JKc$n%k3)||b2c=-
> M+LnK+A>$>;;@$vEfKfY?L=VAb__wxr}$K&JI&mkaS
> zw~kS*1G~9 at 9j0;vimRVfxy_Y(?c(tf7y|!~-77nSYEzvqlcpIQf^ZIl at W;O*3M7fT
> z!9kZ0_+7Z-
> @1+ at 3FK$(@q_Qx*CNCLHfLrh%DN_M$JaLeE at 0@S|JKldEOG8tTLJSzc
> zYJ|Dn!`@e*DIXr+U-e-
> ^H5^DwWD+9bE5=`ek8z`XKS_FDqrkua>L0^f)%(?nEBo=A
> z_fYpY?}i^&&`AMu>PnMqa+)M3U!$^re1FlY5cqf;0Cy_D)w70^J`w{D#QyQ|9Rf
> @{
> z8kVb`(W3$AHjlEeUB&Ltb>`mu&NuNEoIQM&cK+Snc~b#~A`kH2n~2dD(13?{J;
> ulG
> z|Id&fV>kskN%9G{)3wsUdQ;W(-n%jm at Z%%a^j$>b;a#Vy<Dc-
> |$FJd0z%bzRz4!P4
> z{sCjp0*YfS>J9)L?rr`_zY37>O at Q{_-78}U2meqcS?f20ZdoD)$&5I7LUsP#5!2mA
> zEIv!W^NqXXbtyvT1i?FFELrj6Q at p|h8in*2V;#tu|Ax1|Dk=1pD}m+Uwxe4Bj5U
> 1+
> zJNV<fsLOyKaN}*L9!@<z9mh8h<ni$wkx9P7lK%h4Z%*B<7Jsrp4EO5e<5xcS!oh
> MF
> zJ_0O6y=;Bij258V7V**nn0p+qQDwP~>Dq?`cmO&E`M9W{0!H{GGAQ{1E-
> QX`E<5s}
> zixRkn at -
> arZCEI?0 at 4(@!dEW!@f%90CZ#9t*CtDBKkZs|re|+@#d>x=TP>&8u37Fif
> zP;WRXRfWgu at yZqbfd>-qeS<tg%t&h+Aa47}cR8#P>jS!=`3l7Lc);J!$~z?;OIihj
> zxJtjk;$;D^S?~^kMG7IeoW6RCcaSk~q(8<IzH0o9OmK=1x&^#M_~DWL3Z%@l
> %Bx4@
> zQb6AQ0u=1$cz8ZPP&8e|HGe+wWG;a{KAZ!dmCOWS0ZA+r)prfR?Qf3}ZHIRt
> %l`lv
> zzO}JApCzUJ at O1P=5WkZCa0l!MTn7vs`QQIzf_!;+1fA~c0XAemf*X$MP!igY&BD
> W#
> zd-rkbYJv*{4EhQVuCL$*Dm%m{luAOUt{}bp7>!hUi69=~R-
> 0q&3OmUD4Bta0ky`-E
> zBMCQ&c4z~>MVXJ at dBmalpL?R*f<qBnTQ#X(J_tX?h<1tLTfD%Bj#$v8##j&Vq
> k}Yl
> z at AY!xHNnH at N%pU<a<nu~HUmE#yNG;vNkH|7S}oL&{>V4s^ECYzID`MbpMs
> Hs!vn@!
> z&V+3w2Pj#D`tZXJ_M-sGAqlrXPlBcONaEABVz;s4SiqS=@9#jn at OTgGC#?-
> dgT$2G
> z--
> !^SMEK$C2MRMB*}oyW&Rm32W4K0r<wWA0cjG*hKmZaaM^HJ~Vp3Cse}#_#
> BI4uv
> z?}PKYf)sz2zQKnMuroQOk$1S&{|Qw)?8fju9MHeU6|8 at 9k`j?5-
> ef({?Vfmz{NTul
> z6~lkvK)7~A<pUsHuchXjkS)~s1>zt017ZiRi1VxPE at +rB{(^ty{I0;Y<X_;P2a4d3
> zzTPsx848;6ue=%x{w`7+O9gX_Fu at +d-G_0CQt1Jgj02h4c>L1?!h9HEL8Lugef_t;
> zp{PGRq8g8|BDz at ifQQ!rNT?+7E-FwFyj#SjQa(^$Ab&|ne*?-
> yfnolYlQqW=01AB<
> z`2nRtKFVKgL(mTh)C&}X`>xkSc+-
> }ThiiC5 at cGo?>P&AiC2xWXLl_@<ZAS2fn>B~y
> zEP9hpAtG3)%foU#Ho^kTkU&H`)PUUf_74!O_alHGC?AjDQv~}Fsb9)RL?Ea%Qe
> =$y
> zhXSsny77dg7WC*bJj9k_&vlFfOrd>PIjS`$P>+v5YSQ(Be8ll!kPo0&7$ISGu3jg5
> zXsxgbZ_sH7fPv9?AP+Yl!AUOpf$xFw@~#>p8DWL)(2C0&tEB~kMLm!50Ugba{s
> 5Us
> z{jxvCJA`Zj-WP~}DDcsbfH{urt^(i(j^2?UIN(APg at +Rg<Px4DH&KuPFrJR#rf;?B
> zU-?Il{bQ^byA-
> _PT`lAX@&y408LS4N0a^3MwID!3+5?Pt9q;bCP7`5;K~m|xn9z2*
> z>AQp%c031C0MSbO0qqHgqY^dWo@^!kv6Qptfgi3X1$_k|p?4zHpiv*AdsRkD
> KJvp4
> zCm;S4$mS{S0Q*XVe}%Ys?dtt2B$q2SM)p<m;qHcx>;OAaaYNG3l=>gnf&eMdp2
> >%o
> z=g?`O9Y^r5u=@fRaNGm>3J*Lli5*cdsZ`zZu8ix(;hvL#HxLPh>lAxe&{qJ{*>j-T
> zxp#cZ&g$A6<iop~AV{7GB|qS0Cm%j|=!XJm&x4gg_WNFq-
> 6+ThAcfEZU}xf;_f_Fu
> zcj6*&ffzxTI(}$a&VJDDSqF04`;~k^V}kt%@&V){;uxqD?;wMq2+^Qppxxuh6E6K
> R
> zJo^TR`e2}fJ;%pzH=2)NKVbCl)CxWd_5;oku&)D1;=FPgmV0jy`9Z251JJTdy~Wyq
> zmtH6;zz^;0#~4uv^5JwTigFn02i=EN5hSti9rSSO-H;DQIAW}^{cyxP!JbD3d3}ZN
> zfu3>%iSkkUSMU%B1_L+W2G?fj#&8u}NoPMCO%bpc0?=+K7Y}~e4JT-
> u0UxXixi*Gh
> zIGlXAVJO)1f5UnLVAmAXaT^aO;V4#6*vZF3u;&2GBU!=<_5-pV%C>9--
> mZXie*!<6
> z><6ePY at xE}kwK;20D^trTk6uDd-;H-I6}j3nY4jg4Jiqz_FYR+BAt^PLs>wQ%xgJd
> zuaCaq3 at Yg#m6nMlC-
> M;iZzf34d`@{+@&UT97RiyDq}mL)eTmB7g~n9&qa1%k>X+ at 0
> zcN~L|v{hZf8oJ;_91jwI*R>1&c*9b?=T1I#{CK$doA3Fa^Iix*K76-7`y2AZhl_)F
> zV)bLZ7vzHj#VZ61{a}RWn-
> 1Rs at HzmhX9EppR<NKCVs~(WK^wdqVOaV=2iI4w0|Ppt
> zIwy`^BB_8n5%nFE+Vim|sk0j(?EnkM=Z?wf at 8XTm(ykMU(x6w32r*QA!#fI&(Y
> }s%
> z8JG`j{I%nUleUr|jvrWW&@vUk at +4?~he~;`_IK<^?429bS8y4eJNHTn%Lg#9*7
> CTH
> zvy!#I+dZi4ITWwt!;Q9}E-#LbA)Yjk7k)|_=v=X^s>ew?VhMH}q}|yOjAp>C;O~NF
> z#yA9O<?1bWQch96hj1!!U7!wN;=4}JIqyD>^5IJP;pZ5tf&&e%Iy_*QiUz=&53jF
> 0
> zKcc=W-=nYsIgn-8;)nM=tM>BEEq+lx0HzyEMf>5ZgNm>&-
> %{+g{t9lO2Z{q^IHbM`
> z*G at jd_yb-H_8bRQuKSk*!hmQg9d48mnp*l-
> *hR;_(GTAb;}3X^lo~rkeG_=gQvmFd
> zRszWjhAU^!12IrO0P{*dI4txuT(wvTk9HN9wX&Oa@)6pBRUs9z{jO#B2apT|0W
> }|?
> zx!x77g?xYoeuJO at k^{u}k%mMkCs-KkcTFw*D-
> <T2)WzyQ13`fw?_VJ%&Lj7|+IvM2
> z8$1hu(W3DOHCG4;tHHjGEr9ci9~@Rts;<04<eNba%q?$69fkVJH8<D~#0F79&
> 0O_I
> zk1z(LgTN4fcZ_8NKb(9-`vJYjJq1WXJ|dcFIfWix4m}?oH-Gx>AH4AdLyq#{`yxJq
> z3oJFpli(sous~4&?4EeHm_DjGuOLB#-H@`94++clDgch~-
> QR~%4a_ZXoBkCN&DZ3r
> zLx0rWDes|tkT7hh()H88A0i*fC8w_dRwW<NBk4eD2*QPbo|mDisQBFJ<GTTtz
> +&%C
> zTsa&|c>Ceh<rrRt|D9JvT91IkL4=qT(5IEYf=6Co1^EcD5MYHQ!UiP2hn@=@IBR
> %-
> zqp}|WtFj-y6GJ`zKja7YM?Bmeln-
> ~qyQKjQ=Picuh?5VeC7b|K`+<O>zAE9u%|Nwq
> zC-
> 4Jme0K&9zj*_#et6 at sD97h`1Bft&$8hRQV5CTJh>=)ChU0VV%=M_?sZo7pB8il!
> zkfcqrAh*6}+mGPgx`sl}189H}BH)j}54=Q-!r at vIu8DjAsi=Ioj$OGsp%+4tO2xaH
> zJa;@A at 7_U0@B0`S{^0}GNyq2N54<P+-
> O at J=MybTH`PcQRAZcOR1MP=bT~Gx>5=r5@
> zkjrj)I8fd-%17C`VCV#OVn=gIzUr~qh_csK4RSY_d;ndlYaC7aVc!^Gdi&u#13!OW
> z>MQpSV(@jC!L0-jJGHO$Jr0n+c2gVgoL7OqjDO^YKdv80eFcF15dl}I*Pe{sD?k7!
> z5mH}}AO1Exi?Bk6b&}`ncg|!j<kk<Ue0bheN}kTnmhurr9|(d?*7D&5#s at 4=uv}x
> H
> z6kzQ<12?5q%15B;<2Rp2goEuu#RszFDuKTj<+Lo4#qq;+9<1JRT*wE$iSJUtWfh-
> 5
> zYAM*GfBm$)QT>Abz&1HcgflqsAMgWu5ZvXkLWgzQ+0_rCbC5_DlMk%bIV!X|
> kFBR1
> zizm7UGkyU6V~nr?kub~3X?K_*a#G{4K2QCisvHlxU<y$KSeL7*Qq4#o_y?`^u`9
> gt
> z at pgFNCD>bGZqHp3qyX$2@~O)q!gn7Ovs_On_5%t5KYXrA)Kw*tfR=0h7;!`leF
> gjd
> z4HR)*!k?qKx;|PdpMU`Nmq`9nK4SH*HHaGG<}M)F)eo&fP{!^FfI#fO3U8GJ at R
> yE}
> zUJ`v%LnnY2z<Wud!}_DLA6|mT?yegpIXKuI+&!Qy1?<kDTYNMA2RQxi7(~crlK3
> +C
> zx3V8_j+PB71bzT4#G1kKt at qI)Yy=cIkbFR$0PF&pTggh$&V>5<j-wS*X-
> ?W5y?t*+
> z^5G at uhAy<#pTa%35!!~+t5C{iV1mYWhxhGD`EcN%2$~F^=K(K7`{Cr(QSkxhx?
> BhK
> zP<#d{2aFVlA<0*jrTY9EAUEDEk1=8w^c8p{NE+aW8;x2>9z#AVn*ohM`2ZaJpb
> bx>
> zG*rE|M7_Kb{9C;3I=gES_)5-
> k0$}byaR^Uc4Q02CNerd at 0I7Y~b9FnOBLvs^$Bub$
> z75GtN2>0>8QLFd09>41N&W(cPMa8}2T1dwt;EN-
> y>hPM+OPY`GqI~=aiQ=5P2+JWE
> z2sFmp52df1Jr61~%15vt1a~D4;RazD_EY~K`mVuIz_vJ7wtNbx|ELV^1)YHTxPg*
> j
> zsy!2&D!@~uh4<7#HX8a`rGMqPR#6e5xEH<--
> mY6}Hg>%NeE`ho0)ZI2=pyjqGw39h
> zn~hBQ!dK at w>v4lgFvl2l*)@{h-^Kc&-
> G{LsOg at mB&YlAy at H~1`Wv`9m;EDu^#kN!u
> zfb_#~5i}0L0Xv*_!b?0J-bKF#@)@v%Zz?`RQio6-
> _JvRfYVq>Qm5&$L9mc*MFCPxz
> zS1yiN(y#>V6f)of{DAElzd<7gfqW_;6=$IWudgt4>gB_Cni5t((h&&ihvPu at Japq=
> z&mCm1ukbWdpK5hL77pyY(0C$3{(k)XJ($dffm~Qa5%0${udguri&VnWpkW+fU
> ^Ltd
> zr!GDWmwr~N8V^EoS89we2CYAKr(bpaoSvg~1sDOKrW`-
> K?*e3}G{0t%czhdxxdkLn
> z;X?2E*tzb=TLVe&?_&Md92>l_^-;+Oyb0$38r3JDi}FE~k-
> J01A>1G$v~}HRWUwuj
> zd^mL;>PEofG}s1^I4{6hK6rpw%2Uy6eV>2zwHuBKz$sSeE!q2C$%h}XeqDA>Y)
> NPz
> z*bgDZ6iG)QtRKjBD1C(#@x~DCxj!%M2lfen0D8!+$f0n9h)`Ly{jblz^77$5BIt#o
> zZUpS=fNDdy%g;t3nX5-
> w%2Uxd!9y9la7_ at a3NS)OsT*S>AAjW3rn4dy!oEY|>IkRG
> zuo&<jWi7}@1&b2M^#PcXs=(}X0tf|}K<@(&CLhofJx at Y+!5LhiVFef=_acLKz`~D
> #
> z(T6EBrvRL*$#XuOmcxYdGVr66U`Iv&LZID+2^b-
> Jeth$<Ujy!V4n9KZd*c<hC at kJ_
> zaRg*3z{J}%NJ9Vdfr>KZumc(BD?Z-tJC{q9a<Wpg->t1h7Wl3TjjrxM;}CgF>)ict
> z76H4z?}d)NW!+_^q!MpHoIH_IL2Q6>kf(*DgVtDpOMZL-
> _5&9^;iw3BN%#?h_>S~r
> z2MJvo3szZumimR!dJ1|+q5wj0c;&0)!=nV_xt`b8uA^XaXfa7>-mz+U?F)qU`1r$*
> zLq-
> o0CrAMbUMUbI$$|k9<Bzh`=V|ss*BEf`#s=Whet3TuEQsR=b$Ek+@%YupKCa-S
> z&K9gtXGtKab}vI3DHw#^Ig9Zes-
> p+UqPT+#Ze0l!`rVJ9Aga2ML<Dd+#k=mPB!QI*
> zNz{(BjzCb}O(c41Ip7{d at UM^)Fcd)z^VV^tYCz~8;YIktG7U%~*Re4CZ8sxa)l_#<
> z8bf>@&p{lqqVhk)-%a3`Hy~Rt6xoj-*darET&u!J5351Izz;k{r^p at OaY+?UUxi1m
> z`p}O`P&kOO0GHZn3=RTjZ^OF)1*@zMH{>i4!e4}M!3x!55npYEV+Cus6Q{32Kq;
> O>
> zb at YH<;se;#O}C&BuN*;ks~X>ORXUd7AE!G)-
> 3U0GMpfWOG;Dm1K>SdFLoom&yayO{
> zj9n|<V~Bsu$L9$w*z(+PML;~9WE!v{fw03oKK{52IUqj!94He2&}ry+4%Ol9@;@
> gZ
> z)fL`7kbF3|3flu9;c(0ibq9VxWkeNteS&?Fl=2!SLh)VIhbk#xcnc^?I}luoevKY@
> zfCN9KZPBm at fe`T+quhrV_^#*u<B*@DVju_F4}ND at -
> k{Cf1(%Qh8R|g}!~Y&usLAoe
> zRf;-19NvI9et3LB_1{DN6QBeNYrqKOpC2D0?I4AxjBJ(_B=I#EqLelv-V{h8jUL{O
> zOZ!$q`H)Y(`vns7 at yGkM>XWyQK@^G!7$nTke{{y6lNCFFkl*`fr>tq54T5S1LGnX
> p
> z)3I>>)M+HAlfq^($ExWSZaWHiQL^UG+r9r<>Xibo6nLe;D+OLD at JfMK3cOO_l>
> )C6
> zc%{HA1zsueN`Y4jyi(wm0<RR<mI7I)+w1jD`u*-
> +87A9S`&wR7Ano=C!?V%l_3iEb
> z{r%+rW;FOa;0S&Q;lpc2);k$qT;EL>t9)G@`ShHvqL2)H`PbdS`Diq{I6oVn4o>>r
> zxL^EBMm_EHPe-
> @YWl=GrI>|@X8kd*cf*Rb?!Obi$)<sd|tHpeBcRe~Aym+Q``opV<
> z#S6!j;_Snd^^!a3`J(Dr;iOnhZ!S(>u4T-+gUcz=P!j+3dj7#q>8Hb*hUL?nGZ2%K
> zZ7=6H>z?1&;2aq<{7?m?tE3|~s#xBh^<J1YN&A-#7+1I-
> Zbz=C?TFb$)dc%wc{6xP
> z9O>UIZ9K)@`wvuMbtj at B#^sEBl<H}Fi>$3JH`eP9l^?w}!e1;d53|}v(s#S--u1$8
> zZjBBEw{AYrAxLj!w at 2J97FYf4h<EVPozZNg6^~fEJy;Ho!|?&Ok`HWVKEHZa85v
> Gi
> zt%YN~UOX$Vd$6sI{Rq8oH61;hk?dW~x8TNl?e^Q)gDlVX>PG)6s(|%+dH+0aeR
> ?+8
> zLRGET#fNG=pd0k(l;RuCi~034n33M)HaNoI{OZ}{cz?M{&)Qk^z^VNH?1_i$>EN~
> v
> zh8TQX%xAON{q^vPG2EXC6hb=MPBkyC4z>3&#iI7Sb2i;%Ir8Ofa(8n%g7`E9sQ
> Vu@
> zH-HZ5 at NTxs^Ss#9?jRz?-
> RaXcxqH#9tBNHE#7mBS)^@ap2i at W5>iXv9_I@&*v8kOJ
> zb259X37 at oo)ugNP<@EMq at PUr}8u;NK!FB>L^?81IGnp-
> 6KBVbbUiP0Newv=#*85e(
> zYJPX|Bxr1;+>r}(PR?&&3bctK#qG)Qbyhm453Uuf+11HY^ob+Wx-Iz5>D81 at N-
> O3}
> zj&4NK;Y`&UZWQ_S#l$$<QgrWf+3<GJptt77o)bN*4Rz+TW7oYm at s0za*W?Q?
> jvJIX
> ztDWeWyA9Kh)8dy7H9N2OH&>TO#QwaF9m~tVSBI({H5)jxx;~mktz$=i_XLhaJH
> k9y
> zskD1p*H at 3mkUC{Gzlb06eJ*-Df4$kDZXB?>IfjI!L%RdycZ1`5+0Rez78rETXZ8s3
> z7!r~WY|jd2jgP_o7R`ToMY6$-
> JwRMt9hyezi9PPvkd~Xdyz29d3zzr$;u9=Q7DGPr
> z>F_+X0g^<UNDIENIXqj9n%*+2ZM>QG at 2z@@`}zTB+QTr<-
> DEnSFP6(C#@!*${qp>@
> z_u;5FNPxY#gb3nnzVL0BO?~QaEmN|ydsAmE&kx$_-
> i=jDep?qE>71NhL58~?xk4EJ
> z{_1 at 20XP6@_w?fWex}ori+nM?y*#UNDIxLN)LDx|PEmC(tq|hs+D=f&`e#>@h
> Ag0B
> zIlVqVdD#P&&fwy9Y7*A#iDGeoHMD1SdRM07GlMUv9_Yv}tQwYArU-
> TiqkF43*LSPQ
> z<!P<Z9|-
> N8!KA(6b&EWv#ofh;CFq at z>H6H)DU)sSOox_{T3%ZG?hdYMoIcJExLRDl
> zOpc_zv)j!b$~7mSURtU*y)YSab0AOj#E7sL%aOs>&fwa_MDfDkSlygj{mTISbhm
> &T
> zn-le8dy4s`Wk}4hYjK#MQuiiSU!7U(NNY4_^^!hW-B_)8I_j&MI;VG*snnRqJ9BFU
> zc53y@<slL@(@VpwEiY9|((IzahDY?p*^3%arYE*@Bybj&#mw-
> X1{N`9Zi`k$x~*=U
> z8OCFEr9h;8L#qkI?aS%&<nyT(z~^pky>FvU?-
> qC3G?)@{zjvlwZ%Qln=eZ6cXQOS!
> zJc3<azl>D5{x*gqqVLXDS`}FgDQ--k)aV;Ex6&I;XCw2oZ;wg^(sh@`^gtg5uW3ZP
> z+h>-BsY6-aFK$(*vW)t2uW!>Ni6y~zau}GMZI`{L8na%E+R^NIrLt?oOlm~y?-Wxx
> z;4|Ic>FGXg=o{K<B0Doo#aPjlden_4%Y6lTpH{-Vy*+eQXil+^=^WWek7J6vJpvP{
> zF~u^I=C`+tPoh|o-%F|6lfv7)o(?wVzbb@{8%vop-
> Z6x3p9ytiMo<MRo6_S9oNI3t
> zlV{uFB(;3VT0|QjtZsz=)VtN1V<z=W>z>oqy{5Pl;x=d&bVyj7+~3|p-s|0DzCo=i
> z1>73Z{R%cDBRJY)O#03>;eI-
> AUJ$mrJ>j?**@MO1u0Gb4_N}BXZ)C at EayvSQ<n~^-
> z+l6hHPR~X+O>y7#^Nd8YrtI*10h!^$)05DK!Rh&BW84>}AQ(fe*xzbLAFHpe(Ol
> @1
> zLA{@gLG^(M;ifn*QoqB=diD&fL^}1!QxH_Y9QH+s4fX}OxTz1tL#_>DNH)@b+iW
> LO
> zncXSfw-U2lClgg9XxGL4s3tO%^)K#f-Q%a1ka}g6&u-52u-
> g&4Gq|jsQ^@bQ4e4Gh
> z8Wnmx&3I^Dq^AmwTtHqo3M>|P=W29BD(Rfv){VU;(upUp9pe;+PPTo9Re<$#
> (SS+s
> zqE629Ti*SRF~f?>P^*S at _0VI^E9%<Hs#r}fnz(_r!!)y2hK?`?o3&}x$aJV%>Cjl*
> z3eBv+bw at Q?E5BtvkCiAjVI?$deJ4Fv{U+xlkB;HX!8=8}HSsWsrsWS`7violJLDb1
> z{lRAE(^k3R{TsUtIiESru5?Q|DO)tDukw3}J2oMhT_Wb{$nQ6HtWbOZPFp$vS3K
> b^
> zKs{T+7i|NaAYR%9#WwKhVn++%wtImYOW>DG2^sQ(yjjU1Y7^^6=72=>t|kC`
> KFf??
> zDGIpzc5^$}HNlC3cglelkc;gGA$>K!m2<CoV0P}sc5-;Cgb;aZ%{{iG&X%RDnYMMY
> z-5f<`Cz&sqsZF)U+HUiZY=nei$CNd;XHs&?T|M at Od0{Jz`Cc(lvm)!JnE{(`t1i=l
> zNeXVUQ`NoKqisz3iSh!MEb3y;sju&tMzctu?sZL-G251}3T}%Vh64$*dAXe)!FueO
> zQ65;*8!#@m at OeARR_C|Wm}euc5Z7xxBh!W|*5c{iLp&{N3`J5aabdZoTKBN}c
> TAJ`
> zi=4$8Qtdfxk!_-rr{}E4+EbC+2w<dJ$6`o+9Sa=k%&JxeuUppLvludG0&t=<R(k=-
> zE at k)U3G>#tytvt3S^3s>tz^`F=QTGH(wItE at 5&CG&XN=ZKkbIv^z>SJ#;pb9MET
> 3i
> zP+Qr&`A*8pQ>|yjk=F}muQrl*+X9v?U&;BsEr41KSuy3;Q+b<hCqi_t2v4^%LOy
> wu
> zlbCgTCvep78*FCJPita%TM((fXwOJa$}e}7aIEJ<&lRmX!IgJiwDcYHT8{~pyq=Ex
> z7E`7x2_3p8XP4J^um{Uza({Pyc_t(9zNoGdY$A^W5t#d*n(pDw3fJRfjHL=T&hM
> #U
> zc+0dJmCeouXqn>k8s;rb8g&NeFabsMCaj!*FHeXG1$fo;;oEi}v+Bm1S^)t2XZvou
> zqPKVlgG9YjmEF+p69e5_>Af*!WDI|n<|YJgcMk~)V|CX<F--
> *wv2vAGMj9ri^RD0G
> z$V^+lU1Wjc5zaGX-3OzbwlVCn0n*)4=3zA=MU9w`Iizh$bzj^JrK(OZh!~YjoHtB{
> zz=ti)&QHzt7X(}DG&MBKIyYBOSg+UL>*^6r&P;?-
> JS(#!^BOX>H0_=m2gNNjLcVE3
> z_r<kbTa>D5fh)C>Apn26DvH(gs%93Fw~1Yy7=wj^4R=}bEiR1d(isi?^wc8E7G9}x
> zc5}Kmw4)tu!+3OthW}FbdjC5+6T`<$nL8+0vm%ac`efynH<GY>%@M(?Vk(engi!
> xb
> zn-HF`t1L*1P_i=DEFV#c+}c>m+pFC>f{=ncAJE30F}YLNAJw7pgDtl-%B;~RA4=EL
> zd()FlkEG_*)lq)r=9%=4k}0YJjhPiT3Uvru3V|@9I-LrS=G2(N<sM3)2lqI*m%oW*
> zx(ma~xh*C<n&B&ggEprDO0^20cA!w!Gn8=_7W`HMx1OtU^gxa7D-
> MX01)sG^jMSJl
> zQ@|d{bjX7f+k7^`vgO8VmXaD<|7t&xF<Z?KZ_FN5 at oze&$yBJnU at -
> wizkUNb!40 at v
> z3MbP at 7Y3UyiPE{^khU<!R%o1uu4QFgUS|R~uub=543etI;C-
> {@Qp;~vRR3M5NkN&f
> zn4Bq=apLi-CC?k^7&cumtWZi}V<#(#YNlYY;6qt*=U=TIn1Gzhi6v%VbggRkk*0fO
> zDkQcN9egY4K-MfcLzHs|MR;r(P}ZG%(Qb3P)QYjU3|eSX*>}=&Igl#uNlE41ZJ1e5
> zLmH}&^e*O9nPIJ`MpTVUguLR*7tBm^No^$`5bRJ&jnJSvwH6mGSV*HPy8DTq
> 3t7-H
> zh>8tN<<OW`-BaR3&9x%-
> QfxWUS0yC*)io?Lpa at t?Sfou?eGHWJq^VV*f>R?+b!j`)
> z6s0ZC)1g%A#VrA$I at 7XAw$<>03V=>2;d8`EM at g3=zrIo2vZ=?ev4o|Vup;R>_
> pcCU
> zaYL*oX+Ama8^$T8?IUIPIn}}A1wlW%5Xk40Te4mmN~bA_sfshwdH_<YM?;?cu
> n1%}
> zt6lve!e4!f1Hcd&nA(6q5gJ91&BANbmQ(9!y|l}{^i&E+ensF6qzanVi*{F)B at -V#
> zS<RZKMJD!!e#H_tSb|R+3}FW*V+0P=UhvGWQzO>GZMqo^mcBC~0iLGTxcoR
> PfI4bJ
> zi#Zt+D)DJhSju1%g_Nq4tQBDvwAfC`THc+Pp+nrL#pH-
> kM>=E)BNaA;HiI5BVazx~
> zRMW5{YzXLc2(7PDrPvFCeR|ejVaf3rO?&L9fdya1kf~mQie`GjnAS1Bs>-K>la3zd
> z!1r~S2c^3pRAy|FP|`5f=^fxmZ<Uf(f@<-bsR;5t5fGIbJ+B)QW=dT})t0Ip)D^K(
> zpbw1YBI}jT+CQ;AtRtd0U7d at uUh`p_8n*&Jiu&AP%i<g_aa+?WC%v*G1I%p5P
> 1$`S
> zhcd)Ks2*9|(N`0TK;}jmR`Nn2G8^?w8jzcR56nss$;I-m3PGi_0o?kC3#>C0!XwjN
> zs^``Y2~}`~#QS<O_?nAx12&N#xt(BiqNh;S`85$}AfwJ#1<-V8nk1${kl_N)k<4(A
> z*9#F{u9$a#6J;aTGoq8U*Hq)H%hB8-
> 0!hy}tzim>;jQ!G*ZEaVH7bS!pmRQRnVw2f
> z#WH;Q*7B~Wqz6U(tk2a6V6pH)&N8)<f;bzQR9HFF{1pNnNdvNn1)p+o1gzeJ6
> B%-a
> z0`*Z>^XqY9NnI+3O#o5Y^u${EuHu`3oa#%69p^u7%R$c7B2J?E(^G5=ISTIZmk1
> 1n
> zBeo{euhu>j*@5>@q&8cxx%`xMxL=*F4ajkTNouWz<0 at Z!d_ZTR_^>{+voM4X
> f6<eD
> zn=Xjz3Tm;4V}(m9d74M>Dmy3a#8W=XH(K1d-o&)86K+CM6-
> <U|d3eLJ>BjW2l5J47
> zysnA{hdWWh8KOxu8R=MB=%~r2N!0(UNlQ8{l4!!L$Oy=2r0IVWk;Yf7uPTcSGH
> dcx
> zrwC~7^K5+szx{8iusa=ED`U(CSE2H*5V3+pgp|L-I+)f!o95ii-T9 at vYQ<mpd`V_a
> zXz+kBG)|$nA+)kTGXO$Y&U;VE5Tqw9196AT+S8#>NkwFu^50h1<!kt>Qx-
> Qaa8eMl
> z at +Ehm%$+p(eqPq{D%i}BBBzI{hDzfv9OO#Iy6N~psUkXl54EfH%L}5eq=&|)SoC
> VC
> z7A;oQAw$GCy`v`c!C>?KLDX~tK*@<;=o-iK&_q1>AjCI-
> sF_wW)1uaQuHwj|1l18?
> zRciFrj>v4aqM}LBCgY=H#MKM2)r2)p&siS2nf$pVniiXv(o7<`zew5sL;tF&Ju0>;
> zxI~600TJnh<(CmdsmZyzQd5xa7B^XwiMa?t>FfZx<kH-ub-
> }z1*q$RA{#@s)#C9I^
> zOe!q8KCL6?E_mz#@K7- at qVLq|XV%`1^pj;Ys;-r%M(};f*C?ftkf_i6!9T6nQ3;ix
> z)P&*#hTJ;}<n!xj73=Ui(0w`ATF}%D846L0UDSRHWPH|>{xX}bR(-ggctEQq#z=0S
> z-;iWh>M2hNF$0uJWA;Zk_xE>KL#?O}M1BQE`J}|-
> O=JXH#oT2SxR}HWB*k+!S*@}P
> z`6xPqQD>RN3K=rt9k^%NbY8=WN^v#E>9A~0uLM#!9qxu&;!Ib2$o1$dgw+-
> 1oCbkq
> zD3u9-
> 3dFBQt=nX*n1Hw!cUP^&yg7@#r)o+X*ebSkX^qkW3(CO}U81VO<s>%cP>`eH
> zRZK%sNsdfkNa0zl at mNC>tyPdKD%bF?m2%6o7qW9{9)TfC5};_n;E0c8Dl|19Dj
> Gzy
> z))6N;{kM!UU==K3Tlz{PU`6!m8$GmgqIm2zRsI`Ldqs21z{<!0FBI80CauTnFi+GX
> zUfR)QxRlWp+$$L{BnCz%WwZ1ZHEqt)RW~<GXUs!fox7`gyb09i at yd>xv4$el;op
> qN
> z;Y+9xHAP6SJP=twGR8wkgHrBT{-
> ){#)M~Y8qiNH{2AoDhB8=r(Otd4X{(&EBdw#M7
> zQU at v`J#o5Hg$_{>SDuZKNS&15M4aSOOJ+V)a*h!ii=d1%Su-
> NXa`fRH#dIvhqau9~
> z4Rv4+ottZ*-
> *iiUcZ&warM+JB*quyAAba+z=|z@&Ao~EVvkBMuOsYeqB=zpFq%j at 5
> zUi0h)nbw40SePx=_*7?dR)I#$l|kntblG6i5}B~g*1V-M3bjKxLUtphB<T-GJ##*N
> z#k!Q4t-6h`cX%!-t48-ali?I<?7_Vf;!b94WH6DDO3KxmgKgEu8h4ewt3o!&G``Bf
> z*uNPDGto_C at Sf&Erd&{iE=MO!>!>MzvH)0iU*`SDhdB+>v~6_9bXWPXup?tOz
> z;Fg
> z(UU<TD3b5cKiZ<bxttseP|GXh at oWnv+5M<{C4sVlhICi;^3KgzgS|G0y%rvMSItN
> x
> zwc`{&)MF(Q$=G`vbPiTVuBD`LSUJZ{!@nv8gV<B0msvbRMwfO=;7_e}YH~lBfiZ
> OC
> zDY&WZI;hl`I3JAC?Ep!GPJ$kZoF5_ablpM83Q0BKqiF}J4CU>p9#U%uK)HLrlyFCF
> zmZEO${U;V+wIk$#N=aY7AcFywQ%W_xoZ=&E61sxq`G_Ffl}Ycrdi;7BBzA4)K*4
> $+
> zBTU6TsGiKw2PiqUq6GIRI8`ZB%)t^d9x|Vs&<!YDw~OH+DRXQkhK#JPSW at pcE
> zabu
> z7NQ~clj$1N7W=&q3 at fvuRM-
> Zm{maUz2z8?5WCK+#(zp;$QifOAeho6zw?_=m*r^7_
> z;M~cwQn3ZKr3pp0+WT|uPwmYRq>81!kQ_<Vw#p at MBw0xA06{?}a`ui-
> 6m7<rmgpM^
> zi84igXq4egWX*52vpz)YJodTt_-
> F)6@`}>#ObiD}?xyrvm^PL&$MZS2Y^{u2x~?q@
> zlC^}K at 9@)+gD?amqNiITwtI0I3!=%Ba_C0p{L>3WIv(`X64HpWbQ>8hp*CszR!C
> _>
> zgyej>M8}n3gK+B`bA^#`wmp8^zae8y#7|OdT*%N(4hLy;SBe00cf};{n)+<pW1q;
> ;
> z3=&%e#JX}K2Z|JYQx at X`LF<B|y#r=Dz9Jo7I+rcizmgsD<?IKUagwXfX^b+F8UJ+
> s
> z=PoTUZMsN>v9cFv|ABf3BA*}Gx at Oy{?}FSe at 5tDAaTTG+y~Oh9)5-
> }SG8~lqljSsV
> zT_z2SNtIZ4+cW8RBO&EFD`_KL8MdOuOb%8V9Bpyhr<_bZpt12xtlJ~g>oOysY`
> 81)
> zPS|2l6{Y9y=?*PX(_27omd*mPcbV>j4B-
> PGDeqWfEhZgzKyHUu<Xj#Vc4>TL+JH1W
> zWJXp7)XBsMC<c*Kzkicc8K88O<n!qr>uVPa7Fq0C^XV-%^W1^r&9BJJ7djx6)-
> pOn
> zGF(F3G8yS3UI6R`ClocyTWm(O?y2Rj7AzJG(Kc)A0dCV}v<}%?Ji~mt9KF#&hIGs$
> zdUDE%#6;!V4&o)lnq$Eam8Drn^@jU>Bla#o8ZPm5)aEM(Et at U_lnq!M>X95%(
> XBz`
> z06k6~NFgA at NI7a@!*eN(2hj*}428tz3H6ZtZKRX%&pRY)!5DxM0m?%Wy#bDl
> Hqq`Z
> zRdXCn%N#=zzLNZ4={$0y5thc;fMw$&bB{PWkb<{U8Bjo`@sGQii9}*B(}>4G9!k
> p6
> z8A2KPh`m{MH^N1k at Xx{}GL`x;fmAyL#UsaNM&g96YUxV<1z5(vS#uDIHv>_cC
> k`?a
> zN!mEkr}z;A5cMwsBFEuJ(v_ADdp`+rA_=VJRqNOyEYc=97|R{=kfT>(nG<R2<J_v
> 8
> zog-F93Ka`qDT{QV)fLkJMt;c8x0%@sm(1&xx)z}<c%IWSd4aH%=Sp06iC#1XiXU-
> Y
> zS8sHnHYp!;N at cH>TI2LWY*%G&PsylVGnk3%RQJNM)ywizcw{7@(l4SED1O9l*
> 2oVz
> zQfAa>g>OwE>l at YUl?Xve(Z%l1!@(UH48<a`*)^3P^0t(8nr$w9ujsnU<X$qalOn)
> O
> zwuqPP8%`vINaai?QgY6hbfm^sq+<1n at vSS^>Ld0xQscg-
> S+@`0EbFi=Zy36YKmp}P
> z{m`y~AI&C$Cq0rRx_w)h*xzU2dscO<9ey~q&B4qOV()3^0=|^Bn%@c;mYHQF5
> ~a3L
> zh+b_&+(XV0aTCEDvx29C?8%bU$TnOvZvw2P+J_Cp!K{l)qlt1R1~Ypi>Rvx7Cz5kI
> z4XzWZ+VNu>`QXA%=1*yI(IJ{B7sMka<@Z at kYL95`sT{L9hVV6`wES-
> 8{g{cwx60m4
> zKAQL;LR4HnAcR#$F4}yXYP-
> hDBnwB$xUA6uvurx`@y*?@z!DwEF%J!5tAW^7R9o?*
> z8uB*qL)mjKA4%G~m at HSz*(F!)+flxzw5%H$BEHXJd?5&ij&V2(kj(%k{pLVT?d
> @-i
> z^aHkzb~k%2<}t|Ls*V1xLpkg8dOhh^v~Ns9N#omkFjvlXjqHHPGclhoV at Oy;PC7
> PV
> zvH6kM`h_GvCr#sz2LGy5I*2M9gdb8N2#dNI*?mfM#gr!ECO;%S5c#ZFhEfC<^N
> 8-|
> zitL$sL7OEOlhdsfn#Skt`9TC;W^M5h5yk2l=T_HVaR(~3GZHB_nH77NAFrY>Y<Vv
> C
> zEuO^)KvVpxemuzBR_HyHAEIwPEkDfI`<x{&Bz8EM#8GQ(I#B{!(q9%o;hE6|<%h
> _K
> zqUKK~X2igOlpHeuQTb0O<Z#5Gm&EEQ*O?suAP%%qP^&e?3)u^?lj>nILXnDZc
> l-rE
> z)`TBY!0G&lbk-
> wjRg}K+yb}3RWa94lZ}X=4eU^y117+ECSYAaLVg)F35un@#Eml_U
> zZ842COPv(Q;AE(Py#tQeDmfob@{gMUGNg`m(c=3oFw@~%ME{EARWbyDMH
> hU<^sX&P
> z2ee)gylI5g)Sc_6mKwYO*|EsfdaU)RXQu|S`FE3(RHh9efyC#!?ZHg!$-B2f?l(>S
> zD>>&x^Gl at b8Y6Ei3K>ViGDO7kuXb<47H`&k4TnK6qar+eA(iP)$TKmRVK7@?$
> i>NY
> zF|3 at Cp!rvFXcvbPGVPaS1j_ux?e|}3-
> LATVnbo!Bx2vq>RdGTAL0b!S)klr%aA>+O
> zH}9rj;%LfGl%exDm9cC7ZWERVeAcyyExy}ley*FxS_fqe79}GbE4lB~4rphi5}N-d
> z+1)aKcTIQJlUV{WA5QMSPV(F3UgO99Fn~!9zJYFNy+|(V8oOhPDc&=q$N|0w*
> +f0D
> zaWNrmqE=VLe9`PuaQHfsMfS}Dbf^ft?U|T}^w^5oVHp&~LgI7XQbS-
> 7F_>wK5h*9N
> zJz3--
> H#5vf<UP5PCFWC$03~ch5&aG+RWXZ>fIjxA+Km<|DL<)VnHl1_1CH4ZA4ww=
> z8m!x`8Op>)Z%8^y#4slf>kZU`39`IPdI3)xFexb{dyJzb|K^%j0FK%$9Be7R;+9P)
> zmNmBjmATu?7^{&3J34)?*5i;=AUX9zjHMj4aHpj`)_ayz+e9F-
> <A~Nlx0Y9l&vncA
> z1wz^Pd-P;-5W&Hhsj9Zh(KJ<#awP{@uclUbk#*!vAgg+x;Kckkx=^0hIGu-
> s%>X5x
> z)ZV@&ayUpQALVe6c4oO>GTl%{j>3uBm2G7EGi;Cj?r-
> #s{bWQ4%BD682WQrNI$PAT
> zEryv`oV+IAv5}S0>}MI?rJ*gkDF)GVQsw5+T5XH at p5^6g6Q>*a`t(d%J1j$$1Plw
> M
> z!w4k`qMx@$Qts?c=Fio4C8&=sXO^h)l at U_1fKU!V<X42Z#((D*GRs}%-
> )BiWMvh!T
> zwFJzkiz#hn**-R1c35JL<R)qb{RE(#Nr>Sq>@<i~JjjHn=CR0V*qOdtzu38nX*DIT
> z;`=O+y`WuM{<-edvgtY53295b<fm~-
> c9)FPvaJqfE^AyK1&+BG^0N?(AOi1gTOz+-
> zaeFU!-
> ao92M4r811}Il at 1NF9;rt&j^#286mh?s#Sk;_x!@EoT6&&&Q6e#r(V(nsLx
> zxGma;DR*ilEiPl+2P-jcI(I_M0OgD)2e-yo#x~Z(7Rj*!Rj!$s$>n=n$nTTR<B9_*
> z-gJ!F8tX$9lr6;W!@s%K?sMH*sloS!V^CrXbmb77s+LQ!O%F5KVk<YYJp<G(l_1IK
> zQWfs5YPV=+O;OXPlj(kZt;O;x8RBqSK at 4VUFp#%pE(kH_$`zvSm0Y{O<bediEn<
> {p
> zOiV6Rk_aC6+Wf*DSs#J5%O2#Y9cO#6i0pq at B<J5s!eX0`RDL^}*a*4JIotb1dhd
> KM
> z1-YRCU0^JiVmzZk2l|{yJBXCzd$}jp2c6fP+QXGrS-X5EQhKH|S4x_5_R&(gaTFaY
> z>I@~S1tllxnybwn=-
> ?$}a+2%X{0n!fjK{e$d^v>F?O24`+m?7s>$<*+(MdTtWuB1q
> z%j4`I)-
> 2~7*Ru##R+(S6#PvwUWdHEQW|f)YU>YET(tIru0)bD4#84oESAQW>AIa88
> zYDp0_=c&xnkh3{Le3#L|l7sj4z5(j`*0p+~0!B#56(5D9<`yT6+A`jaP}aPcZbnD$
> zj6}Cz7HQTTxZJ8rd~YI=A2=ubDrHxKS5KW2C&{98Hd2y*pCvJuS8)$Y23QfwYD?
> !)
> z1_i-uuCSHQ*eAy1{wi|ou&$6FI at 2p<a=-
> X=h41bsG7f>16yImr^>f|CJ!*lU%2z1J
> zOt&;2WS&Yd73c017<3`vG>J(136xhYkUl~Yt80sIqpQuJkY{{8-5ktpWz%K)I*d)L
> z)~ZjVFtsALcBYA02tq04c{J$CpXYl`RTv!QBpaNM&Ie+BSvnL!HAie7f=aFVbWUya
> z1Jcy$ZfcRLf~YIGU*(!<OPPBl(?nzv>UtH&i)#Bj5;EI_ at t)5+XLs|(ayh>jskSlz
> ziu{1 at v#^MVNp1PLZebb$3jf$-BmV09(=>1?-
> N1r2K`mAl>!e{&D|%c`rq$%`M#QOW
> z#CPw9z3Vb%YQcIJ>Q_xk`Gvclu|8d_N4AoK+uL+$A*gqy(yQqFcp~G4dbdsK{?
> QSk
> zoX&l!?S<*=QXyQ?p0RU&E|?}qPAEi6rWvwxu~ZL>5F^moqvT8!+w-
> O)H4<C at BVE=x
> zch{j>xmE0X9)(|f*-
> @D_V!Yo&z8_4^KJ@{cX&UqCOTMHdHL1;}c+JmsivVR^E7W`?
> zUGuFLIIw8}*_p)0fS^X1rM=FhC!Jmh<?u8LORORgQA4$#7k2GAXIdsFMX?NDG
> SQXu
> zbWoxoX1R_TxW5)cqX&)b$#nXHdK(?Fs(;PnJ+98apgGOdm7|w}<WSTjyyp}7!2
> `Kn
> zjro0+DW6vAT2s87+SXvE%}03kYHYfDgxtD&O=grpwgs)%9BW6oOlne+G^#vaG
> C#5>
> z)oWkZi=C;1g0FRq5R~}l8f*wAn=U=5R1UAO#}^`;WMC=%CoXu(A*XX6Y8WY^J
> +3yn
> zQ~P=qM<B|*Bnb}&s)x8`d at zR_2dJbk)i6*p7k1yW>HKruH5*<>^JzAxC++o`?e
> D8*
> z1*p1G-;T1>jY{IBLNpNGFpdA3=<a({&GP`Mb)P*|L_r6NQL@$Ny2ZRIN(h+-
> x7w0v
> z*`%W~HNGJ6S(w3;_0c?_sy1CJ3W)rw7i`v6y?2b0RIaf{645ReDkb|1VF`B#cQu
> pq
> zX;_GnC+Wz^2rMGCBWtF$UmA6w<hrOeQ&&TTPY!7rLsim&oW&@G3a8Nc7
> Q^%~7b+YL
> z*z-
> @G`+C&Z5wVrzW3O1MML3vk&=UwHrb~FcWRee}N22+uw8gA1soZd48E7>!ld
> >Q+
> zsP9>?qB~4s9Ohh!BhrWs<jQ(v925%{BKEGwZBU3$@yh4~f+4$9l(mK5^i(?uRG
> aGM
> zD$Cfl!4DC8UeE=(v?e)-Uy~Fq^{rwWS*Ab^aV}SYA$8V7T4^0B#0o{p3O-
> k~#quhn
> z!>{RZf>vopGwJ at osY*$uo6D<EVKJi6<9W6eY$qcyHC$XXmPa55I5YQuS=DW@
> Wx1<7
> zd8X!b-
> OL=N#(a9gqrqj%%oKUHS)o!UYZ}kUu3Z0$e{}FFR3&}&oCHj at MmNTkCCYpK
> z+WR9h>QVTX16AD662@!-5`%|>4Tou6%y?3Y18VKy0qTz^Bo%t%-
> l+PhDTz#RwB>RI
> zs<3n=2j29qLPf_Rz$BQ)!@tte4iw#D#}%^7j0gu?8(y!Mw_ at a+of$!6?rWrS?i)sz
> z#06Kzg)C60Xy8wJ!qBXV!b)U3WrIg3K)1iNGSmzDogW3t_&&=ry6V2TwHts42g
> ?N+
> zPNC$}t3ia-J-
> aO at 0HV5qGxk+2mC?Ii(&(+4O{yO{q)K6toF$b2e4MW=c4eX%G`C<=
> zor)i7mvk6kL>h+TC(@e-xGOf|x56)2Xm)dP+J`*}PtGpy=5izl1pq&4u66Ds*Pe3S
> z;9AGps}`yVGTly8&Pufj@>G!9o at 65_qtITme9nZE%2bZ^T$i)DKMx068#p*}FK3
> hc
> zyZh-
> }1}X3%90mI>km~>ZV`J%1u#`?TNvu_(C0W>+WU7bJrxMg|*Xfx^B*yk`{vNOl
> zLGd2xQ8B~8lejh+rW~x%J|eK;-
> ~oJ at C=Jq0tcM<*Hmw)X3X4wOXuHYeeK!v9x8#Ct
> zq{NB}DKB1KiE%nhttkt2WKIXb=HcMXnl9PEjCH~DXLU4yrR}QEr1C&~iEH_*5+>;
> K
> z|E`Jxh#l at rC_Ddlb(9YFzi$%>$Y?+{zok90!lpkFssc#OZMyBtHgjY#sw#jJ{bdFo
> zEl_dN!p1eg>`QgApm9UFcLt<DQqO_nwbMDBFE5EuOycH&O+b5**g2nYif at _
> WU=oCY
> ztPVM?SE5n-
> %je^bwGL!$EMTHmlQyX<V6TdF(x|1}83J_40k^RQ{Vk_4feJI)AtGt@
> zS?_M)x_`d7C2==i&N2{udDXTI5$woRV0X>G`k<!OX`F>4>#o#-
> FuEgVqE{0iWQVnY
> zhqZ6<W?No0B86NnNY%RKQ|Q%WJTWs8dG^9q3 at MgOx?mz!&8c(oP?0$qY
> Gdfag<R9a
> z$Cg?^ng-
> 4i_J(V1p1|Hx@!aq}JkEMuHSl0>nV;*PkXQ#UcN0;(T2%$Za_a6tMMfBa
> z4yl1(${xf7Q-)}Dq0%i_{-hqPiP at hD&ekWXG5IRKn6@=c{eqRfAo{2oFEp8=;*Bcc
> zwC3WGs!#9ozM%0<RJfEaVpoI91MLY3h{)L&q(EK7+rYc+E!94#CLgi4&Ch=t3{iG
> U
> zYpXR+bykxDWc4RQAzr9Op*-xSQY0Z*z{EX5+UhKoiyE-~$H-!lLq|vF6&)4=-
> exwc
> z;K<@!w%hmurO+Nqe)v$*q?qzS$XZ*_t}?_0!{?C+XRDj3N|=Dw%Z$XWAl4Snl
> +HlT
> zi!n}S?L0sklHc^Dr7{8l1r5U+3x5kfOKIY)XE*6iC+e$`fMjcz)U40lRO23O`*yax
> z9=LeY6PvX-GD|(4b}x**AY4)Sli!_6;Yh4}Nw$I$N=Sdc&B`X7I>FvDzSAo<&=JjV
> zb19cwyLPu4m$!i~%P1`l)#;v^^)But{TyD!{ASqI0RST!DV7N7R`Ny863=k0c4R5o
> z;vMxEyUTvVbn^=Z)4B=T8noNrHtlt;v%9k1 at akU7cjWWC(ZJw_nVTn;>nibBwV
> Gnp
> z-
> %e&0glC<*9;1>1+tUV1c2v|1pt9u>+risd+O+9QYaH3>4==9oCbRisv6#>9Z?Dcz
> zd(v*W>a55cANeQR+_!Wel}pG2{9R)y4Bw at 2BSBb!j`ARY9V;=?VsGqyp}QPZIah
> 0x
> zTs>*0H#i**&xXUnNiWlS$`vx#Vu`r4YG&K9bVrR)dC<#nv%$$SyG;wqnM-
> 2w>zanQ
> z0NAF8`MK_?&5#!GOoht^(w1l1!rAq8tLZkL&6=GX6J<-
> Se_J#JLLAnb8E&y!!P&Bq
> znZ2+pLpnyX&|2<>qDF3oke~V%7;`Et<JZ~~a=kKgW9q9YpV;i6du^5_5BzI=u6w
> ;3
> zL%J3_a^bDZ1^%07p-
> F>vq?PBy%Kb>4RTrDD5^(jWoeMR`g_?X*kgXnI`zKa#e?7B|
> z`UaRiJuL)nkS?c={Lu{)H&meogim9o*5>u=;%eJ1);i_{=^+OE8ybj at _2dC|g~qgY
> z18UkAJ1Mxn$+D~QEuFHuRWL{{P=hfB3-
> M%fMWM&ycDpfyJw2M!k7O7WIMglkbKS6f
> zM31~1YD}%cB~VMGQ>J?EeygcfHE#kvhj~0YUD0u5dYZCg4J}F16Dz_F0b>zMY
> J#!X
> zGc!no^YyKpkYw_EfWBX<Z(R at 6%)Ll4-qaA4^9WNz3{9OL=TPA(W{tI|;i_*-
> %Ry2j
> z=#~%FK+9vWDcvhVw*?%sR$>u%rq_e4TRT at ClumkF)8!ygNUmb=ZGmi~miY
> %XAtbzu
> zKOzJt8g}4IH9PGQX}e{{&{!@95Q-`5xsa8hL&|c0rHu{K`Rrn5-Y`+FHO2C}HlLuX
> z6%4sOD>^@9f<#qa-
> H8?Z!A2B|7Ne<?Te}U#Oh)tc`U9G&UWXjNueL}AEX5dHd&Q0+
> z>wJFMYy!F$Go?@ct8zk`<8=5dGr<8-Sxq)LTK#L4uIZZq>lg%{nf?T|oNp0tSeJ4`
> z6GW1vSHmmj#@i05)$Cg2>Bkz<{^iuz+|#|c>mWZu-
> }cPfFT<fytR@$=hCMyKu`{dT
> z)fp!eL?E=bTJI8_Q_I)XlDf1;{{mL4`R&Dt4r!(Rv)fr6Hy}}WD_?V4+MDIAe0s-_
> zb+MdYpBXI4PDb~&+<?hBX*~4UL27;zF?Cbt#=%@USB+-
> 0!?y;Tb9;Gq(hVWeH0$<<
> zqnoKuS_ at _P&vUQ?^LvbFTtF<JPjIn8Cv>bd>kZDX?q;^#z;}w7ib?AERxy at Sgs;1
> y
> zv#nH+Dm%Ab4Bwt&HJ`$q!R6&>ba{1iKbhAz1YT%kL+eo8=YChMvhdi4HZ13py
> Blo7
> z<>mG5{d7?)-B7-
> mO6jn^2F_z0TcB>t6Uj+}?5ts$IkYHWt at 6CafXAk99jVx&A<acQ
> z)|!)u7 at p;>4Yo at dOBVOic0l-A&-
> wCLU^8y)srA9K30dQbh0~$Ape`cW@@)2`jxK8^
> zY#wPvHCrMci{)~$AyCH{a^@pm`xaM5P`XfQ1}C at m3OFL$e3r9?F<W4Gn4+)
> @Xj9*B
> z#vh+9Z}hn9M6E=J0rMVCi=kTiiV37g?@G($X7p)^l}hzH44vCU8SE|Pi%ah7VBO
> Y4
> z(Y$TKzJ<J=gNJ^gBA_sfu}}9Z=354HEKK*k*S!&$B(%S5KF_V06KimjU+smdwE?G
> g
> zgdpm?(O%cKDWC4sWA<tteL1ZS8q{JQAFM=bj{|J2N93s?wEmXoYT6f&Frpd|c-
> T!u
> ziY5O_c}uj8QS9VyM?+Yct5nP{S?!(6X?_!#tzrwL>F*>WhR1#kQn!PdHjbvEG>Eg
> 6
> za&cUBIx7Ui7Nd5UG?cPdOsvfXtY_O>k;TDR=r**Z#iOn{fh_3HFQG at 7fUP~|*N
> yv3
> zm|*nHp<L60_?QgY)~+u%#DO&~N57Ny&1rSc0&-
> Q%YU02qI}S3}mKsA$V2IT#(%waT
> zM}Bc>r(PbN=FJskC)cgr_hNEx<?=!Wa<f{;!UIk2=zK+l&cEGIwlV9Sx3Y>kM6-4H
> zw}kS%zn%W5Rj*p!4(paHTDzry at i<V6jSX~=AvXB5dkPaAu0PcM$!Ax?7t0Oo3
> y|4f
> zJKYo-
> wVK#@?yf6Ydzq`?_#U0kPHI`!4dXif)4Hv2U at CNSb=I$u@;y*I at T+O}<m`G<
> z6OYD42dBN-
> u!rgB?((s)+BT)uun at ero7#M<PVe;m@)jcOc{wa8^5uMb2MPQAj+n8j
> zt at e2zq%dIviwz*cUbdkqR<P9%%<2r9q`PKPNbF?3U)$2583E1jPa9NXr+0EXJc
> p@|
> z>+9>Q%hCDS=}GSc;YCTUw9_A)o?VQt$~Fv7s~NVkjQH)^(R(>jA>P{d(sr`!9R at k
> <
> zG|f7lEUQ~N!3)38t2A?MXp!p&{<7(vEo<E3og190wYuK0Ev{;H*3NZ(xG!d>#tub
> 5
> zsDrsyku<3hdq<Y!cf(rC7T^B=<E&c~aLKP4)cUTZN$aLLU|{!QSm<3_-txV)Uqd1J
> zz2lbfHWf>4)d(UoIn#47o1p#OJ at 1^^`QebEeFW)1^3_TR?9hGkK^yG-
> J4aSy$f36$
> ziygp_`taxKx_0sD{*8U{5Ympd4AOZ#Ir#$j;oD(5*REpVNDGJX at F=|ih%jC*hrNy
> z
> z<j)bM!!`WO*dMp7KEES-IlllhJrN2u(F;eFV=vrJlA+p?u4D(~=jGGO|KElqo%34R
> zfS7B;zVip_E$Kj~&qt1|^X25yNTfbc<u46PI=GsZ(JexR@^o?NQMuKA2njSMlN7
> 7P
> z^ycE^1B+ByE!}Vr6Wtrq!(r*c4y&g()M-Ah37M6>0)F%5Vs>{kIv);TC;D!gA8rEs
> zFmI-P*!ySRoKvH-d5_iBY&apruQ at I9)nYN5&8E}I-AJw(Iu>R}hnse~C&P;?48zyC
> zRGuEIYmw=EOw`hW at gdS0zQAo<Z1jPLR62tTSaEQ5eS0^Vl3AVFHZMj`JLd*#0
> Bdov
> z9*EC09<#F?1NQ07bcxF*ie{lGTV71mx}0NRMPa6=w`QcjL`nXx)KV1+?PZ^DoBz
> JN
> zc|u)Pk*+(6d)Q0r8`o+Xa0Te4pXiSk7|n~fis>_~gLE_;)GsrQ=v8MQtbp{kQO(8T
> zw%v{h$LNLdxv`oYjEW2K<RBX-
> AEOl;U}opB4I9rkE?nPG*}jiE=aUVNU)2P at clN#&
> zKi&K0*ITPru at lHFYu*as39#;5wB!i;?9~$>cBm at UX8;)s$VIWZc at g8R>}=8y#Hk
> SG
> zn`a-2TE~aeYv)H6>f at 2eN3E`gba1;_YduA9tq#F`?ziK|>REi;`gV0Lrj237_3GI*
> zYd!LfPr5CFLoYC=BhC7a1CmyoV>c4!nI2}NO6A%o`Q6#ejAmz@{`pPKUP^~p8u
> UyI
> zX;fH{=>C#3k~7#|`{H`C5GxMaeAMxosJ*$`^sFXoRV?l<26bydHp6|Y62Oy_!TIP
> 4
> zwqJ2O(J!Xg#`iLw3Y!DelNp=!uI6`Far>eJRB~hxu)$Kd-#<ASz|sHE)8(?^UDz%F
> zXLVrB!PUiwm#lwehCeO%9!x at A!K#T1ST+HZo_~i^o=;29{cD3o2Os#diT!Et3gM
> Lk
> TuM~Ktz$*n_Dey{xHWc`O(cS1K
> 
> literal 0
> HcmV?d00001
> 
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.id
> f
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.i
> df
> new file mode 100644
> index 0000000000..1f79332020
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.i
> df
> @@ -0,0 +1,10 @@
> +// /** @file
> +// Platform Logo image definition file.
> +//
> +// Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#image IMG_LOGO Logo.bmp
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.in
> f
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.i
> nf
> new file mode 100644
> index 0000000000..3380f3c1d5
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.i
> nf
> @@ -0,0 +1,28 @@
> +## @file
> +#  The default logo bitmap picture shown on setup screen, which is
> corresponding to gEfiDefaultBmpLogoGuid.
> +#
> +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = Logo
> +  MODULE_UNI_FILE                = Logo.uni
> +  FILE_GUID                      = 7BB28B99-61BB-11D5-9A5D-0090273FC14D
> +  MODULE_TYPE                    = USER_DEFINED
> +  VERSION_STRING                 = 1.0
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC ARM AARCH64
> +#
> +
> +[Binaries]
> +  BIN|Logo.bmp|*
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  LogoExtra.uni
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.u
> ni
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.u
> ni
> new file mode 100644
> index 0000000000..9d1bbaffa9
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/Logo.u
> ni
> @@ -0,0 +1,16 @@
> +// /** @file
> +// The default logo bitmap picture shown on setup screen, which is
> corresponding to gEfiDefaultBmpLogoGuid.
> +//
> +// This module provides the default logo bitmap picture shown on setup
> screen, which corresponds to gEfiDefaultBmpLogoGuid.
> +//
> +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Provides the default
> logo bitmap picture shown on setup screen, which corresponds to
> gEfiDefaultBmpLogoGuid"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This module
> provides the default logo bitmap picture shown on setup screen, which
> corresponds to gEfiDefaultBmpLogoGuid."
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xe.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xe.inf
> new file mode 100644
> index 0000000000..01102b138f
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xe.inf
> @@ -0,0 +1,55 @@
> +## @file
> +#  The default logo bitmap picture shown on setup screen.
> +#
> +# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = LogoDxe
> +  MODULE_UNI_FILE                = LogoDxe.uni
> +  FILE_GUID                      = F74D20EE-37E7-48FC-97F7-9B1047749C69
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeLogo
> +#
> +#  This flag specifies whether HII resource section is generated into PE image.
> +#
> +  UEFI_HII_RESOURCE_SECTION      = TRUE
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  Logo.bmp
> +  Logo.c
> +  Logo.idf
> +
> +[Packages]
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  DebugLib
> +
> +[Protocols]
> +  gEfiHiiDatabaseProtocolGuid        ## CONSUMES
> +  gEfiHiiImageExProtocolGuid         ## CONSUMES
> +  gEfiHiiPackageListProtocolGuid     ## PRODUCES CONSUMES
> +  gEdkiiPlatformLogoProtocolGuid     ## PRODUCES
> +
> +[Depex]
> +  gEfiHiiDatabaseProtocolGuid AND
> +  gEfiHiiImageExProtocolGuid
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  LogoDxeExtra.uni
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xe.uni
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xe.uni
> new file mode 100644
> index 0000000000..9635701b60
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xe.uni
> @@ -0,0 +1,16 @@
> +// /** @file
> +// The default logo bitmap picture shown on setup screen.
> +//
> +// This module provides the default logo bitmap picture shown on setup
> screen, through EDKII Platform Logo protocol.
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Provides the default
> logo bitmap picture shown on setup screen."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This module
> provides the default logo bitmap picture shown on setup screen, through EDKII
> Platform Logo protocol."
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xeExtra.uni
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xeExtra.uni
> new file mode 100644
> index 0000000000..c6ea34b81d
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoD
> xeExtra.uni
> @@ -0,0 +1,14 @@
> +// /** @file
> +// Logo Localized Strings and Content
> +//
> +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Logo Image File"
> +
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoEx
> tra.uni
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoEx
> tra.uni
> new file mode 100644
> index 0000000000..041179fb75
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdeModulePkg/Logo/LogoEx
> tra.uni
> @@ -0,0 +1,14 @@
> +// /** @file
> +// Logo Localized Strings and Content
> +//
> +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Logo Image File"
> +
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf
> 8/DxePciLibX58Ich10.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf
> 8/DxePciLibX58Ich10.inf
> new file mode 100644
> index 0000000000..e5ca95e20e
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MdePkg/Library/BasePciLibCf
> 8/DxePciLibX58Ich10.inf
> @@ -0,0 +1,40 @@
> +## @file
> +#  An instance of the PCI Library that is based on both the PCI CF8 Library and
> +#  the PCI Express Library.
> +#
> +#  This PciLib instance caches the SimicsX58 platform type (X58-ICH10) in
> +#  its entry point function, then delegates function calls to one of the
> +#  PciCf8Lib or PciExpressLib "backends" as appropriate.
> +#
> +#  Copyright (C) 2016, Red Hat, Inc.
> +# Copyright (c) 2007 - 2014 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = DxePciLibX58Ich10
> +  FILE_GUID                      = FC214B5D-B5B5-4E54-9B28-5E94532E5E2A
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciLib|DXE_DRIVER DXE_RUNTIME_DRIVER
> SMM_CORE DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION
> +  CONSTRUCTOR                    = InitializeConfigAccessMethod
> +
> +#  VALID_ARCHITECTURES           = IA32 X64
> +
> +[Sources]
> +  PciLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> +
> +[LibraryClasses]
> +  PcdLib
> +  PciCf8Lib
> +  PciExpressLib
> +
> +[Pcd]
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.h
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.h
> new file mode 100644
> index 0000000000..2deb2a88eb
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.h
> @@ -0,0 +1,45 @@
> +/** @file
> +  This is an implementation of the ACPI platform driver.
> +
> +  Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _ACPI_PLATFORM_H_
> +#define _ACPI_PLATFORM_H_
> +
> +//
> +// Statements that include other header files
> +//
> +
> +#include <Base.h>
> +#include <Uefi.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/HighPrecisionEventTimerTable.h>
> +#include
> <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +#include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
> +#include <Register/Hpet.h>
> +#include <Guid/EventGroup.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/BoardAcpiTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/AslUpdateLib.h>
> +#include <Library/PciSegmentInfoLib.h>
> +
> +#include <Protocol/AcpiTable.h>
> +#include <Protocol/MpService.h>
> +#include <Protocol/PciIo.h>
> +
> +#include <Register/Cpuid.h>
> +
> +#endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.inf
> new file mode 100644
> index 0000000000..b4b52b6622
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/MinPlatformPkg/Acpi/AcpiTa
> bles/AcpiPlatform.inf
> @@ -0,0 +1,105 @@
> +## @file
> +#  Component information file for AcpiPlatform module
> +#
> +# Copyright (c) 2017 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = AcpiPlatform
> +  FILE_GUID                      = FC90EB7A-3E0A-483C-A26C-484D36593FF4
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = InstallAcpiPlatform
> +
> +[Sources.common]
> +  AcpiPlatform.h
> +  AcpiPlatform.c
> +  Fadt/Fadt.c
> +  Facs/Facs.c
> +  Hpet/Hpet.c
> +  Wsmt/Wsmt.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +  MinPlatformPkg/MinPlatformPkg.dec
> +  PcAtChipsetPkg/PcAtChipsetPkg.dec
> +
> +[LibraryClasses]
> +  UefiDriverEntryPoint
> +  BaseLib
> +  DebugLib
> +  IoLib
> +  PcdLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  BaseMemoryLib
> +  HobLib
> +  PciSegmentInfoLib
> +  AslUpdateLib
> +
> +[Pcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
> +
> +  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicEnable
> +  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicCount
> +  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicIdBase
> +  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicAddressBase
> +  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicInterruptBase
> +  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuThreadCount
> +  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuCoreCount
> +  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
> +
> +  gMinPlatformPkgTokenSpaceGuid.PcdFadtPreferredPmProfile
> +  gMinPlatformPkgTokenSpaceGuid.PcdFadtIaPcBootArch
> +  gMinPlatformPkgTokenSpaceGuid.PcdFadtFlags
> +
> +  gPcAtChipsetPkgTokenSpaceGuid.PcdHpetBaseAddress
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdPciExpressRegionLength
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiEnableSwSmi
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiDisableSwSmi
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AEventBlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BEventBlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AControlBlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BControlBlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm2ControlBlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPmTimerBlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe0BlockAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe1BlockAddress
> +
> +  gMinPlatformPkgTokenSpaceGuid.PcdLocalApicAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdIoApicAddress
> +  gMinPlatformPkgTokenSpaceGuid.PcdIoApicId
> +
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
> +  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
> +
> +  gMinPlatformPkgTokenSpaceGuid.PcdWsmtProtectionFlags
> +
> +[Protocols]
> +  gEfiAcpiTableProtocolGuid                     ## CONSUMES
> +  gEfiMpServiceProtocolGuid                     ## CONSUMES
> +  gEfiPciIoProtocolGuid                         ## CONSUMES
> +
> +[Guids]
> +  gEfiGlobalVariableGuid                        ## CONSUMES
> +  gEfiHobListGuid                               ## CONSUMES
> +  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
> +
> +[Depex]
> +  gEfiAcpiTableProtocolGuid           AND
> +  gEfiMpServiceProtocolGuid           AND
> +  gEfiPciRootBridgeIoProtocolGuid     AND
> +  gEfiVariableArchProtocolGuid        AND
> +  gEfiVariableWriteArchProtocolGuid
> +
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qe
> mu.h
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qe
> mu.h
> new file mode 100644
> index 0000000000..f6ef44a14f
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qe
> mu.h
> @@ -0,0 +1,507 @@
> +/** @file
> +  QEMU Video Controller Driver
> +
> +  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +//
> +// QEMU Video Controller Driver
> +//
> +
> +#ifndef _QEMU_H_
> +#define _QEMU_H_
> +
> +
> +#include <Uefi.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/PciIo.h>
> +#include <Protocol/DriverSupportedEfiVersion.h>
> +#include <Protocol/DevicePath.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/FrameBufferBltLib.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/Acpi.h>
> +
> +#include <Library/S3BootScriptLib.h>
> +
> +//
> +// QEMU Video PCI Configuration Header values
> +//
> +#define CIRRUS_LOGIC_VENDOR_ID                0x1013
> +#define CIRRUS_LOGIC_5430_DEVICE_ID           0x00a8
> +#define CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID 0x00a0
> +#define CIRRUS_LOGIC_5446_DEVICE_ID           0x00b8
> +
> +//
> +// QEMU Vide Graphical Mode Data
> +//
> +typedef struct {
> +  UINT32  InternalModeIndex; // points into card-specific mode table
> +  UINT32  HorizontalResolution;
> +  UINT32  VerticalResolution;
> +  UINT32  ColorDepth;
> +} QEMU_VIDEO_MODE_DATA;
> +
> +#define PIXEL_RED_SHIFT   0
> +#define PIXEL_GREEN_SHIFT 3
> +#define PIXEL_BLUE_SHIFT  6
> +
> +#define PIXEL_RED_MASK    (BIT7 | BIT6 | BIT5)
> +#define PIXEL_GREEN_MASK  (BIT4 | BIT3 | BIT2)
> +#define PIXEL_BLUE_MASK   (BIT1 | BIT0)
> +
> +#define PIXEL_TO_COLOR_BYTE(pixel, mask, shift) ((UINT8) ((pixel & mask) <<
> shift))
> +#define PIXEL_TO_RED_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel,
> PIXEL_RED_MASK, PIXEL_RED_SHIFT)
> +#define PIXEL_TO_GREEN_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel,
> PIXEL_GREEN_MASK, PIXEL_GREEN_SHIFT)
> +#define PIXEL_TO_BLUE_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel,
> PIXEL_BLUE_MASK, PIXEL_BLUE_SHIFT)
> +
> +#define RGB_BYTES_TO_PIXEL(Red, Green, Blue) \
> +  (UINT8) ( (((Red) >> PIXEL_RED_SHIFT) & PIXEL_RED_MASK) | \
> +            (((Green) >> PIXEL_GREEN_SHIFT) & PIXEL_GREEN_MASK) | \
> +            (((Blue) >> PIXEL_BLUE_SHIFT) & PIXEL_BLUE_MASK) )
> +
> +#define PIXEL24_RED_MASK    0x00ff0000
> +#define PIXEL24_GREEN_MASK  0x0000ff00
> +#define PIXEL24_BLUE_MASK   0x000000ff
> +
> +#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
> +
> +//
> +// QEMU Video Private Data Structure
> +//
> +#define QEMU_VIDEO_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('Q', 'V',
> 'I', 'D')
> +
> +typedef enum {
> +  QEMU_VIDEO_CIRRUS_5430 = 1,
> +  QEMU_VIDEO_CIRRUS_5446,
> +  QEMU_VIDEO_BOCHS,
> +  QEMU_VIDEO_BOCHS_MMIO,
> +} QEMU_VIDEO_VARIANT;
> +
> +typedef struct {
> +  UINT8                                 SubClass;
> +  UINT16                                VendorId;
> +  UINT16                                DeviceId;
> +  QEMU_VIDEO_VARIANT                    Variant;
> +  CHAR16                                *Name;
> +} QEMU_VIDEO_CARD;
> +
> +typedef struct {
> +  UINT64                                Signature;
> +  EFI_HANDLE                            Handle;
> +  EFI_PCI_IO_PROTOCOL                   *PciIo;
> +  UINT64                                OriginalPciAttributes;
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL          GraphicsOutput;
> +  EFI_DEVICE_PATH_PROTOCOL              *GopDevicePath;
> +
> +  //
> +  // The next two fields match the client-visible
> +  // EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.MaxMode field.
> +  //
> +  UINTN                                 MaxMode;
> +  QEMU_VIDEO_MODE_DATA                  *ModeData;
> +
> +  QEMU_VIDEO_VARIANT                    Variant;
> +  FRAME_BUFFER_CONFIGURE                *FrameBufferBltConfigure;
> +  UINTN                                 FrameBufferBltConfigureSize;
> +} QEMU_VIDEO_PRIVATE_DATA;
> +
> +///
> +/// Card-specific Video Mode structures
> +///
> +typedef struct {
> +  UINT32  Width;
> +  UINT32  Height;
> +  UINT32  ColorDepth;
> +  UINT8   *CrtcSettings;
> +  UINT16  *SeqSettings;
> +  UINT8   MiscSetting;
> +} QEMU_VIDEO_CIRRUS_MODES;
> +
> +typedef struct {
> +  UINT32  Width;
> +  UINT32  Height;
> +  UINT32  ColorDepth;
> +} QEMU_VIDEO_BOCHS_MODES;
> +
> +#define QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS(a) \
> +  CR(a, QEMU_VIDEO_PRIVATE_DATA, GraphicsOutput,
> QEMU_VIDEO_PRIVATE_DATA_SIGNATURE)
> +
> +
> +//
> +// Global Variables
> +//
> +extern UINT8                                      AttributeController[];
> +extern UINT8                                      GraphicsController[];
> +extern UINT8                                      Crtc_640_480_256_60[];
> +extern UINT16                                     Seq_640_480_256_60[];
> +extern UINT8                                      Crtc_800_600_256_60[];
> +extern UINT16                                     Seq_800_600_256_60[];
> +extern UINT8                                      Crtc_1024_768_256_60[];
> +extern UINT16                                     Seq_1024_768_256_60[];
> +extern QEMU_VIDEO_CIRRUS_MODES                    QemuVideoCirrusModes[];
> +extern QEMU_VIDEO_BOCHS_MODES                     QemuVideoBochsModes[];
> +extern EFI_DRIVER_BINDING_PROTOCOL                gQemuVideoDriverBinding;
> +extern EFI_COMPONENT_NAME_PROTOCOL
> gQemuVideoComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL
> gQemuVideoComponentName2;
> +extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL
> gQemuVideoDriverSupportedEfiVersion;
> +
> +//
> +// Io Registers defined by VGA
> +//
> +#define CRTC_ADDRESS_REGISTER   0x3d4
> +#define CRTC_DATA_REGISTER      0x3d5
> +#define SEQ_ADDRESS_REGISTER    0x3c4
> +#define SEQ_DATA_REGISTER       0x3c5
> +#define GRAPH_ADDRESS_REGISTER  0x3ce
> +#define GRAPH_DATA_REGISTER     0x3cf
> +#define ATT_ADDRESS_REGISTER    0x3c0
> +#define MISC_OUTPUT_REGISTER    0x3c2
> +#define INPUT_STATUS_1_REGISTER 0x3da
> +#define DAC_PIXEL_MASK_REGISTER 0x3c6
> +#define PALETTE_INDEX_REGISTER  0x3c8
> +#define PALETTE_DATA_REGISTER   0x3c9
> +
> +#define VBE_DISPI_IOPORT_INDEX           0x01CE
> +#define VBE_DISPI_IOPORT_DATA            0x01D0
> +
> +#define VBE_DISPI_INDEX_ID               0x0
> +#define VBE_DISPI_INDEX_XRES             0x1
> +#define VBE_DISPI_INDEX_YRES             0x2
> +#define VBE_DISPI_INDEX_BPP              0x3
> +#define VBE_DISPI_INDEX_ENABLE           0x4
> +#define VBE_DISPI_INDEX_BANK             0x5
> +#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
> +#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
> +#define VBE_DISPI_INDEX_X_OFFSET         0x8
> +#define VBE_DISPI_INDEX_Y_OFFSET         0x9
> +#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
> +
> +#define VBE_DISPI_ID0                    0xB0C0
> +#define VBE_DISPI_ID1                    0xB0C1
> +#define VBE_DISPI_ID2                    0xB0C2
> +#define VBE_DISPI_ID3                    0xB0C3
> +#define VBE_DISPI_ID4                    0xB0C4
> +#define VBE_DISPI_ID5                    0xB0C5
> +
> +#define VBE_DISPI_DISABLED               0x00
> +#define VBE_DISPI_ENABLED                0x01
> +#define VBE_DISPI_GETCAPS                0x02
> +#define VBE_DISPI_8BIT_DAC               0x20
> +#define VBE_DISPI_LFB_ENABLED            0x40
> +#define VBE_DISPI_NOCLEARMEM             0x80
> +
> +//
> +// Graphics Output Hardware abstraction internal worker functions
> +//
> +EFI_STATUS
> +QemuVideoGraphicsOutputConstructor (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  );
> +
> +EFI_STATUS
> +QemuVideoGraphicsOutputDestructor (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  );
> +
> +
> +//
> +// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface
> +//
> +/**
> +  TODO: Add function description
> +
> +  @param  This TODO: add argument description
> +  @param  Controller TODO: add argument description
> +  @param  RemainingDevicePath TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoControllerDriverSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> +  );
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  This TODO: add argument description
> +  @param  Controller TODO: add argument description
> +  @param  RemainingDevicePath TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoControllerDriverStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
> +  );
> +
> +/**
> +  TODO: Add function description
> +
> +  @param  This TODO: add argument description
> +  @param  Controller TODO: add argument description
> +  @param  NumberOfChildren TODO: add argument description
> +  @param  ChildHandleBuffer TODO: add argument description
> +
> +  TODO: add return values
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoControllerDriverStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                   Controller,
> +  IN UINTN                        NumberOfChildren,
> +  IN EFI_HANDLE                   *ChildHandleBuffer
> +  );
> +
> +//
> +// EFI Component Name Functions
> +//
> +/**
> +  Retrieves a Unicode string that is the user readable name of the driver.
> +
> +  This function retrieves the user readable name of a driver in the form of a
> +  Unicode string. If the driver specified by This has a user readable name in
> +  the language specified by Language, then a pointer to the driver name is
> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> +  by This does not support the language specified by Language,
> +  then EFI_UNSUPPORTED is returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language. This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified
> +                                in RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  DriverName[out]       A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                driver specified by This in the language
> +                                specified by Language.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
> +                                This and the language specified by Language was
> +                                returned in DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoComponentNameGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  );
> +
> +
> +/**
> +  Retrieves a Unicode string that is the user readable name of the controller
> +  that is being managed by a driver.
> +
> +  This function retrieves the user readable name of the controller specified by
> +  ControllerHandle and ChildHandle in the form of a Unicode string. If the
> +  driver specified by This has a user readable name in the language specified by
> +  Language, then a pointer to the controller name is returned in
> ControllerName,
> +  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
> +  managing the controller specified by ControllerHandle and ChildHandle,
> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
> +  support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
> +
> +  @param  This[in]              A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
> +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> +  @param  ControllerHandle[in]  The handle of a controller that the driver
> +                                specified by This is managing.  This handle
> +                                specifies the controller whose name is to be
> +                                returned.
> +
> +  @param  ChildHandle[in]       The handle of the child controller to retrieve
> +                                the name of.  This is an optional parameter that
> +                                may be NULL.  It will be NULL for device
> +                                drivers.  It will also be NULL for a bus drivers
> +                                that wish to retrieve the name of the bus
> +                                controller.  It will not be NULL for a bus
> +                                driver that wishes to retrieve the name of a
> +                                child controller.
> +
> +  @param  Language[in]          A pointer to a Null-terminated ASCII string
> +                                array indicating the language.  This is the
> +                                language of the driver name that the caller is
> +                                requesting, and it must match one of the
> +                                languages specified in SupportedLanguages. The
> +                                number of languages supported by a driver is up
> +                                to the driver writer. Language is specified in
> +                                RFC 4646 or ISO 639-2 language code format.
> +
> +  @param  ControllerName[out]   A pointer to the Unicode string to return.
> +                                This Unicode string is the name of the
> +                                controller specified by ControllerHandle and
> +                                ChildHandle in the language specified by
> +                                Language from the point of view of the driver
> +                                specified by This.
> +
> +  @retval EFI_SUCCESS           The Unicode string for the user readable name in
> +                                the language specified by Language for the
> +                                driver specified by This was returned in
> +                                DriverName.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
> EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid
> +                                EFI_HANDLE.
> +
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> +                                managing the controller specified by
> +                                ControllerHandle and ChildHandle.
> +
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not support
> +                                the language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +QemuVideoComponentNameGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHandle,
> +  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT CHAR16                                          **ControllerName
> +  );
> +
> +
> +//
> +// Local Function Prototypes
> +//
> +VOID
> +InitializeCirrusGraphicsMode (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  QEMU_VIDEO_CIRRUS_MODES  *ModeData
> +  );
> +
> +VOID
> +InitializeBochsGraphicsMode (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  QEMU_VIDEO_BOCHS_MODES   *ModeData
> +  );
> +
> +VOID
> +SetPaletteColor (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Index,
> +  UINT8                           Red,
> +  UINT8                           Green,
> +  UINT8                           Blue
> +  );
> +
> +VOID
> +SetDefaultPalette (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  );
> +
> +VOID
> +DrawLogo (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           ScreenWidth,
> +  UINTN                           ScreenHeight
> +  );
> +
> +VOID
> +outb (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address,
> +  UINT8                           Data
> +  );
> +
> +VOID
> +outw (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address,
> +  UINT16                          Data
> +  );
> +
> +UINT8
> +inb (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address
> +  );
> +
> +UINT16
> +inw (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                           Address
> +  );
> +
> +VOID
> +BochsWrite (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINT16                   Reg,
> +  UINT16                   Data
> +  );
> +
> +UINT16
> +BochsRead (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINT16                   Reg
> +  );
> +
> +VOID
> +VgaOutb (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  UINTN                    Reg,
> +  UINT8                    Data
> +  );
> +
> +EFI_STATUS
> +QemuVideoCirrusModeSetup (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private
> +  );
> +
> +EFI_STATUS
> +QemuVideoBochsModeSetup (
> +  QEMU_VIDEO_PRIVATE_DATA  *Private,
> +  BOOLEAN                  IsQxl
> +  );
> +
> +VOID
> +InstallVbeShim (
> +  IN CONST CHAR16         *CardName,
> +  IN EFI_PHYSICAL_ADDRESS FrameBufferBase
> +  );
> +#endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qe
> muVideoDxe.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qe
> muVideoDxe.inf
> new file mode 100644
> index 0000000000..8370559016
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Qe
> muVideoDxe.inf
> @@ -0,0 +1,73 @@
> +## @file
> +#  This driver is a sample implementation of the Graphics Output Protocol for
> +#  the QEMU (Cirrus Logic 5446) video controller.
> +#
> +# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = QemuVideoDxe
> +  FILE_GUID                      = e3752948-b9a1-4770-90c4-df41c38986be
> +  MODULE_TYPE                    = UEFI_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeQemuVideo
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +#  DRIVER_BINDING                =  gQemuVideoDriverBinding
> +#  COMPONENT_NAME                =  gQemuVideoComponentName
> +#
> +
> +[Sources.common]
> +  ComponentName.c
> +  Driver.c
> +  DriverSupportedEfiVersion.c
> +  Gop.c
> +  Initialize.c
> +  Qemu.h
> +
> +[Sources.Ia32, Sources.X64]
> +  VbeShim.c
> +  VbeShim.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  OptionRomPkg/OptionRomPkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +  SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  FrameBufferBltLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  PcdLib
> +  PciLib
> +  PrintLib
> +  TimerLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  S3BootScriptLib
> +
> +[Protocols]
> +  gEfiDriverSupportedEfiVersionProtocolGuid     # PROTOCOL
> ALWAYS_PRODUCED
> +  gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
> +  gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
> +  gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> +  gEfiDxeSmmReadyToLockProtocolGuid
> +
> +[Pcd]
> +  gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.asm
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.asm
> new file mode 100644
> index 0000000000..cb2a60d827
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.asm
> @@ -0,0 +1,281 @@
> +;------------------------------------------------------------------------------
> +; @file
> +; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's
> buggy,
> +; default VGA driver to switch to 1024x768x32, on the stdvga and QXL video
> +; cards of QEMU.
> +;
> +; Copyright (C) 2014, Red Hat, Inc.
> +; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
> +;
> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +;------------------------------------------------------------------------------
> +
> +; enable this macro for debug messages
> +;%define DEBUG
> +
> +%macro DebugLog 1
> +%ifdef DEBUG
> +  push       si
> +  mov        si, %1
> +  call       PrintStringSi
> +  pop        si
> +%endif
> +%endmacro
> +
> +
> +BITS 16
> +ORG 0
> +
> +VbeInfo:
> +TIMES 256 nop
> +
> +VbeModeInfo:
> +TIMES 256 nop
> +
> +
> +Handler:
> +  cmp        ax, 0x4f00
> +  je         GetInfo
> +  cmp        ax, 0x4f01
> +  je         GetModeInfo
> +  cmp        ax, 0x4f02
> +  je         SetMode
> +  cmp        ax, 0x4f03
> +  je         GetMode
> +  cmp        ax, 0x4f10
> +  je         GetPmCapabilities
> +  cmp        ax, 0x4f15
> +  je         ReadEdid
> +  cmp        ah, 0x00
> +  je         SetModeLegacy
> +  DebugLog   StrUnkownFunction
> +Hang:
> +  jmp        Hang
> +
> +
> +GetInfo:
> +  push       es
> +  push       di
> +  push       ds
> +  push       si
> +  push       cx
> +
> +  DebugLog   StrEnterGetInfo
> +
> +  ; target (es:di) set on input
> +  push       cs
> +  pop        ds
> +  mov        si, VbeInfo
> +  ; source (ds:si) set now
> +
> +  mov        cx, 256
> +  cld
> +  rep movsb
> +
> +  pop        cx
> +  pop        si
> +  pop        ds
> +  pop        di
> +  pop        es
> +  jmp        Success
> +
> +
> +GetModeInfo:
> +  push       es
> +  push       di
> +  push       ds
> +  push       si
> +  push       cx
> +
> +  DebugLog   StrEnterGetModeInfo
> +
> +  and        cx, ~0x4000 ; clear potentially set LFB bit in mode number
> +  cmp        cx, 0x00f1
> +  je         KnownMode1
> +  DebugLog   StrUnkownMode
> +  jmp        Hang
> +KnownMode1:
> +  ; target (es:di) set on input
> +  push       cs
> +  pop        ds
> +  mov        si, VbeModeInfo
> +  ; source (ds:si) set now
> +
> +  mov        cx, 256
> +  cld
> +  rep movsb
> +
> +  pop        cx
> +  pop        si
> +  pop        ds
> +  pop        di
> +  pop        es
> +  jmp        Success
> +
> +
> +%define ATT_ADDRESS_REGISTER   0x03c0
> +%define VBE_DISPI_IOPORT_INDEX 0x01ce
> +%define VBE_DISPI_IOPORT_DATA  0x01d0
> +
> +%define VBE_DISPI_INDEX_XRES        0x1
> +%define VBE_DISPI_INDEX_YRES        0x2
> +%define VBE_DISPI_INDEX_BPP         0x3
> +%define VBE_DISPI_INDEX_ENABLE      0x4
> +%define VBE_DISPI_INDEX_BANK        0x5
> +%define VBE_DISPI_INDEX_VIRT_WIDTH  0x6
> +%define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
> +%define VBE_DISPI_INDEX_X_OFFSET    0x8
> +%define VBE_DISPI_INDEX_Y_OFFSET    0x9
> +
> +%define VBE_DISPI_ENABLED     0x01
> +%define VBE_DISPI_LFB_ENABLED 0x40
> +
> +%macro BochsWrite 2
> +  push       dx
> +  push       ax
> +
> +  mov        dx, VBE_DISPI_IOPORT_INDEX
> +  mov        ax, %1
> +  out        dx, ax
> +
> +  mov        dx, VBE_DISPI_IOPORT_DATA
> +  mov        ax, %2
> +  out        dx, ax
> +
> +  pop        ax
> +  pop        dx
> +%endmacro
> +
> +SetMode:
> +  push       dx
> +  push       ax
> +
> +  DebugLog   StrEnterSetMode
> +
> +  cmp        bx, 0x40f1
> +  je         KnownMode2
> +  DebugLog   StrUnkownMode
> +  jmp        Hang
> +KnownMode2:
> +
> +  ; unblank
> +  mov        dx, ATT_ADDRESS_REGISTER
> +  mov        al, 0x20
> +  out        dx, al
> +
> +  BochsWrite VBE_DISPI_INDEX_ENABLE,        0
> +  BochsWrite VBE_DISPI_INDEX_BANK,          0
> +  BochsWrite VBE_DISPI_INDEX_X_OFFSET,      0
> +  BochsWrite VBE_DISPI_INDEX_Y_OFFSET,      0
> +  BochsWrite VBE_DISPI_INDEX_BPP,          32
> +  BochsWrite VBE_DISPI_INDEX_XRES,       1024
> +  BochsWrite VBE_DISPI_INDEX_VIRT_WIDTH, 1024
> +  BochsWrite VBE_DISPI_INDEX_YRES,        768
> +  BochsWrite VBE_DISPI_INDEX_VIRT_HEIGHT, 768
> +  BochsWrite VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED |
> VBE_DISPI_LFB_ENABLED
> +
> +  pop        ax
> +  pop        dx
> +  jmp        Success
> +
> +
> +GetMode:
> +  DebugLog   StrEnterGetMode
> +  mov        bx, 0x40f1
> +  jmp        Success
> +
> +
> +GetPmCapabilities:
> +  DebugLog   StrGetPmCapabilities
> +  jmp        Unsupported
> +
> +
> +ReadEdid:
> +  DebugLog   StrReadEdid
> +  jmp        Unsupported
> +
> +
> +SetModeLegacy:
> +  DebugLog   StrEnterSetModeLegacy
> +
> +  cmp        al, 0x03
> +  je         KnownMode3
> +  cmp        al, 0x12
> +  je         KnownMode4
> +  DebugLog   StrUnkownMode
> +  jmp        Hang
> +KnownMode3:
> +  mov        al, 0x30
> +  jmp        SetModeLegacyDone
> +KnownMode4:
> +  mov        al, 0x20
> +SetModeLegacyDone:
> +  DebugLog   StrExitSuccess
> +  iret
> +
> +
> +Success:
> +  DebugLog   StrExitSuccess
> +  mov        ax, 0x004f
> +  iret
> +
> +
> +Unsupported:
> +  DebugLog   StrExitUnsupported
> +  mov        ax, 0x014f
> +  iret
> +
> +
> +%ifdef DEBUG
> +PrintStringSi:
> +  pusha
> +  push       ds ; save original
> +  push       cs
> +  pop        ds
> +  mov        dx, 0x0402
> +PrintStringSiLoop:
> +  lodsb
> +  cmp        al, 0
> +  je         PrintStringSiDone
> +  out        dx, al
> +  jmp        PrintStringSiLoop
> +PrintStringSiDone:
> +  pop        ds ; restore original
> +  popa
> +  ret
> +
> +
> +StrExitSuccess:
> +  db 'Exit', 0x0a, 0
> +
> +StrExitUnsupported:
> +  db 'Unsupported', 0x0a, 0
> +
> +StrUnkownFunction:
> +  db 'Unknown Function', 0x0a, 0
> +
> +StrEnterGetInfo:
> +  db 'GetInfo', 0x0a, 0
> +
> +StrEnterGetModeInfo:
> +  db 'GetModeInfo', 0x0a, 0
> +
> +StrEnterGetMode:
> +  db 'GetMode', 0x0a, 0
> +
> +StrEnterSetMode:
> +  db 'SetMode', 0x0a, 0
> +
> +StrEnterSetModeLegacy:
> +  db 'SetModeLegacy', 0x0a, 0
> +
> +StrUnkownMode:
> +  db 'Unkown Mode', 0x0a, 0
> +
> +StrGetPmCapabilities:
> +  db 'GetPmCapabilities', 0x0a, 0
> +
> +StrReadEdid:
> +  db 'ReadEdid', 0x0a, 0
> +%endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.h
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.h
> new file mode 100644
> index 0000000000..cc9b6e14cd
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.h
> @@ -0,0 +1,701 @@
> +//
> +// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
> +//
> +#ifndef _VBE_SHIM_H_
> +#define _VBE_SHIM_H_
> +STATIC CONST UINT8 mVbeShim[] = {
> +  /* 00000000 nop                            */  0x90,
> +  /* 00000001 nop                            */  0x90,
> +  /* 00000002 nop                            */  0x90,
> +  /* 00000003 nop                            */  0x90,
> +  /* 00000004 nop                            */  0x90,
> +  /* 00000005 nop                            */  0x90,
> +  /* 00000006 nop                            */  0x90,
> +  /* 00000007 nop                            */  0x90,
> +  /* 00000008 nop                            */  0x90,
> +  /* 00000009 nop                            */  0x90,
> +  /* 0000000A nop                            */  0x90,
> +  /* 0000000B nop                            */  0x90,
> +  /* 0000000C nop                            */  0x90,
> +  /* 0000000D nop                            */  0x90,
> +  /* 0000000E nop                            */  0x90,
> +  /* 0000000F nop                            */  0x90,
> +  /* 00000010 nop                            */  0x90,
> +  /* 00000011 nop                            */  0x90,
> +  /* 00000012 nop                            */  0x90,
> +  /* 00000013 nop                            */  0x90,
> +  /* 00000014 nop                            */  0x90,
> +  /* 00000015 nop                            */  0x90,
> +  /* 00000016 nop                            */  0x90,
> +  /* 00000017 nop                            */  0x90,
> +  /* 00000018 nop                            */  0x90,
> +  /* 00000019 nop                            */  0x90,
> +  /* 0000001A nop                            */  0x90,
> +  /* 0000001B nop                            */  0x90,
> +  /* 0000001C nop                            */  0x90,
> +  /* 0000001D nop                            */  0x90,
> +  /* 0000001E nop                            */  0x90,
> +  /* 0000001F nop                            */  0x90,
> +  /* 00000020 nop                            */  0x90,
> +  /* 00000021 nop                            */  0x90,
> +  /* 00000022 nop                            */  0x90,
> +  /* 00000023 nop                            */  0x90,
> +  /* 00000024 nop                            */  0x90,
> +  /* 00000025 nop                            */  0x90,
> +  /* 00000026 nop                            */  0x90,
> +  /* 00000027 nop                            */  0x90,
> +  /* 00000028 nop                            */  0x90,
> +  /* 00000029 nop                            */  0x90,
> +  /* 0000002A nop                            */  0x90,
> +  /* 0000002B nop                            */  0x90,
> +  /* 0000002C nop                            */  0x90,
> +  /* 0000002D nop                            */  0x90,
> +  /* 0000002E nop                            */  0x90,
> +  /* 0000002F nop                            */  0x90,
> +  /* 00000030 nop                            */  0x90,
> +  /* 00000031 nop                            */  0x90,
> +  /* 00000032 nop                            */  0x90,
> +  /* 00000033 nop                            */  0x90,
> +  /* 00000034 nop                            */  0x90,
> +  /* 00000035 nop                            */  0x90,
> +  /* 00000036 nop                            */  0x90,
> +  /* 00000037 nop                            */  0x90,
> +  /* 00000038 nop                            */  0x90,
> +  /* 00000039 nop                            */  0x90,
> +  /* 0000003A nop                            */  0x90,
> +  /* 0000003B nop                            */  0x90,
> +  /* 0000003C nop                            */  0x90,
> +  /* 0000003D nop                            */  0x90,
> +  /* 0000003E nop                            */  0x90,
> +  /* 0000003F nop                            */  0x90,
> +  /* 00000040 nop                            */  0x90,
> +  /* 00000041 nop                            */  0x90,
> +  /* 00000042 nop                            */  0x90,
> +  /* 00000043 nop                            */  0x90,
> +  /* 00000044 nop                            */  0x90,
> +  /* 00000045 nop                            */  0x90,
> +  /* 00000046 nop                            */  0x90,
> +  /* 00000047 nop                            */  0x90,
> +  /* 00000048 nop                            */  0x90,
> +  /* 00000049 nop                            */  0x90,
> +  /* 0000004A nop                            */  0x90,
> +  /* 0000004B nop                            */  0x90,
> +  /* 0000004C nop                            */  0x90,
> +  /* 0000004D nop                            */  0x90,
> +  /* 0000004E nop                            */  0x90,
> +  /* 0000004F nop                            */  0x90,
> +  /* 00000050 nop                            */  0x90,
> +  /* 00000051 nop                            */  0x90,
> +  /* 00000052 nop                            */  0x90,
> +  /* 00000053 nop                            */  0x90,
> +  /* 00000054 nop                            */  0x90,
> +  /* 00000055 nop                            */  0x90,
> +  /* 00000056 nop                            */  0x90,
> +  /* 00000057 nop                            */  0x90,
> +  /* 00000058 nop                            */  0x90,
> +  /* 00000059 nop                            */  0x90,
> +  /* 0000005A nop                            */  0x90,
> +  /* 0000005B nop                            */  0x90,
> +  /* 0000005C nop                            */  0x90,
> +  /* 0000005D nop                            */  0x90,
> +  /* 0000005E nop                            */  0x90,
> +  /* 0000005F nop                            */  0x90,
> +  /* 00000060 nop                            */  0x90,
> +  /* 00000061 nop                            */  0x90,
> +  /* 00000062 nop                            */  0x90,
> +  /* 00000063 nop                            */  0x90,
> +  /* 00000064 nop                            */  0x90,
> +  /* 00000065 nop                            */  0x90,
> +  /* 00000066 nop                            */  0x90,
> +  /* 00000067 nop                            */  0x90,
> +  /* 00000068 nop                            */  0x90,
> +  /* 00000069 nop                            */  0x90,
> +  /* 0000006A nop                            */  0x90,
> +  /* 0000006B nop                            */  0x90,
> +  /* 0000006C nop                            */  0x90,
> +  /* 0000006D nop                            */  0x90,
> +  /* 0000006E nop                            */  0x90,
> +  /* 0000006F nop                            */  0x90,
> +  /* 00000070 nop                            */  0x90,
> +  /* 00000071 nop                            */  0x90,
> +  /* 00000072 nop                            */  0x90,
> +  /* 00000073 nop                            */  0x90,
> +  /* 00000074 nop                            */  0x90,
> +  /* 00000075 nop                            */  0x90,
> +  /* 00000076 nop                            */  0x90,
> +  /* 00000077 nop                            */  0x90,
> +  /* 00000078 nop                            */  0x90,
> +  /* 00000079 nop                            */  0x90,
> +  /* 0000007A nop                            */  0x90,
> +  /* 0000007B nop                            */  0x90,
> +  /* 0000007C nop                            */  0x90,
> +  /* 0000007D nop                            */  0x90,
> +  /* 0000007E nop                            */  0x90,
> +  /* 0000007F nop                            */  0x90,
> +  /* 00000080 nop                            */  0x90,
> +  /* 00000081 nop                            */  0x90,
> +  /* 00000082 nop                            */  0x90,
> +  /* 00000083 nop                            */  0x90,
> +  /* 00000084 nop                            */  0x90,
> +  /* 00000085 nop                            */  0x90,
> +  /* 00000086 nop                            */  0x90,
> +  /* 00000087 nop                            */  0x90,
> +  /* 00000088 nop                            */  0x90,
> +  /* 00000089 nop                            */  0x90,
> +  /* 0000008A nop                            */  0x90,
> +  /* 0000008B nop                            */  0x90,
> +  /* 0000008C nop                            */  0x90,
> +  /* 0000008D nop                            */  0x90,
> +  /* 0000008E nop                            */  0x90,
> +  /* 0000008F nop                            */  0x90,
> +  /* 00000090 nop                            */  0x90,
> +  /* 00000091 nop                            */  0x90,
> +  /* 00000092 nop                            */  0x90,
> +  /* 00000093 nop                            */  0x90,
> +  /* 00000094 nop                            */  0x90,
> +  /* 00000095 nop                            */  0x90,
> +  /* 00000096 nop                            */  0x90,
> +  /* 00000097 nop                            */  0x90,
> +  /* 00000098 nop                            */  0x90,
> +  /* 00000099 nop                            */  0x90,
> +  /* 0000009A nop                            */  0x90,
> +  /* 0000009B nop                            */  0x90,
> +  /* 0000009C nop                            */  0x90,
> +  /* 0000009D nop                            */  0x90,
> +  /* 0000009E nop                            */  0x90,
> +  /* 0000009F nop                            */  0x90,
> +  /* 000000A0 nop                            */  0x90,
> +  /* 000000A1 nop                            */  0x90,
> +  /* 000000A2 nop                            */  0x90,
> +  /* 000000A3 nop                            */  0x90,
> +  /* 000000A4 nop                            */  0x90,
> +  /* 000000A5 nop                            */  0x90,
> +  /* 000000A6 nop                            */  0x90,
> +  /* 000000A7 nop                            */  0x90,
> +  /* 000000A8 nop                            */  0x90,
> +  /* 000000A9 nop                            */  0x90,
> +  /* 000000AA nop                            */  0x90,
> +  /* 000000AB nop                            */  0x90,
> +  /* 000000AC nop                            */  0x90,
> +  /* 000000AD nop                            */  0x90,
> +  /* 000000AE nop                            */  0x90,
> +  /* 000000AF nop                            */  0x90,
> +  /* 000000B0 nop                            */  0x90,
> +  /* 000000B1 nop                            */  0x90,
> +  /* 000000B2 nop                            */  0x90,
> +  /* 000000B3 nop                            */  0x90,
> +  /* 000000B4 nop                            */  0x90,
> +  /* 000000B5 nop                            */  0x90,
> +  /* 000000B6 nop                            */  0x90,
> +  /* 000000B7 nop                            */  0x90,
> +  /* 000000B8 nop                            */  0x90,
> +  /* 000000B9 nop                            */  0x90,
> +  /* 000000BA nop                            */  0x90,
> +  /* 000000BB nop                            */  0x90,
> +  /* 000000BC nop                            */  0x90,
> +  /* 000000BD nop                            */  0x90,
> +  /* 000000BE nop                            */  0x90,
> +  /* 000000BF nop                            */  0x90,
> +  /* 000000C0 nop                            */  0x90,
> +  /* 000000C1 nop                            */  0x90,
> +  /* 000000C2 nop                            */  0x90,
> +  /* 000000C3 nop                            */  0x90,
> +  /* 000000C4 nop                            */  0x90,
> +  /* 000000C5 nop                            */  0x90,
> +  /* 000000C6 nop                            */  0x90,
> +  /* 000000C7 nop                            */  0x90,
> +  /* 000000C8 nop                            */  0x90,
> +  /* 000000C9 nop                            */  0x90,
> +  /* 000000CA nop                            */  0x90,
> +  /* 000000CB nop                            */  0x90,
> +  /* 000000CC nop                            */  0x90,
> +  /* 000000CD nop                            */  0x90,
> +  /* 000000CE nop                            */  0x90,
> +  /* 000000CF nop                            */  0x90,
> +  /* 000000D0 nop                            */  0x90,
> +  /* 000000D1 nop                            */  0x90,
> +  /* 000000D2 nop                            */  0x90,
> +  /* 000000D3 nop                            */  0x90,
> +  /* 000000D4 nop                            */  0x90,
> +  /* 000000D5 nop                            */  0x90,
> +  /* 000000D6 nop                            */  0x90,
> +  /* 000000D7 nop                            */  0x90,
> +  /* 000000D8 nop                            */  0x90,
> +  /* 000000D9 nop                            */  0x90,
> +  /* 000000DA nop                            */  0x90,
> +  /* 000000DB nop                            */  0x90,
> +  /* 000000DC nop                            */  0x90,
> +  /* 000000DD nop                            */  0x90,
> +  /* 000000DE nop                            */  0x90,
> +  /* 000000DF nop                            */  0x90,
> +  /* 000000E0 nop                            */  0x90,
> +  /* 000000E1 nop                            */  0x90,
> +  /* 000000E2 nop                            */  0x90,
> +  /* 000000E3 nop                            */  0x90,
> +  /* 000000E4 nop                            */  0x90,
> +  /* 000000E5 nop                            */  0x90,
> +  /* 000000E6 nop                            */  0x90,
> +  /* 000000E7 nop                            */  0x90,
> +  /* 000000E8 nop                            */  0x90,
> +  /* 000000E9 nop                            */  0x90,
> +  /* 000000EA nop                            */  0x90,
> +  /* 000000EB nop                            */  0x90,
> +  /* 000000EC nop                            */  0x90,
> +  /* 000000ED nop                            */  0x90,
> +  /* 000000EE nop                            */  0x90,
> +  /* 000000EF nop                            */  0x90,
> +  /* 000000F0 nop                            */  0x90,
> +  /* 000000F1 nop                            */  0x90,
> +  /* 000000F2 nop                            */  0x90,
> +  /* 000000F3 nop                            */  0x90,
> +  /* 000000F4 nop                            */  0x90,
> +  /* 000000F5 nop                            */  0x90,
> +  /* 000000F6 nop                            */  0x90,
> +  /* 000000F7 nop                            */  0x90,
> +  /* 000000F8 nop                            */  0x90,
> +  /* 000000F9 nop                            */  0x90,
> +  /* 000000FA nop                            */  0x90,
> +  /* 000000FB nop                            */  0x90,
> +  /* 000000FC nop                            */  0x90,
> +  /* 000000FD nop                            */  0x90,
> +  /* 000000FE nop                            */  0x90,
> +  /* 000000FF nop                            */  0x90,
> +  /* 00000100 nop                            */  0x90,
> +  /* 00000101 nop                            */  0x90,
> +  /* 00000102 nop                            */  0x90,
> +  /* 00000103 nop                            */  0x90,
> +  /* 00000104 nop                            */  0x90,
> +  /* 00000105 nop                            */  0x90,
> +  /* 00000106 nop                            */  0x90,
> +  /* 00000107 nop                            */  0x90,
> +  /* 00000108 nop                            */  0x90,
> +  /* 00000109 nop                            */  0x90,
> +  /* 0000010A nop                            */  0x90,
> +  /* 0000010B nop                            */  0x90,
> +  /* 0000010C nop                            */  0x90,
> +  /* 0000010D nop                            */  0x90,
> +  /* 0000010E nop                            */  0x90,
> +  /* 0000010F nop                            */  0x90,
> +  /* 00000110 nop                            */  0x90,
> +  /* 00000111 nop                            */  0x90,
> +  /* 00000112 nop                            */  0x90,
> +  /* 00000113 nop                            */  0x90,
> +  /* 00000114 nop                            */  0x90,
> +  /* 00000115 nop                            */  0x90,
> +  /* 00000116 nop                            */  0x90,
> +  /* 00000117 nop                            */  0x90,
> +  /* 00000118 nop                            */  0x90,
> +  /* 00000119 nop                            */  0x90,
> +  /* 0000011A nop                            */  0x90,
> +  /* 0000011B nop                            */  0x90,
> +  /* 0000011C nop                            */  0x90,
> +  /* 0000011D nop                            */  0x90,
> +  /* 0000011E nop                            */  0x90,
> +  /* 0000011F nop                            */  0x90,
> +  /* 00000120 nop                            */  0x90,
> +  /* 00000121 nop                            */  0x90,
> +  /* 00000122 nop                            */  0x90,
> +  /* 00000123 nop                            */  0x90,
> +  /* 00000124 nop                            */  0x90,
> +  /* 00000125 nop                            */  0x90,
> +  /* 00000126 nop                            */  0x90,
> +  /* 00000127 nop                            */  0x90,
> +  /* 00000128 nop                            */  0x90,
> +  /* 00000129 nop                            */  0x90,
> +  /* 0000012A nop                            */  0x90,
> +  /* 0000012B nop                            */  0x90,
> +  /* 0000012C nop                            */  0x90,
> +  /* 0000012D nop                            */  0x90,
> +  /* 0000012E nop                            */  0x90,
> +  /* 0000012F nop                            */  0x90,
> +  /* 00000130 nop                            */  0x90,
> +  /* 00000131 nop                            */  0x90,
> +  /* 00000132 nop                            */  0x90,
> +  /* 00000133 nop                            */  0x90,
> +  /* 00000134 nop                            */  0x90,
> +  /* 00000135 nop                            */  0x90,
> +  /* 00000136 nop                            */  0x90,
> +  /* 00000137 nop                            */  0x90,
> +  /* 00000138 nop                            */  0x90,
> +  /* 00000139 nop                            */  0x90,
> +  /* 0000013A nop                            */  0x90,
> +  /* 0000013B nop                            */  0x90,
> +  /* 0000013C nop                            */  0x90,
> +  /* 0000013D nop                            */  0x90,
> +  /* 0000013E nop                            */  0x90,
> +  /* 0000013F nop                            */  0x90,
> +  /* 00000140 nop                            */  0x90,
> +  /* 00000141 nop                            */  0x90,
> +  /* 00000142 nop                            */  0x90,
> +  /* 00000143 nop                            */  0x90,
> +  /* 00000144 nop                            */  0x90,
> +  /* 00000145 nop                            */  0x90,
> +  /* 00000146 nop                            */  0x90,
> +  /* 00000147 nop                            */  0x90,
> +  /* 00000148 nop                            */  0x90,
> +  /* 00000149 nop                            */  0x90,
> +  /* 0000014A nop                            */  0x90,
> +  /* 0000014B nop                            */  0x90,
> +  /* 0000014C nop                            */  0x90,
> +  /* 0000014D nop                            */  0x90,
> +  /* 0000014E nop                            */  0x90,
> +  /* 0000014F nop                            */  0x90,
> +  /* 00000150 nop                            */  0x90,
> +  /* 00000151 nop                            */  0x90,
> +  /* 00000152 nop                            */  0x90,
> +  /* 00000153 nop                            */  0x90,
> +  /* 00000154 nop                            */  0x90,
> +  /* 00000155 nop                            */  0x90,
> +  /* 00000156 nop                            */  0x90,
> +  /* 00000157 nop                            */  0x90,
> +  /* 00000158 nop                            */  0x90,
> +  /* 00000159 nop                            */  0x90,
> +  /* 0000015A nop                            */  0x90,
> +  /* 0000015B nop                            */  0x90,
> +  /* 0000015C nop                            */  0x90,
> +  /* 0000015D nop                            */  0x90,
> +  /* 0000015E nop                            */  0x90,
> +  /* 0000015F nop                            */  0x90,
> +  /* 00000160 nop                            */  0x90,
> +  /* 00000161 nop                            */  0x90,
> +  /* 00000162 nop                            */  0x90,
> +  /* 00000163 nop                            */  0x90,
> +  /* 00000164 nop                            */  0x90,
> +  /* 00000165 nop                            */  0x90,
> +  /* 00000166 nop                            */  0x90,
> +  /* 00000167 nop                            */  0x90,
> +  /* 00000168 nop                            */  0x90,
> +  /* 00000169 nop                            */  0x90,
> +  /* 0000016A nop                            */  0x90,
> +  /* 0000016B nop                            */  0x90,
> +  /* 0000016C nop                            */  0x90,
> +  /* 0000016D nop                            */  0x90,
> +  /* 0000016E nop                            */  0x90,
> +  /* 0000016F nop                            */  0x90,
> +  /* 00000170 nop                            */  0x90,
> +  /* 00000171 nop                            */  0x90,
> +  /* 00000172 nop                            */  0x90,
> +  /* 00000173 nop                            */  0x90,
> +  /* 00000174 nop                            */  0x90,
> +  /* 00000175 nop                            */  0x90,
> +  /* 00000176 nop                            */  0x90,
> +  /* 00000177 nop                            */  0x90,
> +  /* 00000178 nop                            */  0x90,
> +  /* 00000179 nop                            */  0x90,
> +  /* 0000017A nop                            */  0x90,
> +  /* 0000017B nop                            */  0x90,
> +  /* 0000017C nop                            */  0x90,
> +  /* 0000017D nop                            */  0x90,
> +  /* 0000017E nop                            */  0x90,
> +  /* 0000017F nop                            */  0x90,
> +  /* 00000180 nop                            */  0x90,
> +  /* 00000181 nop                            */  0x90,
> +  /* 00000182 nop                            */  0x90,
> +  /* 00000183 nop                            */  0x90,
> +  /* 00000184 nop                            */  0x90,
> +  /* 00000185 nop                            */  0x90,
> +  /* 00000186 nop                            */  0x90,
> +  /* 00000187 nop                            */  0x90,
> +  /* 00000188 nop                            */  0x90,
> +  /* 00000189 nop                            */  0x90,
> +  /* 0000018A nop                            */  0x90,
> +  /* 0000018B nop                            */  0x90,
> +  /* 0000018C nop                            */  0x90,
> +  /* 0000018D nop                            */  0x90,
> +  /* 0000018E nop                            */  0x90,
> +  /* 0000018F nop                            */  0x90,
> +  /* 00000190 nop                            */  0x90,
> +  /* 00000191 nop                            */  0x90,
> +  /* 00000192 nop                            */  0x90,
> +  /* 00000193 nop                            */  0x90,
> +  /* 00000194 nop                            */  0x90,
> +  /* 00000195 nop                            */  0x90,
> +  /* 00000196 nop                            */  0x90,
> +  /* 00000197 nop                            */  0x90,
> +  /* 00000198 nop                            */  0x90,
> +  /* 00000199 nop                            */  0x90,
> +  /* 0000019A nop                            */  0x90,
> +  /* 0000019B nop                            */  0x90,
> +  /* 0000019C nop                            */  0x90,
> +  /* 0000019D nop                            */  0x90,
> +  /* 0000019E nop                            */  0x90,
> +  /* 0000019F nop                            */  0x90,
> +  /* 000001A0 nop                            */  0x90,
> +  /* 000001A1 nop                            */  0x90,
> +  /* 000001A2 nop                            */  0x90,
> +  /* 000001A3 nop                            */  0x90,
> +  /* 000001A4 nop                            */  0x90,
> +  /* 000001A5 nop                            */  0x90,
> +  /* 000001A6 nop                            */  0x90,
> +  /* 000001A7 nop                            */  0x90,
> +  /* 000001A8 nop                            */  0x90,
> +  /* 000001A9 nop                            */  0x90,
> +  /* 000001AA nop                            */  0x90,
> +  /* 000001AB nop                            */  0x90,
> +  /* 000001AC nop                            */  0x90,
> +  /* 000001AD nop                            */  0x90,
> +  /* 000001AE nop                            */  0x90,
> +  /* 000001AF nop                            */  0x90,
> +  /* 000001B0 nop                            */  0x90,
> +  /* 000001B1 nop                            */  0x90,
> +  /* 000001B2 nop                            */  0x90,
> +  /* 000001B3 nop                            */  0x90,
> +  /* 000001B4 nop                            */  0x90,
> +  /* 000001B5 nop                            */  0x90,
> +  /* 000001B6 nop                            */  0x90,
> +  /* 000001B7 nop                            */  0x90,
> +  /* 000001B8 nop                            */  0x90,
> +  /* 000001B9 nop                            */  0x90,
> +  /* 000001BA nop                            */  0x90,
> +  /* 000001BB nop                            */  0x90,
> +  /* 000001BC nop                            */  0x90,
> +  /* 000001BD nop                            */  0x90,
> +  /* 000001BE nop                            */  0x90,
> +  /* 000001BF nop                            */  0x90,
> +  /* 000001C0 nop                            */  0x90,
> +  /* 000001C1 nop                            */  0x90,
> +  /* 000001C2 nop                            */  0x90,
> +  /* 000001C3 nop                            */  0x90,
> +  /* 000001C4 nop                            */  0x90,
> +  /* 000001C5 nop                            */  0x90,
> +  /* 000001C6 nop                            */  0x90,
> +  /* 000001C7 nop                            */  0x90,
> +  /* 000001C8 nop                            */  0x90,
> +  /* 000001C9 nop                            */  0x90,
> +  /* 000001CA nop                            */  0x90,
> +  /* 000001CB nop                            */  0x90,
> +  /* 000001CC nop                            */  0x90,
> +  /* 000001CD nop                            */  0x90,
> +  /* 000001CE nop                            */  0x90,
> +  /* 000001CF nop                            */  0x90,
> +  /* 000001D0 nop                            */  0x90,
> +  /* 000001D1 nop                            */  0x90,
> +  /* 000001D2 nop                            */  0x90,
> +  /* 000001D3 nop                            */  0x90,
> +  /* 000001D4 nop                            */  0x90,
> +  /* 000001D5 nop                            */  0x90,
> +  /* 000001D6 nop                            */  0x90,
> +  /* 000001D7 nop                            */  0x90,
> +  /* 000001D8 nop                            */  0x90,
> +  /* 000001D9 nop                            */  0x90,
> +  /* 000001DA nop                            */  0x90,
> +  /* 000001DB nop                            */  0x90,
> +  /* 000001DC nop                            */  0x90,
> +  /* 000001DD nop                            */  0x90,
> +  /* 000001DE nop                            */  0x90,
> +  /* 000001DF nop                            */  0x90,
> +  /* 000001E0 nop                            */  0x90,
> +  /* 000001E1 nop                            */  0x90,
> +  /* 000001E2 nop                            */  0x90,
> +  /* 000001E3 nop                            */  0x90,
> +  /* 000001E4 nop                            */  0x90,
> +  /* 000001E5 nop                            */  0x90,
> +  /* 000001E6 nop                            */  0x90,
> +  /* 000001E7 nop                            */  0x90,
> +  /* 000001E8 nop                            */  0x90,
> +  /* 000001E9 nop                            */  0x90,
> +  /* 000001EA nop                            */  0x90,
> +  /* 000001EB nop                            */  0x90,
> +  /* 000001EC nop                            */  0x90,
> +  /* 000001ED nop                            */  0x90,
> +  /* 000001EE nop                            */  0x90,
> +  /* 000001EF nop                            */  0x90,
> +  /* 000001F0 nop                            */  0x90,
> +  /* 000001F1 nop                            */  0x90,
> +  /* 000001F2 nop                            */  0x90,
> +  /* 000001F3 nop                            */  0x90,
> +  /* 000001F4 nop                            */  0x90,
> +  /* 000001F5 nop                            */  0x90,
> +  /* 000001F6 nop                            */  0x90,
> +  /* 000001F7 nop                            */  0x90,
> +  /* 000001F8 nop                            */  0x90,
> +  /* 000001F9 nop                            */  0x90,
> +  /* 000001FA nop                            */  0x90,
> +  /* 000001FB nop                            */  0x90,
> +  /* 000001FC nop                            */  0x90,
> +  /* 000001FD nop                            */  0x90,
> +  /* 000001FE nop                            */  0x90,
> +  /* 000001FF nop                            */  0x90,
> +  /* 00000200 cmp ax,0x4f00                  */  0x3D, 0x00, 0x4F,
> +  /* 00000203 jz 0x22d                       */  0x74, 0x28,
> +  /* 00000205 cmp ax,0x4f01                  */  0x3D, 0x01, 0x4F,
> +  /* 00000208 jz 0x245                       */  0x74, 0x3B,
> +  /* 0000020A cmp ax,0x4f02                  */  0x3D, 0x02, 0x4F,
> +  /* 0000020D jz 0x269                       */  0x74, 0x5A,
> +  /* 0000020F cmp ax,0x4f03                  */  0x3D, 0x03, 0x4F,
> +  /* 00000212 jz word 0x331                  */  0x0F, 0x84, 0x1B, 0x01,
> +  /* 00000216 cmp ax,0x4f10                  */  0x3D, 0x10, 0x4F,
> +  /* 00000219 jz word 0x336                  */  0x0F, 0x84, 0x19, 0x01,
> +  /* 0000021D cmp ax,0x4f15                  */  0x3D, 0x15, 0x4F,
> +  /* 00000220 jz word 0x338                  */  0x0F, 0x84, 0x14, 0x01,
> +  /* 00000224 cmp ah,0x0                     */  0x80, 0xFC, 0x00,
> +  /* 00000227 jz word 0x33a                  */  0x0F, 0x84, 0x0F, 0x01,
> +  /* 0000022B jmp short 0x22b                */  0xEB, 0xFE,
> +  /* 0000022D push es                        */  0x06,
> +  /* 0000022E push di                        */  0x57,
> +  /* 0000022F push ds                        */  0x1E,
> +  /* 00000230 push si                        */  0x56,
> +  /* 00000231 push cx                        */  0x51,
> +  /* 00000232 push cs                        */  0x0E,
> +  /* 00000233 pop ds                         */  0x1F,
> +  /* 00000234 mov si,0x0                     */  0xBE, 0x00, 0x00,
> +  /* 00000237 mov cx,0x100                   */  0xB9, 0x00, 0x01,
> +  /* 0000023A cld                            */  0xFC,
> +  /* 0000023B rep movsb                      */  0xF3, 0xA4,
> +  /* 0000023D pop cx                         */  0x59,
> +  /* 0000023E pop si                         */  0x5E,
> +  /* 0000023F pop ds                         */  0x1F,
> +  /* 00000240 pop di                         */  0x5F,
> +  /* 00000241 pop es                         */  0x07,
> +  /* 00000242 jmp word 0x34c                 */  0xE9, 0x07, 0x01,
> +  /* 00000245 push es                        */  0x06,
> +  /* 00000246 push di                        */  0x57,
> +  /* 00000247 push ds                        */  0x1E,
> +  /* 00000248 push si                        */  0x56,
> +  /* 00000249 push cx                        */  0x51,
> +  /* 0000024A and cx,0xbfff                  */  0x81, 0xE1, 0xFF, 0xBF,
> +  /* 0000024E cmp cx,0xf1                    */  0x81, 0xF9, 0xF1, 0x00,
> +  /* 00000252 jz 0x256                       */  0x74, 0x02,
> +  /* 00000254 jmp short 0x22b                */  0xEB, 0xD5,
> +  /* 00000256 push cs                        */  0x0E,
> +  /* 00000257 pop ds                         */  0x1F,
> +  /* 00000258 mov si,0x100                   */  0xBE, 0x00, 0x01,
> +  /* 0000025B mov cx,0x100                   */  0xB9, 0x00, 0x01,
> +  /* 0000025E cld                            */  0xFC,
> +  /* 0000025F rep movsb                      */  0xF3, 0xA4,
> +  /* 00000261 pop cx                         */  0x59,
> +  /* 00000262 pop si                         */  0x5E,
> +  /* 00000263 pop ds                         */  0x1F,
> +  /* 00000264 pop di                         */  0x5F,
> +  /* 00000265 pop es                         */  0x07,
> +  /* 00000266 jmp word 0x34c                 */  0xE9, 0xE3, 0x00,
> +  /* 00000269 push dx                        */  0x52,
> +  /* 0000026A push ax                        */  0x50,
> +  /* 0000026B cmp bx,0x40f1                  */  0x81, 0xFB, 0xF1, 0x40,
> +  /* 0000026F jz 0x273                       */  0x74, 0x02,
> +  /* 00000271 jmp short 0x22b                */  0xEB, 0xB8,
> +  /* 00000273 mov dx,0x3c0                   */  0xBA, 0xC0, 0x03,
> +  /* 00000276 mov al,0x20                    */  0xB0, 0x20,
> +  /* 00000278 out dx,al                      */  0xEE,
> +  /* 00000279 push dx                        */  0x52,
> +  /* 0000027A push ax                        */  0x50,
> +  /* 0000027B mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 0000027E mov ax,0x4                     */  0xB8, 0x04, 0x00,
> +  /* 00000281 out dx,ax                      */  0xEF,
> +  /* 00000282 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 00000285 mov ax,0x0                     */  0xB8, 0x00, 0x00,
> +  /* 00000288 out dx,ax                      */  0xEF,
> +  /* 00000289 pop ax                         */  0x58,
> +  /* 0000028A pop dx                         */  0x5A,
> +  /* 0000028B push dx                        */  0x52,
> +  /* 0000028C push ax                        */  0x50,
> +  /* 0000028D mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 00000290 mov ax,0x5                     */  0xB8, 0x05, 0x00,
> +  /* 00000293 out dx,ax                      */  0xEF,
> +  /* 00000294 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 00000297 mov ax,0x0                     */  0xB8, 0x00, 0x00,
> +  /* 0000029A out dx,ax                      */  0xEF,
> +  /* 0000029B pop ax                         */  0x58,
> +  /* 0000029C pop dx                         */  0x5A,
> +  /* 0000029D push dx                        */  0x52,
> +  /* 0000029E push ax                        */  0x50,
> +  /* 0000029F mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 000002A2 mov ax,0x8                     */  0xB8, 0x08, 0x00,
> +  /* 000002A5 out dx,ax                      */  0xEF,
> +  /* 000002A6 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 000002A9 mov ax,0x0                     */  0xB8, 0x00, 0x00,
> +  /* 000002AC out dx,ax                      */  0xEF,
> +  /* 000002AD pop ax                         */  0x58,
> +  /* 000002AE pop dx                         */  0x5A,
> +  /* 000002AF push dx                        */  0x52,
> +  /* 000002B0 push ax                        */  0x50,
> +  /* 000002B1 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 000002B4 mov ax,0x9                     */  0xB8, 0x09, 0x00,
> +  /* 000002B7 out dx,ax                      */  0xEF,
> +  /* 000002B8 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 000002BB mov ax,0x0                     */  0xB8, 0x00, 0x00,
> +  /* 000002BE out dx,ax                      */  0xEF,
> +  /* 000002BF pop ax                         */  0x58,
> +  /* 000002C0 pop dx                         */  0x5A,
> +  /* 000002C1 push dx                        */  0x52,
> +  /* 000002C2 push ax                        */  0x50,
> +  /* 000002C3 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 000002C6 mov ax,0x3                     */  0xB8, 0x03, 0x00,
> +  /* 000002C9 out dx,ax                      */  0xEF,
> +  /* 000002CA mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 000002CD mov ax,0x20                    */  0xB8, 0x20, 0x00,
> +  /* 000002D0 out dx,ax                      */  0xEF,
> +  /* 000002D1 pop ax                         */  0x58,
> +  /* 000002D2 pop dx                         */  0x5A,
> +  /* 000002D3 push dx                        */  0x52,
> +  /* 000002D4 push ax                        */  0x50,
> +  /* 000002D5 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 000002D8 mov ax,0x1                     */  0xB8, 0x01, 0x00,
> +  /* 000002DB out dx,ax                      */  0xEF,
> +  /* 000002DC mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 000002DF mov ax,0x400                   */  0xB8, 0x00, 0x04,
> +  /* 000002E2 out dx,ax                      */  0xEF,
> +  /* 000002E3 pop ax                         */  0x58,
> +  /* 000002E4 pop dx                         */  0x5A,
> +  /* 000002E5 push dx                        */  0x52,
> +  /* 000002E6 push ax                        */  0x50,
> +  /* 000002E7 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 000002EA mov ax,0x6                     */  0xB8, 0x06, 0x00,
> +  /* 000002ED out dx,ax                      */  0xEF,
> +  /* 000002EE mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 000002F1 mov ax,0x400                   */  0xB8, 0x00, 0x04,
> +  /* 000002F4 out dx,ax                      */  0xEF,
> +  /* 000002F5 pop ax                         */  0x58,
> +  /* 000002F6 pop dx                         */  0x5A,
> +  /* 000002F7 push dx                        */  0x52,
> +  /* 000002F8 push ax                        */  0x50,
> +  /* 000002F9 mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 000002FC mov ax,0x2                     */  0xB8, 0x02, 0x00,
> +  /* 000002FF out dx,ax                      */  0xEF,
> +  /* 00000300 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 00000303 mov ax,0x300                   */  0xB8, 0x00, 0x03,
> +  /* 00000306 out dx,ax                      */  0xEF,
> +  /* 00000307 pop ax                         */  0x58,
> +  /* 00000308 pop dx                         */  0x5A,
> +  /* 00000309 push dx                        */  0x52,
> +  /* 0000030A push ax                        */  0x50,
> +  /* 0000030B mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 0000030E mov ax,0x7                     */  0xB8, 0x07, 0x00,
> +  /* 00000311 out dx,ax                      */  0xEF,
> +  /* 00000312 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 00000315 mov ax,0x300                   */  0xB8, 0x00, 0x03,
> +  /* 00000318 out dx,ax                      */  0xEF,
> +  /* 00000319 pop ax                         */  0x58,
> +  /* 0000031A pop dx                         */  0x5A,
> +  /* 0000031B push dx                        */  0x52,
> +  /* 0000031C push ax                        */  0x50,
> +  /* 0000031D mov dx,0x1ce                   */  0xBA, 0xCE, 0x01,
> +  /* 00000320 mov ax,0x4                     */  0xB8, 0x04, 0x00,
> +  /* 00000323 out dx,ax                      */  0xEF,
> +  /* 00000324 mov dx,0x1d0                   */  0xBA, 0xD0, 0x01,
> +  /* 00000327 mov ax,0x41                    */  0xB8, 0x41, 0x00,
> +  /* 0000032A out dx,ax                      */  0xEF,
> +  /* 0000032B pop ax                         */  0x58,
> +  /* 0000032C pop dx                         */  0x5A,
> +  /* 0000032D pop ax                         */  0x58,
> +  /* 0000032E pop dx                         */  0x5A,
> +  /* 0000032F jmp short 0x34c                */  0xEB, 0x1B,
> +  /* 00000331 mov bx,0x40f1                  */  0xBB, 0xF1, 0x40,
> +  /* 00000334 jmp short 0x34c                */  0xEB, 0x16,
> +  /* 00000336 jmp short 0x350                */  0xEB, 0x18,
> +  /* 00000338 jmp short 0x350                */  0xEB, 0x16,
> +  /* 0000033A cmp al,0x3                     */  0x3C, 0x03,
> +  /* 0000033C jz 0x345                       */  0x74, 0x07,
> +  /* 0000033E cmp al,0x12                    */  0x3C, 0x12,
> +  /* 00000340 jz 0x349                       */  0x74, 0x07,
> +  /* 00000342 jmp word 0x22b                 */  0xE9, 0xE6, 0xFE,
> +  /* 00000345 mov al,0x30                    */  0xB0, 0x30,
> +  /* 00000347 jmp short 0x34b                */  0xEB, 0x02,
> +  /* 00000349 mov al,0x20                    */  0xB0, 0x20,
> +  /* 0000034B iretw                          */  0xCF,
> +  /* 0000034C mov ax,0x4f                    */  0xB8, 0x4F, 0x00,
> +  /* 0000034F iretw                          */  0xCF,
> +  /* 00000350 mov ax,0x14f                   */  0xB8, 0x4F, 0x01,
> +  /* 00000353 iretw                          */  0xCF,
> +};
> +#endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.sh
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.sh
> new file mode 100644
> index 0000000000..7669f8a219
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/OvmfPkg/QemuVideoDxe/Vb
> eShim.sh
> @@ -0,0 +1,79 @@
> +#!/bin/sh
> +###
> +# @file
> +# Shell script to assemble and dump the fake Int10h handler from NASM
> source to
> +# a C array.
> +#
> +# Copyright (C) 2014, Red Hat, Inc.
> +# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +###
> +
> +set -e -u
> +
> +STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
> +
> +#
> +# Install exit handler -- remove temporary files.
> +#
> +exit_handler()
> +{
> +  rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
> +      "$STEM".bytes
> +}
> +trap exit_handler EXIT
> +
> +#
> +# Assemble the source file.
> +#
> +nasm -o "$STEM".bin -- "$STEM".asm
> +
> +#
> +# Disassemble it, in order to get a binary dump associated with the source.
> +# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
> +#
> +ndisasm "$STEM".bin >"$STEM".disasm
> +
> +#
> +# Create three files, each with one column of the disassembly.
> +#
> +# The first column contains the offsets, and it starts the comment.
> +#
> +cut -c 1-8 -- "$STEM".disasm \
> +| sed -e 's,^,  /* ,' >"$STEM".offsets
> +
> +#
> +# The second column contains the assembly-language instructions, and it closes
> +# the comment. We first pad it to 30 characters.
> +#
> +cut -c 29- -- "$STEM".disasm \
> +| sed -e 's,$,                              ,' \
> +      -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
> +
> +#
> +# The third column contains the bytes corresponding to the instruction,
> +# represented as C integer constants. First strip trailing whitespace from the
> +# middle column of the input disassembly, then process pairs of nibbles.
> +#
> +cut -c 11-28 -- "$STEM".disasm \
> +| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' >"$STEM".bytes
> +
> +#
> +# Write the output file, recombining the columns. The output should have CRLF
> +# line endings.
> +#
> +{
> +  printf '//\n'
> +  printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
> +      "$(basename -- "$0")"
> +  printf '//\n'
> +  printf '#ifndef _VBE_SHIM_H_\n'
> +  printf '#define _VBE_SHIM_H_\n'
> +  printf 'STATIC CONST UINT8 mVbeShim[] = {\n'
> +  paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
> +  printf '};\n'
> +  printf '#endif\n'
> +} \
> +| unix2dos >"$STEM".h
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.h
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.h
> new file mode 100644
> index 0000000000..a9673f9c87
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.h
> @@ -0,0 +1,218 @@
> +/** @file
> +  Driver implementing the Tiano Legacy 8259 Protocol
> +
> +Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _8259_H__
> +#define _8259_H__
> +
> +#include <Protocol/Legacy8259.h>
> +#include <Protocol/PciIo.h>
> +
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +
> +#include <IndustryStandard/Pci.h>
> +
> +// 8259 Hardware definitions
> +
> +#define LEGACY_MODE_BASE_VECTOR_MASTER                    0x08
> +#define LEGACY_MODE_BASE_VECTOR_SLAVE                     0x70
> +
> +#define PROTECTED_MODE_BASE_VECTOR_MASTER                 0x68
> +#define PROTECTED_MODE_BASE_VECTOR_SLAVE                  0x70
> +
> +#define LEGACY_8259_CONTROL_REGISTER_MASTER               0x20
> +#define LEGACY_8259_MASK_REGISTER_MASTER                  0x21
> +#define LEGACY_8259_CONTROL_REGISTER_SLAVE                0xA0
> +#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
> +
> +#define LEGACY_8259_EOI                                   0x20
> +
> +// Protocol Function Prototypes
> +
> +/**
> +  Sets the base address for the 8259 master and slave PICs.
> +
> +  @param[in]  This        Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  MasterBase  Interrupt vectors for IRQ0-IRQ7.
> +  @param[in]  SlaveBase   Interrupt vectors for IRQ8-IRQ15.
> +
> +  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
> +  @retval  EFI_DEVICE_ERROR  There was an error while writing to the 8259
> PIC.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259SetVectorBase (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN UINT8                     MasterBase,
> +  IN UINT8                     SlaveBase
> +  );
> +
> +/**
> +  Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
> +
> +  @param[in]   This                Indicates the EFI_LEGACY_8259_PROTOCOL
> instance.
> +  @param[out]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
> +  @param[out]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-
> IRQ15.
> +  @param[out]  ProtectedMask       32-bit mode interrupt mask for IRQ0-
> IRQ15.
> +  @param[out]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-
> IRQ15.
> +
> +  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
> +  @retval  EFI_DEVICE_ERROR  There was an error while reading the 8259 PIC.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259GetMask (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  OUT UINT16                    *LegacyMask, OPTIONAL
> +  OUT UINT16                    *LegacyEdgeLevel, OPTIONAL
> +  OUT UINT16                    *ProtectedMask, OPTIONAL
> +  OUT UINT16                    *ProtectedEdgeLevel OPTIONAL
> +  );
> +
> +/**
> +  Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks.
> +
> +  @param[in]  This                Indicates the EFI_LEGACY_8259_PROTOCOL
> instance.
> +  @param[in]  LegacyMask          16-bit mode interrupt mask for IRQ0-IRQ15.
> +  @param[in]  LegacyEdgeLevel     16-bit mode edge/level mask for IRQ-IRQ15.
> +  @param[in]  ProtectedMask       32-bit mode interrupt mask for IRQ0-IRQ15.
> +  @param[in]  ProtectedEdgeLevel  32-bit mode edge/level mask for IRQ0-
> IRQ15.
> +
> +  @retval  EFI_SUCCESS       The 8259 PIC was programmed successfully.
> +  @retval  EFI_DEVICE_ERROR  There was an error while writing the 8259 PIC.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259SetMask (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN UINT16                    *LegacyMask, OPTIONAL
> +  IN UINT16                    *LegacyEdgeLevel, OPTIONAL
> +  IN UINT16                    *ProtectedMask, OPTIONAL
> +  IN UINT16                    *ProtectedEdgeLevel OPTIONAL
> +  );
> +
> +/**
> +  Sets the mode of the PICs.
> +
> +  @param[in]  This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Mode       16-bit real or 32-bit protected mode.
> +  @param[in]  Mask       The value with which to set the interrupt mask.
> +  @param[in]  EdgeLevel  The value with which to set the edge/level mask.
> +
> +  @retval  EFI_SUCCESS            The mode was set successfully.
> +  @retval  EFI_INVALID_PARAMETER  The mode was not set.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259SetMode (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_MODE             Mode,
> +  IN UINT16                    *Mask, OPTIONAL
> +  IN UINT16                    *EdgeLevel OPTIONAL
> +  );
> +
> +/**
> +  Translates the IRQ into a vector.
> +
> +  @param[in]   This    Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]   Irq     IRQ0-IRQ15.
> +  @param[out]  Vector  The vector that is assigned to the IRQ.
> +
> +  @retval  EFI_SUCCESS            The Vector that matches Irq was returned.
> +  @retval  EFI_INVALID_PARAMETER  Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259GetVector (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN  EFI_8259_IRQ              Irq,
> +  OUT UINT8                     *Vector
> +  );
> +
> +/**
> +  Enables the specified IRQ.
> +
> +  @param[in]  This            Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Irq             IRQ0-IRQ15.
> +  @param[in]  LevelTriggered  0 = Edge triggered; 1 = Level triggered.
> +
> +  @retval  EFI_SUCCESS            The Irq was enabled on the 8259 PIC.
> +  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259EnableIrq (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_IRQ              Irq,
> +  IN BOOLEAN                   LevelTriggered
> +  );
> +
> +/**
> +  Disables the specified IRQ.
> +
> +  @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Irq   IRQ0-IRQ15.
> +
> +  @retval  EFI_SUCCESS            The Irq was disabled on the 8259 PIC.
> +  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259DisableIrq (
> +  IN EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN EFI_8259_IRQ              Irq
> +  );
> +
> +/**
> +  Reads the PCI configuration space to get the interrupt number that is assigned
> to the card.
> +
> +  @param[in]   This       Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]   PciHandle  PCI function for which to return the vector.
> +  @param[out]  Vector     IRQ number that corresponds to the interrupt line.
> +
> +  @retval  EFI_SUCCESS  The interrupt line value was read successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259GetInterruptLine (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN  EFI_HANDLE                PciHandle,
> +  OUT UINT8                     *Vector
> +  );
> +
> +/**
> +  Issues the End of Interrupt (EOI) commands to PICs.
> +
> +  @param[in]  This  Indicates the EFI_LEGACY_8259_PROTOCOL instance.
> +  @param[in]  Irq   The interrupt for which to issue the EOI command.
> +
> +  @retval  EFI_SUCCESS            The EOI command was issued.
> +  @retval  EFI_INVALID_PARAMETER  The Irq is not valid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Interrupt8259EndOfInterrupt (
> +  IN  EFI_LEGACY_8259_PROTOCOL  *This,
> +  IN  EFI_8259_IRQ              Irq
> +  );
> +
> +#endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.inf
> new file mode 100644
> index 0000000000..e66b21c914
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/8259.inf
> @@ -0,0 +1,46 @@
> +## @file
> +# 8259 Interrupt Controller driver that provides Legacy 8259 protocol.
> +#
> +# Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = Legacy8259
> +  MODULE_UNI_FILE                = Legacy8259.uni
> +  FILE_GUID                      = 79CA4208-BBA1-4a9a-8456-E1E66A81484E
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = Install8259
> +
> +[Sources]
> +  8259.c
> +  8259.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  PcAtChipsetPkg/PcAtChipsetPkg.dec
> +  SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> +
> +[LibraryClasses]
> +  UefiBootServicesTableLib
> +  DebugLib
> +  UefiDriverEntryPoint
> +  IoLib
> +  PcdLib
> +
> +[Protocols]
> +  gEfiLegacy8259ProtocolGuid                    ## PRODUCES
> +  gEfiPciIoProtocolGuid                         ## SOMETIMES_CONSUMES
> +
> +[Pcd]
> +  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask      ##
> CONSUMES
> +  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel ##
> CONSUMES
> +
> +[Depex]
> +  TRUE
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  Legacy8259Extra.uni
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/Legacy8259.uni
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/Legacy8259.uni
> new file mode 100644
> index 0000000000..d035292419
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/Legacy8259.uni
> @@ -0,0 +1,16 @@
> +// /** @file
> +// 8259 Interrupt Controller driver that provides Legacy 8259 protocol.
> +//
> +// 8259 Interrupt Controller driver that provides Legacy 8259 protocol.
> +//
> +// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "8259 Interrupt
> Controller driver that provides Legacy 8259 protocol"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "8259 Interrupt
> Controller driver that provides Legacy 8259 protocol."
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/Legacy8259Extra.uni
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/Legacy8259Extra.uni
> new file mode 100644
> index 0000000000..ee43f6923c
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Overrides/PcAtChipsetPkg/8259Interru
> ptControllerDxe/Legacy8259Extra.uni
> @@ -0,0 +1,14 @@
> +// /** @file
> +// Legacy8259 Localized Strings and Content
> +//
> +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Legacy 8259 Interrupt Controller DXE Driver"
> +
> +
> --
> 2.16.2.windows.1


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

View/Reply Online (#46315): https://edk2.groups.io/g/devel/message/46315
Mute This Topic: https://groups.io/mt/32816099/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list