public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS
@ 2019-09-05 21:38 David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel

Create the SimicsOpenBoardPkg and its silicon Pkg to provide the support
for SIMICS quick start platform. it uses X58/ICH10 and emulated by SIMICS
model.

Different from v4:
  Cleanup name of SkyLake
  expand the QSP acronym to Quick Start Package
  ExChange the patch number 6 and 7 to make patch6 as final patch
  Change ICH to Ich in commit comments
David Wei (7):
  SimicsX58SktPkg:  Add CPU Pkg for SimicsX58
  SimicsIch10Pkg:  Add Ich Pkg for SimicsIch10
  SimicsOpenBoardPkg:  Add SimicsOpenBoardPkg and its modules
  SimicsOpenBoardPkg: Add DXE driver for Legacy Sio
  SimicsOpenBoardPkg:  Add modules and dec file under SimicsOpenBoardPkg
  SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip
  Platform/Intel:  Add build option for SIMICS QSP Platform

 .../MinPlatformAcpiTables/AcpiPlatform.c           | 1579 ++++++++++++++++++++
 .../AcpiTables/MinPlatformAcpiTables/Facs/Facs.c   |   84 ++
 .../AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c   |  359 +++++
 .../AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c   |   78 +
 .../AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c   |   46 +
 .../Library/BoardInitLib/PeiBoardInitPostMemLib.c  |   44 +
 .../Library/BoardInitLib/PeiBoardInitPreMemLib.c   |  110 ++
 .../Library/BoardInitLib/PeiX58Ich10Detect.c       |   26 +
 .../BoardInitLib/PeiX58Ich10InitPostMemLib.c       |   34 +
 .../BoardInitLib/PeiX58Ich10InitPreMemLib.c        |  111 ++
 .../LegacySioDxe/ComponentName.c                   |  173 +++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioChip.c      |  272 ++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c    |  600 ++++++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioService.c   |  249 +++
 .../SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c   |  647 ++++++++
 .../Library/LoadLinuxLib/Linux.c                   |  662 ++++++++
 .../Library/LoadLinuxLib/LinuxGdt.c                |  175 +++
 .../Library/NvVarsFileLib/FsAccess.c               |  507 +++++++
 .../Library/NvVarsFileLib/NvVarsFileLib.c          |   77 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    |  419 ++++++
 .../SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c |  100 ++
 .../Library/PeiReportFvLib/PeiReportFvLib.c        |  119 ++
 .../Library/PlatformBootManagerLib/BdsPlatform.c   | 1553 +++++++++++++++++++
 .../Library/PlatformBootManagerLib/PlatformData.c  |   35 +
 .../SerializeVariablesLib/SerializeVariablesLib.c  |  869 +++++++++++
 .../SiliconPolicyInitLib/SiliconPolicyInitLib.c    |  108 ++
 .../SiliconPolicyUpdateLib.c                       |   70 +
 .../Intel/SimicsOpenBoardPkg/SecCore/SecMain.c     |  956 ++++++++++++
 .../Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c  |  865 +++++++++++
 .../SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c  |  124 ++
 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c |   57 +
 .../SimicsOpenBoardPkg/SimicsPei/FeatureControl.c  |  115 ++
 .../Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c |  568 +++++++
 .../Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c  |  630 ++++++++
 .../SimicsVideoDxe/ComponentName.c                 |  205 +++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c     | 1011 +++++++++++++
 .../SimicsVideoDxe/DriverSupportedEfiVersion.c     |   15 +
 .../Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c  |  416 ++++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c |  341 +++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c    |  302 ++++
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.c          |  148 ++
 .../Library/ResetSystemLib/ResetSystemLib.c        |  137 ++
 .../Library/SmmSpiFlashCommonLib/SpiFlashCommon.c  |  194 +++
 .../SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c    |   54 +
 .../LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c |  935 ++++++++++++
 .../SmmControl/RuntimeDxe/SmmControl2Dxe.c         |  410 +++++
 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c      |  175 +++
 .../SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c     |  148 ++
 .../SimicsX58SktPkg/Smm/Access/SmmAccessPei.c      |  346 +++++
 .../SimicsX58SktPkg/Smm/Access/SmramInternal.c     |  200 +++
 Maintainers.txt                                    |   12 +
 .../SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf   |   31 +
 .../Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl   |  821 ++++++++++
 .../MinPlatformAcpiTables/AcpiPlatform.h           |   45 +
 .../MinPlatformAcpiTables/AcpiPlatform.inf         |  105 ++
 .../Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h |   75 +
 .../BoardX58Ich10/DecomprScratchEnd.fdf.inc        |   67 +
 .../BoardInitLib/PeiBoardInitPostMemLib.inf        |   36 +
 .../Library/BoardInitLib/PeiBoardInitPreMemLib.inf |   39 +
 .../Library/BoardInitLib/PeiX58Ich10InitLib.h      |   16 +
 .../BoardX58Ich10/OpenBoardPkg.dsc                 |  233 +++
 .../BoardX58Ich10/OpenBoardPkg.fdf                 |  304 ++++
 .../BoardX58Ich10/OpenBoardPkg.fdf.inc             |   54 +
 .../BoardX58Ich10/OpenBoardPkgBuildOption.dsc      |   78 +
 .../BoardX58Ich10/OpenBoardPkgConfig.dsc           |   56 +
 .../BoardX58Ich10/OpenBoardPkgPcd.dsc              |  281 ++++
 .../BoardX58Ich10/VarStore.fdf.inc                 |   53 +
 .../BoardX58Ich10/build_config.cfg                 |   31 +
 .../Include/Guid/SimicsBoardConfig.h               |   18 +
 .../Include/IndustryStandard/I440FxPiix4.h         |   50 +
 .../Include/IndustryStandard/LinuxBzImage.h        |  159 ++
 .../Include/Library/LoadLinuxLib.h                 |  205 +++
 .../Include/Library/SerializeVariablesLib.h        |  224 +++
 .../SimicsOpenBoardPkg/Include/SimicsPlatforms.h   |   55 +
 .../LegacySioDxe/ComponentName.h                   |   87 ++
 .../LegacySioDxe/LegacySioDxe.inf                  |   54 +
 .../SimicsOpenBoardPkg/LegacySioDxe/Register.h     |   15 +
 .../SimicsOpenBoardPkg/LegacySioDxe/SioChip.h      |  195 +++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h    |  134 ++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioService.h   |  143 ++
 .../Library/DxeLogoLib/DxeLogoLib.inf              |   55 +
 .../Library/DxeLogoLib/OemBadging.h                |   83 +
 .../Library/LoadLinuxLib/DxeLoadLinuxLib.inf       |   42 +
 .../Library/LoadLinuxLib/Ia32/JumpToKernel.nasm    |   41 +
 .../Library/LoadLinuxLib/LoadLinuxLib.h            |   52 +
 .../Library/LoadLinuxLib/X64/JumpToKernel.nasm     |   85 ++
 .../Library/NvVarsFileLib/NvVarsFileLib.h          |   55 +
 .../Library/NvVarsFileLib/NvVarsFileLib.inf        |   53 +
 .../Library/PciHostBridgeLib/PciHostBridge.h       |   68 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |   51 +
 .../Library/PeiReportFvLib/PeiReportFvLib.inf      |   56 +
 .../Library/PlatformBootManagerLib/BdsPlatform.h   |  172 +++
 .../PlatformBootManagerLib.inf                     |   72 +
 .../SerializeVariablesLib/SerializeVariablesLib.h  |   33 +
 .../SerializeVariablesLib.inf                      |   36 +
 Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp    |  Bin 0 -> 141078 bytes
 Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec |  152 ++
 .../SiliconPolicyInitLib/SiliconPolicyInitLib.inf  |   38 +
 .../SiliconPolicyUpdateLib.inf                     |   35 +
 .../SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm  |   45 +
 .../Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf   |   73 +
 .../SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm   |   45 +
 .../Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h  |   38 +
 .../SimicsOpenBoardPkg/SimicsDxe/Platform.uni      |   31 +
 .../SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h  |   52 +
 .../SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr |   67 +
 .../SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf     |   65 +
 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h |   50 +
 .../Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h  |   88 ++
 .../SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf     |  104 ++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h     |  507 +++++++
 .../SimicsVideoDxe/SimicsVideoDxe.inf              |   74 +
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm  |  279 ++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h    |  701 +++++++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh   |   79 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.h          |   38 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf        |   51 +
 Platform/Intel/build.cfg                           |    2 +
 Platform/Intel/build_bios.py                       |    3 +
 Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec          |   26 +
 Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc      |   12 +
 .../Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf  |    9 +
 .../Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf   |    9 +
 .../Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf    |   13 +
 .../Include/Library/SpiFlashCommonLib.h            |   98 ++
 Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h   |   43 +
 Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h   |   94 ++
 .../SimicsIch10Pkg/Include/PchReservedResources.h  |   60 +
 .../Intel/SimicsIch10Pkg/Include/Protocol/Spi.h    |  295 ++++
 .../SimicsIch10Pkg/Include/Register/PchRegsPmc.h   |  647 ++++++++
 .../SimicsIch10Pkg/Include/Register/PchRegsSpi.h   |  304 ++++
 .../SimicsIch10Pkg/Include/Register/X58Ich10.h     |  114 ++
 .../IncludePrivate/Library/PchSpiCommonLib.h       |  396 +++++
 .../Library/ResetSystemLib/ResetSystemLib.inf      |   34 +
 .../SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf  |   50 +
 .../BasePchSpiCommonLib/BasePchSpiCommonLib.inf    |   31 +
 .../SmmControl/RuntimeDxe/SmmControl2Dxe.inf       |   61 +
 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h      |   23 +
 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf |   44 +
 .../Include/Register/X58SmramSaveStateMap.h        |  178 +++
 Silicon/Intel/SimicsX58SktPkg/SktPkg.dec           |   37 +
 Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc        |   14 +
 .../Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf |    9 +
 .../Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf  |   10 +
 Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf    |   16 +
 .../Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf   |   14 +
 .../SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf   |   54 +
 .../SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf    |   65 +
 .../SimicsX58SktPkg/Smm/Access/SmramInternal.h     |   82 +
 149 files changed, 27547 insertions(+)
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10Detect.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPostMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPreMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/DecomprScratchEnd.fdf.inc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf.inc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOption.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgPcd.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/VarStore.fdf.inc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/LegacySioDxe.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/Register.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Library/SpiFlashCommonLib.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/PchReservedResources.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Protocol/Spi.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsPmc.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsSpi.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Register/X58Ich10.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IncludePrivate/Library/PchSpiCommonLib.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Include/Register/X58SmramSaveStateMap.h
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPkg.dec
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h

-- 
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 2/7] SimicsIch10Pkg: Add Ich Pkg for SimicsIch10 David Wei
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add CPU Pkg for SimicsX58. It is added for simics Quick Start Platform project support

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 .../SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c     | 148 +++++++++
 .../SimicsX58SktPkg/Smm/Access/SmmAccessPei.c      | 346 +++++++++++++++++++++
 .../SimicsX58SktPkg/Smm/Access/SmramInternal.c     | 200 ++++++++++++
 .../Include/Register/X58SmramSaveStateMap.h        | 178 +++++++++++
 Silicon/Intel/SimicsX58SktPkg/SktPkg.dec           |  37 +++
 Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc        |  14 +
 .../Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf |   9 +
 .../Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf  |  10 +
 Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf    |  16 +
 .../Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf   |  14 +
 .../SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf   |  54 ++++
 .../SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf    |  65 ++++
 .../SimicsX58SktPkg/Smm/Access/SmramInternal.h     |  82 +++++
 13 files changed, 1173 insertions(+)
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Include/Register/X58SmramSaveStateMap.h
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPkg.dec
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf
 create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h

diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c
new file mode 100644
index 0000000000..5d3b2c14aa
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c
@@ -0,0 +1,148 @@
+/** @file
+  A DXE_DRIVER providing SMRAM access by producing EFI_SMM_ACCESS2_PROTOCOL.
+
+  X58 TSEG is expected to have been verified and set up by the SmmAccessPei
+  driver.
+
+  Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
+  Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/SmmAccess2.h>
+
+#include "SmramInternal.h"
+
+/**
+  Opens the SMRAM area to be accessible by a boot-service driver.
+
+  This function "opens" SMRAM so that it is visible while not inside of SMM.
+  The function should return EFI_UNSUPPORTED if the hardware does not support
+  hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM
+  configuration is locked.
+
+  @param[in] This           The EFI_SMM_ACCESS2_PROTOCOL instance.
+
+  @retval EFI_SUCCESS       The operation was successful.
+  @retval EFI_UNSUPPORTED   The system does not support opening and closing of
+                            SMRAM.
+  @retval EFI_DEVICE_ERROR  SMRAM cannot be opened, perhaps because it is
+                            locked.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccess2DxeOpen (
+  IN EFI_SMM_ACCESS2_PROTOCOL  *This
+  )
+{
+  return SmramAccessOpen (&This->LockState, &This->OpenState);
+}
+
+/**
+  Inhibits access to the SMRAM.
+
+  This function "closes" SMRAM so that it is not visible while outside of SMM.
+  The function should return EFI_UNSUPPORTED if the hardware does not support
+  hiding of SMRAM.
+
+  @param[in] This           The EFI_SMM_ACCESS2_PROTOCOL instance.
+
+  @retval EFI_SUCCESS       The operation was successful.
+  @retval EFI_UNSUPPORTED   The system does not support opening and closing of
+                            SMRAM.
+  @retval EFI_DEVICE_ERROR  SMRAM cannot be closed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccess2DxeClose (
+  IN EFI_SMM_ACCESS2_PROTOCOL  *This
+  )
+{
+  return SmramAccessClose (&This->LockState, &This->OpenState);
+}
+
+/**
+  Inhibits access to the SMRAM.
+
+  This function prohibits access to the SMRAM region.  This function is usually
+  implemented such that it is a write-once operation.
+
+  @param[in] This          The EFI_SMM_ACCESS2_PROTOCOL instance.
+
+  @retval EFI_SUCCESS      The device was successfully locked.
+  @retval EFI_UNSUPPORTED  The system does not support locking of SMRAM.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccess2DxeLock (
+  IN EFI_SMM_ACCESS2_PROTOCOL  *This
+  )
+{
+  return SmramAccessLock (&This->LockState, &This->OpenState);
+}
+
+/**
+  Queries the memory controller for the possible regions that will support
+  SMRAM.
+
+  @param[in]     This           The EFI_SMM_ACCESS2_PROTOCOL instance.
+  @param[in,out] SmramMapSize   A pointer to the size, in bytes, of the
+                                SmramMemoryMap buffer.
+  @param[in,out] SmramMap       A pointer to the buffer in which firmware
+                                places the current memory map.
+
+  @retval EFI_SUCCESS           The chipset supported the given resource.
+  @retval EFI_BUFFER_TOO_SMALL  The SmramMap parameter was too small.  The
+                                current buffer size needed to hold the memory
+                                map is returned in SmramMapSize.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccess2DxeGetCapabilities (
+  IN CONST EFI_SMM_ACCESS2_PROTOCOL  *This,
+  IN OUT UINTN                       *SmramMapSize,
+  IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
+  )
+{
+  return SmramAccessGetCapabilities (This->LockState, This->OpenState,
+           SmramMapSize, SmramMap);
+}
+
+//
+// LockState and OpenState will be filled in by the entry point.
+//
+STATIC EFI_SMM_ACCESS2_PROTOCOL mAccess2 = {
+  &SmmAccess2DxeOpen,
+  &SmmAccess2DxeClose,
+  &SmmAccess2DxeLock,
+  &SmmAccess2DxeGetCapabilities
+};
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+SmmAccess2DxeEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  //
+  // This module should only be included if SMRAM support is required.
+  //
+  ASSERT (FeaturePcdGet (PcdSmmSmramRequire));
+
+  GetStates (&mAccess2.LockState, &mAccess2.OpenState);
+  return gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+                &gEfiSmmAccess2ProtocolGuid, &mAccess2,
+                NULL);
+}
diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c
new file mode 100644
index 0000000000..c54026b4d1
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c
@@ -0,0 +1,346 @@
+/** @file
+  A PEIM with the following responsibilities:
+
+  - verify & configure the X58 TSEG in the entry point,
+  - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,
+  - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose
+    it via the gEfiAcpiVariableGuid GUID HOB.
+
+  This PEIM runs from RAM, so we can write to variables with static storage
+  duration.
+
+  Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
+  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/AcpiS3Context.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/SmmAccess.h>
+
+#include <Register/X58Ich10.h>
+#include "SmramInternal.h"
+
+//
+// PEI_SMM_ACCESS_PPI implementation.
+//
+
+/**
+  Opens the SMRAM area to be accessible by a PEIM driver.
+
+  This function "opens" SMRAM so that it is visible while not inside of SMM.
+  The function should return EFI_UNSUPPORTED if the hardware does not support
+  hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM
+  configuration is locked.
+
+  @param  PeiServices            General purpose services available to every
+                                 PEIM.
+  @param  This                   The pointer to the SMM Access Interface.
+  @param  DescriptorIndex        The region of SMRAM to Open.
+
+  @retval EFI_SUCCESS            The region was successfully opened.
+  @retval EFI_DEVICE_ERROR       The region could not be opened because locked
+                                 by chipset.
+  @retval EFI_INVALID_PARAMETER  The descriptor index was out of bounds.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccessPeiOpen (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN UINTN                           DescriptorIndex
+  )
+{
+  if (DescriptorIndex >= DescIdxCount) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // According to current practice, DescriptorIndex is not considered at all,
+  // beyond validating it.
+  //
+  return SmramAccessOpen (&This->LockState, &This->OpenState);
+}
+
+/**
+  Inhibits access to the SMRAM.
+
+  This function "closes" SMRAM so that it is not visible while outside of SMM.
+  The function should return EFI_UNSUPPORTED if the hardware does not support
+  hiding of SMRAM.
+
+  @param  PeiServices              General purpose services available to every
+                                   PEIM.
+  @param  This                     The pointer to the SMM Access Interface.
+  @param  DescriptorIndex          The region of SMRAM to Close.
+
+  @retval EFI_SUCCESS              The region was successfully closed.
+  @retval EFI_DEVICE_ERROR         The region could not be closed because
+                                   locked by chipset.
+  @retval EFI_INVALID_PARAMETER    The descriptor index was out of bounds.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccessPeiClose (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN UINTN                           DescriptorIndex
+  )
+{
+  if (DescriptorIndex >= DescIdxCount) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // According to current practice, DescriptorIndex is not considered at all,
+  // beyond validating it.
+  //
+  return SmramAccessClose (&This->LockState, &This->OpenState);
+}
+
+/**
+  Inhibits access to the SMRAM.
+
+  This function prohibits access to the SMRAM region.  This function is usually
+  implemented such that it is a write-once operation.
+
+  @param  PeiServices              General purpose services available to every
+                                   PEIM.
+  @param  This                     The pointer to the SMM Access Interface.
+  @param  DescriptorIndex          The region of SMRAM to Close.
+
+  @retval EFI_SUCCESS            The region was successfully locked.
+  @retval EFI_DEVICE_ERROR       The region could not be locked because at
+                                 least one range is still open.
+  @retval EFI_INVALID_PARAMETER  The descriptor index was out of bounds.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccessPeiLock (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN UINTN                           DescriptorIndex
+  )
+{
+  if (DescriptorIndex >= DescIdxCount) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // According to current practice, DescriptorIndex is not considered at all,
+  // beyond validating it.
+  //
+  return SmramAccessLock (&This->LockState, &This->OpenState);
+}
+
+/**
+  Queries the memory controller for the possible regions that will support
+  SMRAM.
+
+  @param  PeiServices           General purpose services available to every
+                                PEIM.
+  @param This                   The pointer to the SmmAccessPpi Interface.
+  @param SmramMapSize           The pointer to the variable containing size of
+                                the buffer to contain the description
+                                information.
+  @param SmramMap               The buffer containing the data describing the
+                                Smram region descriptors.
+
+  @retval EFI_BUFFER_TOO_SMALL  The user did not provide a sufficient buffer.
+  @retval EFI_SUCCESS           The user provided a sufficiently-sized buffer.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmAccessPeiGetCapabilities (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN OUT UINTN                       *SmramMapSize,
+  IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
+  )
+{
+  return SmramAccessGetCapabilities (This->LockState, This->OpenState, SmramMapSize, SmramMap);
+}
+
+//
+// LockState and OpenState will be filled in by the entry point.
+//
+STATIC PEI_SMM_ACCESS_PPI mAccess = {
+  &SmmAccessPeiOpen,
+  &SmmAccessPeiClose,
+  &SmmAccessPeiLock,
+  &SmmAccessPeiGetCapabilities
+};
+
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gPeiSmmAccessPpiGuid, &mAccess
+  }
+};
+
+
+//
+// Utility functions.
+//
+STATIC
+UINT8
+CmosRead8 (
+  IN UINT8  Index
+  )
+{
+  IoWrite8 (0x70, Index);
+  return IoRead8 (0x71);
+}
+
+STATIC
+UINT32
+GetSystemMemorySizeBelow4gb (
+  VOID
+  )
+{
+  UINT32 Cmos0x34;
+  UINT32 Cmos0x35;
+
+  Cmos0x34 = CmosRead8 (0x34);
+  Cmos0x35 = CmosRead8 (0x35);
+
+  return ((Cmos0x35 << 8 | Cmos0x34) << 16) + SIZE_16MB;
+}
+
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+SmmAccessPeiEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  UINT16               HostBridgeDevId;
+  UINT32                EsmramcVal;
+  UINT32               TopOfLowRam, TopOfLowRamMb;
+  EFI_STATUS           Status;
+  UINTN                SmramMapSize;
+  EFI_SMRAM_DESCRIPTOR SmramMap[DescIdxCount];
+  VOID                 *GuidHob;
+
+  //
+  // This module should only be included if SMRAM support is required.
+  //
+  ASSERT (FeaturePcdGet (PcdSmmSmramRequire));
+
+  //
+  // Verify if we're running on a X58 machine type.
+  //
+  HostBridgeDevId = PciRead16 (SIMICS_HOSTBRIDGE_DID);
+  if (HostBridgeDevId != INTEL_ICH10_DEVICE_ID) {
+    DEBUG ((EFI_D_ERROR, "%a: no SMRAM with host bridge DID=0x%04x; only "
+      "DID=0x%04x (X58) is supported\n", __FUNCTION__, HostBridgeDevId,
+      INTEL_ICH10_DEVICE_ID));
+    goto WrongConfig;
+  }
+
+  //
+  // Confirm if Simics supports SMRAM.
+  //
+  // With no support for it, the ESMRAMC (Extended System Management RAM
+  // Control) register reads as zero. If there is support, the cache-enable
+  // bits are hard-coded as 1 by Simics.
+  //
+
+  TopOfLowRam = GetSystemMemorySizeBelow4gb ();
+  ASSERT ((TopOfLowRam & (SIZE_1MB - 1)) == 0);
+  TopOfLowRamMb = TopOfLowRam >> 20;
+  DEBUG((EFI_D_INFO, "TopOfLowRam =0x%x; TopOfLowRamMb =0x%x \n", TopOfLowRam, TopOfLowRamMb));
+
+
+  //
+  // Set Top of Low Usable DRAM.
+  //
+  PciWrite32 (DRAMC_REGISTER_X58(MCH_TOLUD), TopOfLowRam);
+  DEBUG((EFI_D_INFO, "MCH_TOLUD =0x%x; \n", PciRead32(DRAMC_REGISTER_X58(MCH_TOLUD))));
+
+  //
+  // Set TSEG Memory Base.
+  //
+  EsmramcVal = (TopOfLowRamMb - FixedPcdGet8(PcdX58TsegMbytes)) << MCH_TSEGMB_MB_SHIFT;
+  //
+  // Set TSEG size, and disable TSEG visibility outside of SMM. Note that the
+  // T_EN bit has inverse meaning; when T_EN is set, then TSEG visibility is
+  // *restricted* to SMM.
+  //
+  EsmramcVal &= ~(UINT32)MCH_ESMRAMC_TSEG_MASK;
+  EsmramcVal |= FixedPcdGet8 (PcdX58TsegMbytes) == 8 ? MCH_ESMRAMC_TSEG_8MB :
+                FixedPcdGet8 (PcdX58TsegMbytes) == 2 ? MCH_ESMRAMC_TSEG_2MB :
+                MCH_ESMRAMC_TSEG_1MB;
+  EsmramcVal |= MCH_ESMRAMC_T_EN;
+  PciWrite32(DRAMC_REGISTER_X58(MCH_TSEGMB), EsmramcVal);
+  DEBUG((EFI_D_INFO, "MCH_TSEGMB =0x%x; \n", PciRead32(DRAMC_REGISTER_X58(MCH_TSEGMB))));
+  DEBUG((EFI_D_INFO, "MCH_TSEGMB_1 =0x%x; MCH_TSEGMB_2 =0x%x;\n", ((TopOfLowRamMb - FixedPcdGet8(PcdX58TsegMbytes)) << MCH_TSEGMB_MB_SHIFT), EsmramcVal));
+
+  //
+  // Create the GUID HOB and point it to the first SMRAM range.
+  //
+  GetStates (&mAccess.LockState, &mAccess.OpenState);
+  SmramMapSize = sizeof SmramMap;
+  Status = SmramAccessGetCapabilities (mAccess.LockState, mAccess.OpenState, &SmramMapSize, SmramMap);
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG_CODE_BEGIN ();
+  {
+    UINTN Count;
+    UINTN Idx;
+
+    Count = SmramMapSize / sizeof SmramMap[0];
+    DEBUG ((EFI_D_VERBOSE, "%a: SMRAM map follows, %d entries\n", __FUNCTION__, (INT32)Count));
+    DEBUG ((EFI_D_VERBOSE, "% 20a % 20a % 20a % 20a\n", "PhysicalStart(0x)",
+      "PhysicalSize(0x)", "CpuStart(0x)", "RegionState(0x)"));
+    for (Idx = 0; Idx < Count; ++Idx) {
+      DEBUG ((EFI_D_VERBOSE, "% 20Lx % 20Lx % 20Lx % 20Lx\n",
+        SmramMap[Idx].PhysicalStart, SmramMap[Idx].PhysicalSize,
+        SmramMap[Idx].CpuStart, SmramMap[Idx].RegionState));
+    }
+  }
+  DEBUG_CODE_END ();
+
+  GuidHob = BuildGuidHob (&gEfiAcpiVariableGuid, sizeof SmramMap[DescIdxSmmS3ResumeState]);
+  if (GuidHob == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (GuidHob, &SmramMap[DescIdxSmmS3ResumeState], sizeof SmramMap[DescIdxSmmS3ResumeState]);
+
+  //
+  // We're done. The next step should succeed, but even if it fails, we can't
+  // roll back the above BuildGuidHob() allocation, because PEI doesn't support
+  // releasing memory.
+  //
+  return PeiServicesInstallPpi (mPpiList);
+
+WrongConfig:
+  //
+  // We really don't want to continue in this case.
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+  return EFI_UNSUPPORTED;
+}
diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c
new file mode 100644
index 0000000000..4b5a92f602
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c
@@ -0,0 +1,200 @@
+/** @file
+  Functions and types shared by the SMM accessor PEI and DXE modules.
+
+  Copyright (C) 2015, Red Hat, Inc.
+  Copyright (C) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/AcpiS3Context.h>
+#include <Register/X58Ich10.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+
+#include "SmramInternal.h"
+
+BOOLEAN gLockState;
+BOOLEAN gOpenState;
+
+/**
+  Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and
+  OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,
+  from the D_LCK and T_EN bits.
+
+  PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on
+  the LockState and OpenState fields being up-to-date on entry, and they need
+  to restore the same invariant on exit, if they touch the bits in question.
+
+  @param[out] LockState  Reflects the D_LCK bit on output; TRUE iff SMRAM is
+                         locked.
+  @param[out] OpenState  Reflects the inverse of the T_EN bit on output; TRUE
+                         iff SMRAM is open.
+**/
+VOID
+GetStates (
+  OUT BOOLEAN *LockState,
+  OUT BOOLEAN *OpenState
+)
+{
+  UINT8 EsmramcVal;
+
+  EsmramcVal = PciRead8(DRAMC_REGISTER_X58(MCH_TSEGMB));
+
+  *OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN);
+  *LockState = !*OpenState;
+
+  *OpenState = gOpenState;
+  *LockState = gLockState;
+}
+
+//
+// The functions below follow the PEI_SMM_ACCESS_PPI and
+// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This
+// pointers are removed (TSEG doesn't depend on them), and so is the
+// DescriptorIndex parameter (TSEG doesn't support range-wise locking).
+//
+// The LockState and OpenState members that are common to both
+// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in
+// isolation from the rest of the (non-shared) members.
+//
+
+EFI_STATUS
+SmramAccessOpen (
+  OUT BOOLEAN *LockState,
+  OUT BOOLEAN *OpenState
+  )
+{
+
+  //
+  // Open TSEG by clearing T_EN.
+  //
+  PciAnd8(DRAMC_REGISTER_X58(MCH_TSEGMB),
+    (UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff));
+
+  gOpenState = TRUE;
+  gLockState = !gOpenState;
+
+  GetStates (LockState, OpenState);
+  if (!*OpenState) {
+    return EFI_DEVICE_ERROR;
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SmramAccessClose (
+  OUT BOOLEAN *LockState,
+  OUT BOOLEAN *OpenState
+  )
+{
+  //
+  // Close TSEG by setting T_EN.
+  //
+  PciOr8(DRAMC_REGISTER_X58(MCH_TSEGMB), MCH_ESMRAMC_T_EN);
+
+  gOpenState = FALSE;
+  gLockState = !gOpenState;
+
+  GetStates (LockState, OpenState);
+  if (*OpenState) {
+    return EFI_DEVICE_ERROR;
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SmramAccessLock (
+  OUT    BOOLEAN *LockState,
+  IN OUT BOOLEAN *OpenState
+  )
+{
+  if (*OpenState) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Close & lock TSEG by setting T_EN and D_LCK.
+  //
+  PciOr8 (DRAMC_REGISTER_X58(MCH_TSEGMB), MCH_ESMRAMC_T_EN);
+
+  gOpenState = FALSE;
+  gLockState = !gOpenState;
+
+  GetStates (LockState, OpenState);
+  if (*OpenState || !*LockState) {
+    return EFI_DEVICE_ERROR;
+  }
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SmramAccessGetCapabilities (
+  IN BOOLEAN                  LockState,
+  IN BOOLEAN                  OpenState,
+  IN OUT UINTN                *SmramMapSize,
+  IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+  )
+{
+  UINTN  OriginalSize;
+  UINT32 TsegMemoryBaseMb, TsegMemoryBase;
+  UINT64 CommonRegionState;
+  UINT8  TsegSizeBits;
+
+  OriginalSize  = *SmramMapSize;
+  *SmramMapSize = DescIdxCount * sizeof *SmramMap;
+  if (OriginalSize < *SmramMapSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  //
+  // Read the TSEG Memory Base register.
+  //
+  TsegMemoryBaseMb = PciRead32(DRAMC_REGISTER_X58(MCH_TSEGMB));
+
+  TsegMemoryBaseMb = 0xDF800000;
+
+  TsegMemoryBase = (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) << 20;
+
+  //
+  // Precompute the region state bits that will be set for all regions.
+  //
+  CommonRegionState = (OpenState ? EFI_SMRAM_OPEN : EFI_SMRAM_CLOSED) |
+                      (LockState ? EFI_SMRAM_LOCKED : 0) |
+                      EFI_CACHEABLE;
+
+  //
+  // The first region hosts an SMM_S3_RESUME_STATE object. It is located at the
+  // start of TSEG. We round up the size to whole pages, and we report it as
+  // EFI_ALLOCATED, so that the SMM_CORE stays away from it.
+  //
+  SmramMap[DescIdxSmmS3ResumeState].PhysicalStart = TsegMemoryBase;
+  SmramMap[DescIdxSmmS3ResumeState].CpuStart      = TsegMemoryBase;
+  SmramMap[DescIdxSmmS3ResumeState].PhysicalSize  =
+    EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE)));
+  SmramMap[DescIdxSmmS3ResumeState].RegionState   =
+    CommonRegionState | EFI_ALLOCATED;
+
+  //
+  // Get the TSEG size bits from the ESMRAMC register.
+  //
+  TsegSizeBits = PciRead8 (DRAMC_REGISTER_X58(MCH_TSEGMB)) &
+                            MCH_ESMRAMC_TSEG_MASK;
+
+  TsegSizeBits = MCH_ESMRAMC_TSEG_8MB;
+
+  //
+  // The second region is the main one, following the first.
+  //
+  SmramMap[DescIdxMain].PhysicalStart =
+    SmramMap[DescIdxSmmS3ResumeState].PhysicalStart +
+    SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
+  SmramMap[DescIdxMain].CpuStart = SmramMap[DescIdxMain].PhysicalStart;
+  SmramMap[DescIdxMain].PhysicalSize =
+    (TsegSizeBits == MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB :
+     TsegSizeBits == MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB :
+     SIZE_1MB) - SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
+  SmramMap[DescIdxMain].RegionState = CommonRegionState;
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/SimicsX58SktPkg/Include/Register/X58SmramSaveStateMap.h b/Silicon/Intel/SimicsX58SktPkg/Include/Register/X58SmramSaveStateMap.h
new file mode 100644
index 0000000000..a067d1488a
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Include/Register/X58SmramSaveStateMap.h
@@ -0,0 +1,178 @@
+/** @file
+SMRAM Save State Map Definitions.
+
+SMRAM Save State Map definitions based on contents of the
+Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  Volume 3C, Section 34.4 SMRAM
+  Volume 3C, Section 34.5 SMI Handler Execution Environment
+  Volume 3C, Section 34.7 Managing Synchronous and Asynchronous SMIs
+
+and the AMD64 Architecture Programmer's Manual
+  Volume 2, Section 10.2 SMM Resources
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015, Red Hat, Inc.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __X58_SMRAM_SAVE_STATE_MAP_H__
+#define __X58_SMRAM_SAVE_STATE_MAP_H__
+
+#pragma pack (1)
+
+///
+/// 32-bit SMRAM Save State Map
+///
+typedef struct {
+  UINT8   Reserved0[0x200]; // 7c00h
+  UINT8   Reserved1[0xf8];  // 7e00h
+  UINT32  SMBASE;           // 7ef8h
+  UINT32  SMMRevId;         // 7efch
+  UINT16  IORestart;        // 7f00h
+  UINT16  AutoHALTRestart;  // 7f02h
+  UINT8   Reserved2[0x9C];  // 7f08h
+  UINT32  IOMemAddr;        // 7fa0h
+  UINT32  IOMisc;           // 7fa4h
+  UINT32  _ES;              // 7fa8h
+  UINT32  _CS;              // 7fach
+  UINT32  _SS;              // 7fb0h
+  UINT32  _DS;              // 7fb4h
+  UINT32  _FS;              // 7fb8h
+  UINT32  _GS;              // 7fbch
+  UINT32  Reserved3;        // 7fc0h
+  UINT32  _TR;              // 7fc4h
+  UINT32  _DR7;             // 7fc8h
+  UINT32  _DR6;             // 7fcch
+  UINT32  _EAX;             // 7fd0h
+  UINT32  _ECX;             // 7fd4h
+  UINT32  _EDX;             // 7fd8h
+  UINT32  _EBX;             // 7fdch
+  UINT32  _ESP;             // 7fe0h
+  UINT32  _EBP;             // 7fe4h
+  UINT32  _ESI;             // 7fe8h
+  UINT32  _EDI;             // 7fech
+  UINT32  _EIP;             // 7ff0h
+  UINT32  _EFLAGS;          // 7ff4h
+  UINT32  _CR3;             // 7ff8h
+  UINT32  _CR0;             // 7ffch
+} X58_SMRAM_SAVE_STATE_MAP32;
+
+///
+/// 64-bit SMRAM Save State Map
+///
+typedef struct {
+  UINT8   Reserved0[0x200];  // 7c00h
+
+  UINT16  _ES;               // 7e00h
+  UINT16  _ESAccessRights;   // 7e02h
+  UINT32  _ESLimit;          // 7e04h
+  UINT64  _ESBase;           // 7e08h
+
+  UINT16  _CS;               // 7e10h
+  UINT16  _CSAccessRights;   // 7e12h
+  UINT32  _CSLimit;          // 7e14h
+  UINT64  _CSBase;           // 7e18h
+
+  UINT16  _SS;               // 7e20h
+  UINT16  _SSAccessRights;   // 7e22h
+  UINT32  _SSLimit;          // 7e24h
+  UINT64  _SSBase;           // 7e28h
+
+  UINT16  _DS;               // 7e30h
+  UINT16  _DSAccessRights;   // 7e32h
+  UINT32  _DSLimit;          // 7e34h
+  UINT64  _DSBase;           // 7e38h
+
+  UINT16  _FS;               // 7e40h
+  UINT16  _FSAccessRights;   // 7e42h
+  UINT32  _FSLimit;          // 7e44h
+  UINT64  _FSBase;           // 7e48h
+
+  UINT16  _GS;               // 7e50h
+  UINT16  _GSAccessRights;   // 7e52h
+  UINT32  _GSLimit;          // 7e54h
+  UINT64  _GSBase;           // 7e58h
+
+  UINT32  _GDTRReserved1;    // 7e60h
+  UINT16  _GDTRLimit;        // 7e64h
+  UINT16  _GDTRReserved2;    // 7e66h
+  UINT64  _GDTRBase;         // 7e68h
+
+  UINT16  _LDTR;             // 7e70h
+  UINT16  _LDTRAccessRights; // 7e72h
+  UINT32  _LDTRLimit;        // 7e74h
+  UINT64  _LDTRBase;         // 7e78h
+
+  UINT32  _IDTRReserved1;    // 7e80h
+  UINT16  _IDTRLimit;        // 7e84h
+  UINT16  _IDTRReserved2;    // 7e86h
+  UINT64  _IDTRBase;         // 7e88h
+
+  UINT16  _TR;               // 7e90h
+  UINT16  _TRAccessRights;   // 7e92h
+  UINT32  _TRLimit;          // 7e94h
+  UINT64  _TRBase;           // 7e98h
+
+  UINT64  IO_RIP;            // 7ea0h
+  UINT64  IO_RCX;            // 7ea8h
+  UINT64  IO_RSI;            // 7eb0h
+  UINT64  IO_RDI;            // 7eb8h
+  UINT32  IO_DWord;          // 7ec0h
+  UINT8   Reserved1[0x04];   // 7ec4h
+  UINT8   IORestart;         // 7ec8h
+  UINT8   AutoHALTRestart;   // 7ec9h
+  UINT8   Reserved2[0x06];   // 7ecah
+
+  UINT64  IA32_EFER;         // 7ed0h
+  UINT64  SVM_Guest;         // 7ed8h
+  UINT64  SVM_GuestVMCB;     // 7ee0h
+  UINT64  SVM_GuestVIntr;    // 7ee8h
+  UINT8   Reserved3[0x0c];   // 7ef0h
+
+  UINT32  SMMRevId;          // 7efch
+  UINT32  SMBASE;            // 7f00h
+
+  UINT8   Reserved4[0x1c];   // 7f04h
+  UINT64  SVM_GuestPAT;      // 7f20h
+  UINT64  SVM_HostIA32_EFER; // 7f28h
+  UINT64  SVM_HostCR4;       // 7f30h
+  UINT64  SVM_HostCR3;       // 7f38h
+  UINT64  SVM_HostCR0;       // 7f40h
+
+  UINT64  _CR4;              // 7f48h
+  UINT64  _CR3;              // 7f50h
+  UINT64  _CR0;              // 7f58h
+  UINT64  _DR7;              // 7f60h
+  UINT64  _DR6;              // 7f68h
+  UINT64  _RFLAGS;           // 7f70h
+  UINT64  _RIP;              // 7f78h
+  UINT64  _R15;              // 7f80h
+  UINT64  _R14;              // 7f88h
+  UINT64  _R13;              // 7f90h
+  UINT64  _R12;              // 7f98h
+  UINT64  _R11;              // 7fa0h
+  UINT64  _R10;              // 7fa8h
+  UINT64  _R9;               // 7fb0h
+  UINT64  _R8;               // 7fb8h
+  UINT64  _RDI;              // 7fc0h
+  UINT64  _RSI;              // 7fc8h
+  UINT64  _RBP;              // 7fd0h
+  UINT64  _RSP;              // 7fd8h
+  UINT64  _RBX;              // 7fe0h
+  UINT64  _RDX;              // 7fe8h
+  UINT64  _RCX;              // 7ff0h
+  UINT64  _RAX;              // 7ff8h
+} X58_SMRAM_SAVE_STATE_MAP64;
+
+///
+/// Union of 32-bit and 64-bit SMRAM Save State Maps
+///
+typedef union  {
+  X58_SMRAM_SAVE_STATE_MAP32  x86;
+  X58_SMRAM_SAVE_STATE_MAP64  x64;
+} X58_SMRAM_SAVE_STATE_MAP;
+
+#pragma pack ()
+
+#endif
diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPkg.dec b/Silicon/Intel/SimicsX58SktPkg/SktPkg.dec
new file mode 100644
index 0000000000..9fbc546167
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktPkg.dec
@@ -0,0 +1,37 @@
+## @file
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = SimicsX58SktPkg
+  PACKAGE_GUID                   = 070FEC45-BF03-41C1-8D46-8BBE032A7C0C
+  PACKAGE_VERSION                = 0.91
+
+[Includes]
+  Include
+
+[Guids]
+  gSimicsX58PkgTokenSpaceGuid   = {0x5b276d20, 0x37d0, 0x4af0, {0x8d, 0x04, 0x47, 0x91, 0x2b, 0x7c, 0x1d, 0x44}}
+
+[PcdsFixedAtBuild]
+  ## The following setting controls how many megabytes we configure as TSEG on
+  #  X58, for SMRAM purposes. Permitted values are: 1, 2, 8. Other values cause
+  #  undefined behavior.
+  #
+  #  This PCD is only consulted if PcdSmmSmramRequire is TRUE (see below).
+  gSimicsX58PkgTokenSpaceGuid.PcdX58TsegMbytes|8|UINT8|0x20
+
+[PcdsFeatureFlag]
+  ## This feature flag enables SMM/SMRAM support. Note that it also requires
+  #  such support from the underlying QEMU instance; if that support is not
+  #  present, the firmware will reject continuing after a certain point.
+  #
+  #  The flag also acts as a general "security switch"; when TRUE, many
+  #  components will change behavior, with the goal of preventing a malicious
+  #  runtime OS from tampering with firmware structures (special memory ranges
+  #  used by OVMF, the varstore pflash chip, LockBox etc).
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire|FALSE|BOOLEAN|0x1e
diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc b/Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc
new file mode 100644
index 0000000000..af83c380b8
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktPkgPei.dsc
@@ -0,0 +1,14 @@
+## @file
+#  Component description file for the X58 SiPkg PEI drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+  #
+  # SEC Phase modules
+  #
+  UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
+  UefiCpuPkg/CpuMpPei/CpuMpPei.inf
diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
new file mode 100644
index 0000000000..b599df6e96
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the Simics X58 SiPkg DXE drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf
new file mode 100644
index 0000000000..5b9cd9ee25
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf
@@ -0,0 +1,10 @@
+## @file
+#  Component description file for the X58 SiPkg PEI drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+INF  UefiCpuPkg/CpuMpPei/CpuMpPei.inf
diff --git a/Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf
new file mode 100644
index 0000000000..5019e362e3
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf
@@ -0,0 +1,16 @@
+## @file
+#  Component description file for the X58 SiPkg PEI drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# SEC Phase modules
+#
+# The code in this FV handles the initial firmware startup, and
+# decompresses the PEI and DXE FVs which handles the rest of the boot sequence.
+#
+INF  RuleOverride=RESET_VECTOR USE = IA32 UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
diff --git a/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
new file mode 100644
index 0000000000..fdcb4fb9a7
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
@@ -0,0 +1,14 @@
+## @file
+#  Component description file for the Simics X58 SiPkg DXE drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly == FALSE
+  INF  $(SKT_PKG)/Smm/Access/SmmAccess2Dxe.inf
+  INF  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+!endif
+INF  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf
new file mode 100644
index 0000000000..eb8c8f93dd
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf
@@ -0,0 +1,54 @@
+## @file
+# A DXE_DRIVER providing SMRAM access by producing EFI_SMM_ACCESS2_PROTOCOL.
+#
+# X58 TSEG is expected to have been verified and set up by the SmmAccessPei
+# driver.
+#
+# Copyright (C) 2013, 2015, Red Hat, Inc.
+# Copyright (C) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmmAccess2Dxe
+  FILE_GUID                      = AC95AD3D-4366-44BF-9A62-E4B29D7A2206
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010400
+  ENTRY_POINT                    = SmmAccess2DxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SmmAccess2Dxe.c
+  SmramInternal.c
+  SmramInternal.h
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  SimicsX58SktPkg/SktPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  DebugLib
+  PcdLib
+  PciLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiSmmAccess2ProtocolGuid   ## PRODUCES
+
+[FeaturePcd]
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[Depex]
+  TRUE
diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf
new file mode 100644
index 0000000000..2b6b14f437
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf
@@ -0,0 +1,65 @@
+## @file
+# A PEIM with the following responsibilities:
+#
+# - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,
+# - verify & configure the X58 TSEG in the entry point,
+# - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose
+#   it via the gEfiAcpiVariableGuid GUIDed HOB.
+#
+# Copyright (C) 2013, 2015, Red Hat, Inc.
+# Copyright (C) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmmAccessPei
+  FILE_GUID                      = 6C0E75B4-B0B9-44D1-8210-3377D7B4E066
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SmmAccessPeiEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SmmAccessPei.c
+  SmramInternal.c
+  SmramInternal.h
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  SimicsX58SktPkg/SktPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[Guids]
+  gEfiAcpiVariableGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  HobLib
+  IoLib
+  PcdLib
+  PciLib
+  PeiServicesLib
+  PeimEntryPoint
+
+[FeaturePcd]
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[FixedPcd]
+  gSimicsX58PkgTokenSpaceGuid.PcdX58TsegMbytes
+
+[Ppis]
+  gPeiSmmAccessPpiGuid           ## PRODUCES
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h
new file mode 100644
index 0000000000..81180a9c8e
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h
@@ -0,0 +1,82 @@
+/** @file
+  Functions and types shared by the SMM accessor PEI and DXE modules.
+
+  Copyright (C) 2015, Red Hat, Inc.
+  Copyright (C) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Pi/PiMultiPhase.h>
+
+//
+// We'll have two SMRAM ranges.
+//
+// The first is a tiny one that hosts an SMM_S3_RESUME_STATE object, to be
+// filled in by the CPU SMM driver during normal boot, for the PEI instance of
+// the LockBox library (which will rely on the object during S3 resume).
+//
+// The other SMRAM range is the main one, for the SMM core and the SMM drivers.
+//
+typedef enum {
+  DescIdxSmmS3ResumeState = 0,
+  DescIdxMain             = 1,
+  DescIdxCount            = 2
+} DESCRIPTOR_INDEX;
+
+/**
+  Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and
+  OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,
+  from the D_LCK and T_EN bits.
+
+  PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on
+  the LockState and OpenState fields being up-to-date on entry, and they need
+  to restore the same invariant on exit, if they touch the bits in question.
+
+  @param[out] LockState  Reflects the D_LCK bit on output; TRUE iff SMRAM is
+                         locked.
+  @param[out] OpenState  Reflects the inverse of the T_EN bit on output; TRUE
+                         iff SMRAM is open.
+**/
+VOID
+GetStates (
+  OUT BOOLEAN *LockState,
+  OUT BOOLEAN *OpenState
+  );
+
+//
+// The functions below follow the PEI_SMM_ACCESS_PPI and
+// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This
+// pointers are removed (TSEG doesn't depend on them), and so is the
+// DescriptorIndex parameter (TSEG doesn't support range-wise locking).
+//
+// The LockState and OpenState members that are common to both
+// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in
+// isolation from the rest of the (non-shared) members.
+//
+
+EFI_STATUS
+SmramAccessOpen (
+  OUT BOOLEAN *LockState,
+  OUT BOOLEAN *OpenState
+  );
+
+EFI_STATUS
+SmramAccessClose (
+  OUT BOOLEAN *LockState,
+  OUT BOOLEAN *OpenState
+  );
+
+EFI_STATUS
+SmramAccessLock (
+  OUT    BOOLEAN *LockState,
+  IN OUT BOOLEAN *OpenState
+  );
+
+EFI_STATUS
+SmramAccessGetCapabilities (
+  IN BOOLEAN                  LockState,
+  IN BOOLEAN                  OpenState,
+  IN OUT UINTN                *SmramMapSize,
+  IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
+  );
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 2/7] SimicsIch10Pkg: Add Ich Pkg for SimicsIch10
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add Ich Pkg for SimicsIch10. It is added for simics Quick Start Platform project support

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 .../Library/ResetSystemLib/ResetSystemLib.c        | 137 +++
 .../Library/SmmSpiFlashCommonLib/SpiFlashCommon.c  | 194 +++++
 .../SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c    |  54 ++
 .../LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c | 935 +++++++++++++++++++++
 .../SmmControl/RuntimeDxe/SmmControl2Dxe.c         | 410 +++++++++
 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c      | 175 ++++
 Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec          |  26 +
 Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc      |  12 +
 .../Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf  |   9 +
 .../Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf   |   9 +
 .../Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf    |  13 +
 .../Include/Library/SpiFlashCommonLib.h            |  98 +++
 Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h   |  43 +
 Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h   |  94 +++
 .../SimicsIch10Pkg/Include/PchReservedResources.h  |  60 ++
 .../Intel/SimicsIch10Pkg/Include/Protocol/Spi.h    | 295 +++++++
 .../SimicsIch10Pkg/Include/Register/PchRegsPmc.h   | 647 ++++++++++++++
 .../SimicsIch10Pkg/Include/Register/PchRegsSpi.h   | 304 +++++++
 .../SimicsIch10Pkg/Include/Register/X58Ich10.h     | 114 +++
 .../IncludePrivate/Library/PchSpiCommonLib.h       | 396 +++++++++
 .../Library/ResetSystemLib/ResetSystemLib.inf      |  34 +
 .../SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf  |  50 ++
 .../BasePchSpiCommonLib/BasePchSpiCommonLib.inf    |  31 +
 .../SmmControl/RuntimeDxe/SmmControl2Dxe.inf       |  61 ++
 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h      |  23 +
 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf |  44 +
 26 files changed, 4268 insertions(+)
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Library/SpiFlashCommonLib.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/PchReservedResources.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Protocol/Spi.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsPmc.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsSpi.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Include/Register/X58Ich10.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/IncludePrivate/Library/PchSpiCommonLib.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.inf
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h
 create mode 100644 Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf

diff --git a/Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.c b/Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644
index 0000000000..ad3e4f455e
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,137 @@
+/** @file
+  Reset System Library functions for Simics ICH10
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Register/X58Ich10.h>
+
+
+VOID
+AcpiPmControl (
+  UINTN SuspendType
+  )
+{
+  ASSERT (SuspendType < 6);
+  DEBUG((EFI_D_ERROR, "SuspendType = 0x%x\n", SuspendType));
+
+  IoBitFieldWrite16 (ICH10_PMBASE_IO + 4, 10, 13, (UINT16) SuspendType);
+  IoOr16 (ICH10_PMBASE_IO + 0x04, BIT13);
+  CpuDeadLoop ();
+}
+
+/**
+  Calling this function causes a system-wide reset. This sets
+  all circuitry within the system to its initial state. This type of reset
+  is asynchronous to system operation and operates without regard to
+  cycle boundaries.
+
+  System reset should not return, if it returns, it means the system does
+  not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+  VOID
+  )
+{
+  DEBUG((EFI_D_ERROR, "ResetCold_CF9\n"));
+  IoWrite8 (0xCF9, BIT3 | BIT2 | BIT1); // 1st choice: PIIX3 RCR, RCPU|SRST
+  MicroSecondDelay (50);
+
+  DEBUG((EFI_D_ERROR, "ResetCold_Port64\n"));
+  IoWrite8 (0x64, 0xfe);         // 2nd choice: keyboard controller
+  CpuDeadLoop ();
+}
+
+/**
+  Calling this function causes a system-wide initialization. The processors
+  are set to their initial state, and pending cycles are not corrupted.
+
+  System reset should not return, if it returns, it means the system does
+  not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+  VOID
+  )
+{
+  DEBUG((EFI_D_ERROR, "ResetWarm\n"));
+  //
+  //BUGBUG workaround for warm reset
+  //
+  IoWrite8(0xCF9, BIT2 | BIT1);
+  MicroSecondDelay(50);
+
+  IoWrite8 (0x64, 0xfe);
+  CpuDeadLoop ();
+}
+
+/**
+  Calling this function causes the system to enter a power state equivalent
+  to the ACPI G2/S5 or G3 states.
+
+  System shutdown should not return, if it returns, it means the system does
+  not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+  VOID
+  )
+{
+  DEBUG((EFI_D_ERROR, "ResetShutdown\n"));
+  AcpiPmControl (0);
+  ASSERT (FALSE);
+}
+
+
+/**
+  Calling this function causes the system to enter a power state for capsule
+  update.
+
+  Reset update should not return, if it returns, it means the system does
+  not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+  VOID
+  )
+{
+  DEBUG((EFI_D_ERROR, "EnterS3WithImmediateWake\n"));
+  AcpiPmControl (1);
+  ASSERT (FALSE);
+}
+
+/**
+  This function causes a systemwide reset. The exact type of the reset is
+  defined by the EFI_GUID that follows the Null-terminated Unicode string passed
+  into ResetData. If the platform does not recognize the EFI_GUID in ResetData
+  the platform must pick a supported reset type to perform.The platform may
+  optionally log the parameters from any non-normal reset that occurs.
+
+  @param[in]  DataSize   The size, in bytes, of ResetData.
+  @param[in]  ResetData  The data buffer starts with a Null-terminated string,
+                         followed by the EFI_GUID.
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+  IN UINTN   DataSize,
+  IN VOID    *ResetData
+  )
+{
+  DEBUG((EFI_D_ERROR, "ResetPlatformSpecific\n"));
+  ResetCold ();
+}
diff --git a/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
new file mode 100644
index 0000000000..9e3461cbd6
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
@@ -0,0 +1,194 @@
+/** @file
+  Wrap EFI_SPI_PROTOCOL to provide some library level interfaces
+  for module use.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/SpiFlashCommonLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Protocol/Spi.h>
+
+
+EFI_SPI_PROTOCOL       *mSpiProtocol;
+
+//
+// FlashAreaBaseAddress and Size for boottime and runtime usage.
+//
+UINTN mFlashAreaBaseAddress = 0;
+UINTN mFlashAreaSize        = 0;
+
+/**
+  Enable block protection on the Serial Flash device.
+
+  @retval     EFI_SUCCESS       Opertion is successful.
+  @retval     EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Read NumBytes bytes of data from the address specified by
+  PAddress into Buffer.
+
+  @param[in]      Address       The starting physical address of the read.
+  @param[in,out]  NumBytes      On input, the number of bytes to read. On output, the number
+                                of bytes actually read.
+  @param[out]     Buffer        The destination data buffer for the read.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+  IN     UINTN                        Address,
+  IN OUT UINT32                       *NumBytes,
+     OUT UINT8                        *Buffer
+  )
+{
+  ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+  if ((NumBytes == NULL) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // This function is implemented specifically for those platforms
+  // at which the SPI device is memory mapped for read. So this
+  // function just do a memory copy for Spi Flash Read.
+  //
+  CopyMem (Buffer, (VOID *) Address, *NumBytes);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Write NumBytes bytes of data from Buffer to the address specified by
+  PAddresss.
+
+  @param[in]      Address         The starting physical address of the write.
+  @param[in,out]  NumBytes        On input, the number of bytes to write. On output,
+                                  the actual number of bytes written.
+  @param[in]      Buffer          The source data buffer for the write.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+  IN     UINTN                      Address,
+  IN OUT UINT32                     *NumBytes,
+  IN     UINT8                      *Buffer
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     Offset;
+  UINT32                    Length;
+  UINT32                    RemainingBytes;
+
+  ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+  if ((NumBytes == NULL) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ASSERT (Address >= mFlashAreaBaseAddress);
+
+  Offset = Address - mFlashAreaBaseAddress;
+
+  ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+  Status = EFI_SUCCESS;
+  RemainingBytes = *NumBytes;
+
+
+  while (RemainingBytes > 0) {
+    if (RemainingBytes > SECTOR_SIZE_4KB) {
+      Length = SECTOR_SIZE_4KB;
+    } else {
+      Length = RemainingBytes;
+    }
+    Status = mSpiProtocol->FlashWrite (
+                             mSpiProtocol,
+                             FlashRegionBios,
+                             (UINT32) Offset,
+                             Length,
+                             Buffer
+                             );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+    RemainingBytes -= Length;
+    Offset += Length;
+    Buffer += Length;
+  }
+
+  //
+  // Actual number of bytes written
+  //
+  *NumBytes -= RemainingBytes;
+
+  return Status;
+}
+
+/**
+  Erase the block starting at Address.
+
+  @param[in]  Address         The starting physical address of the block to be erased.
+                              This library assume that caller garantee that the PAddress
+                              is at the starting address of this block.
+  @param[in]  NumBytes        On input, the number of bytes of the logical block to be erased.
+                              On output, the actual number of bytes erased.
+
+  @retval     EFI_SUCCESS.      Opertion is successful.
+  @retval     EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+  IN    UINTN                     Address,
+  IN    UINTN                     *NumBytes
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               Offset;
+  UINTN               RemainingBytes;
+
+  ASSERT (NumBytes != NULL);
+  if (NumBytes == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ASSERT (Address >= mFlashAreaBaseAddress);
+
+  Offset = Address - mFlashAreaBaseAddress;
+
+  ASSERT ((*NumBytes % SECTOR_SIZE_4KB) == 0);
+  ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+  Status = EFI_SUCCESS;
+  RemainingBytes = *NumBytes;
+
+
+  Status = mSpiProtocol->FlashErase (
+                           mSpiProtocol,
+                           FlashRegionBios,
+                           (UINT32) Offset,
+                           (UINT32) RemainingBytes
+                           );
+  return Status;
+}
+
diff --git a/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
new file mode 100644
index 0000000000..984b7733c6
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
@@ -0,0 +1,54 @@
+/** @file
+  SMM Library instance of SPI Flash Common Library Class
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/SpiFlashCommonLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Protocol/Spi.h>
+
+extern EFI_SPI_PROTOCOL   *mSpiProtocol;
+
+extern UINTN mFlashAreaBaseAddress;
+extern UINTN mFlashAreaSize;
+
+/**
+  The library constructuor.
+
+  The function does the necessary initialization work for this library
+  instance.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
+  @param[in]  SystemTable       A pointer to the EFI system table.
+
+  @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
+                                It will ASSERT on error for debug version.
+  @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
+**/
+EFI_STATUS
+EFIAPI
+SmmSpiFlashCommonLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS Status;
+
+  mFlashAreaBaseAddress = (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+  mFlashAreaSize        = (UINTN)PcdGet32 (PcdFlashAreaSize);
+
+  //
+  // Locate the SMM SPI protocol.
+  //
+  Status = gSmst->SmmLocateProtocol (
+                    &gEfiSmmSpiProtocolGuid,
+                    NULL,
+                    (VOID **) &mSpiProtocol
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..bd08b2453b
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
@@ -0,0 +1,935 @@
+/** @file
+  PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Protocol/Spi.h>
+#include <IncludePrivate/Library/PchSpiCommonLib.h>
+#include <Register/X58Ich10.h>
+
+/**
+  Initialize an SPI protocol instance.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval EFI_SUCCESS             The protocol instance was properly initialized
+  @exception EFI_UNSUPPORTED      The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+  IN     SPI_INSTANCE       *SpiInstance
+  )
+{
+  UINTN           PchSpiBar0;
+
+  //
+  // Initialize the SPI protocol instance
+  //
+  SpiInstance->Signature                    = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+  SpiInstance->Handle                       = NULL;
+  SpiInstance->SpiProtocol.Revision         = PCH_SPI_SERVICES_REVISION;
+  SpiInstance->SpiProtocol.FlashRead        = SpiProtocolFlashRead;
+  SpiInstance->SpiProtocol.FlashWrite       = SpiProtocolFlashWrite;
+  SpiInstance->SpiProtocol.FlashErase       = SpiProtocolFlashErase;
+  SpiInstance->SpiProtocol.FlashReadSfdp    = SpiProtocolFlashReadSfdp;
+  SpiInstance->SpiProtocol.FlashReadJedecId = SpiProtocolFlashReadJedecId;
+  SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus;
+  SpiInstance->SpiProtocol.FlashReadStatus  = SpiProtocolFlashReadStatus;
+  SpiInstance->SpiProtocol.GetRegionAddress = SpiProtocolGetRegionAddress;
+  SpiInstance->SpiProtocol.ReadPchSoftStrap = SpiProtocolReadPchSoftStrap;
+  SpiInstance->SpiProtocol.ReadCpuSoftStrap = SpiProtocolReadCpuSoftStrap;
+
+  SpiInstance->PchAcpiBase = ICH10_PMBASE_IO;
+  ASSERT (SpiInstance->PchAcpiBase != 0);
+
+  PchSpiBar0 = RCRB + SPIBAR;
+
+  if (PchSpiBar0 == 0) {
+    DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));
+    ASSERT (FALSE);
+  }
+
+  if ((MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC) & B_PCH_SPI_HSFSC_FDV) == 0) {
+    DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use the Hardware Sequencing registers!\n"));
+    ASSERT (FALSE);
+  }
+  SpiInstance->ReadPermission = 0xffff;
+  SpiInstance->WritePermission = 0xffff;
+  DEBUG ((DEBUG_INFO, "Flash Region Permission: Read- 0x%04x; Write= 0x%04x\n",
+                                                SpiInstance->ReadPermission,
+                                                SpiInstance->WritePermission));
+
+  //
+  SpiInstance->TotalFlashSize = PcdGet32(PcdFlashAreaSize);
+  DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashSize));
+  return EFI_SUCCESS;
+}
+
+/**
+  Delay for at least the request number of microseconds for Runtime usage.
+
+  @param[in] ABase                Acpi base address
+  @param[in] Microseconds         Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+PchPmTimerStallRuntimeSafe (
+  IN  UINT16  ABase,
+  IN  UINTN   Microseconds
+  )
+{
+  UINTN   Ticks;
+  UINTN   Counts;
+  UINTN   CurrentTick;
+  UINTN   OriginalTick;
+  UINTN   RemainingTick;
+
+  if (Microseconds == 0) {
+    return;
+  }
+
+  OriginalTick   = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+  CurrentTick    = OriginalTick;
+
+  //
+  // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks
+  //
+  Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+  //
+  // The loops needed by timer overflow
+  //
+  Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+  //
+  // Remaining clocks within one loop
+  //
+  RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+  //
+  // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
+  // one I/O operation, and maybe generate SMI
+  //
+  while ((Counts != 0) || (RemainingTick > CurrentTick)) {
+    CurrentTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+    //
+    // Check if timer overflow
+    //
+    if ((CurrentTick < OriginalTick)) {
+      if (Counts != 0) {
+        Counts--;
+      } else {
+        //
+        // If timer overflow and Counts equ to 0, that means we already stalled more than
+        // RemainingTick, break the loop here
+        //
+        break;
+      }
+    }
+
+    OriginalTick = CurrentTick;
+  }
+}
+
+/**
+  Read data from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[out] Buffer              The Pointer to caller-allocated buffer containing the dada received.
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *Buffer
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionType,
+             FlashCycleRead,
+             Address,
+             ByteCount,
+             Buffer
+             );
+  return Status;
+}
+
+/**
+  Write data to the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[in] Buffer               Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *Buffer
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionType,
+             FlashCycleWrite,
+             Address,
+             ByteCount,
+             Buffer
+             );
+  return Status;
+}
+
+/**
+  Erase some area on the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionType,
+             FlashCycleErase,
+             Address,
+             ByteCount,
+             NULL
+             );
+  return Status;
+}
+
+/**
+  Read SFDP data from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] Address              The starting byte address for SFDP data read.
+  @param[in] ByteCount            Number of bytes in SFDP data portion of the SPI cycle
+  @param[out] SfdpData            The Pointer to caller-allocated buffer containing the SFDP data received
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *SfdpData
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  EFI_STATUS        Status;
+  UINT32            FlashAddress;
+
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  Status            = EFI_SUCCESS;
+
+  if (ComponentNumber > SpiInstance->NumberOfComponents) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FlashAddress = 0;
+  if (ComponentNumber == FlashComponent1) {
+    FlashAddress = SpiInstance->Component1StartAddr;
+  }
+  FlashAddress += Address;
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleReadSfdp,
+             FlashAddress,
+             ByteCount,
+             SfdpData
+             );
+  return Status;
+}
+
+/**
+  Read Jedec Id from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] ByteCount            Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+  @param[out] JedecId             The Pointer to caller-allocated buffer containing JEDEC ID received
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *JedecId
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  EFI_STATUS        Status;
+  UINT32            Address;
+
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  Status            = EFI_SUCCESS;
+
+  if (ComponentNumber > SpiInstance->NumberOfComponents) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Address = 0;
+  if (ComponentNumber == FlashComponent1) {
+    Address = SpiInstance->Component1StartAddr;
+  }
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleReadJedecId,
+             Address,
+             ByteCount,
+             JedecId
+             );
+  return Status;
+}
+
+/**
+  Write the status register in the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+  @param[in] StatusValue          The Pointer to caller-allocated buffer containing the value of Status register writing
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *StatusValue
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleWriteStatus,
+             0,
+             ByteCount,
+             StatusValue
+             );
+  return Status;
+}
+
+/**
+  Read status register in the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+  @param[out] StatusValue         The Pointer to caller-allocated buffer containing the value of Status register received.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *StatusValue
+  )
+{
+  EFI_STATUS        Status;
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionAll,
+             FlashCycleReadStatus,
+             0,
+             ByteCount,
+             StatusValue
+             );
+  return Status;
+}
+
+/**
+  Get the SPI region base and size, based on the enum type
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for for the base address which is listed in the Descriptor.
+  @param[out] BaseAddress         The Flash Linear Address for the Region 'n' Base
+  @param[out] RegionSize          The size for the Region 'n'
+
+  @retval EFI_SUCCESS             Read success
+  @retval EFI_INVALID_PARAMETER   Invalid region type given
+  @retval EFI_DEVICE_ERROR        The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  OUT    UINT32             *BaseAddress,
+  OUT    UINT32             *RegionSize
+  )
+{
+  SPI_INSTANCE    *SpiInstance;
+  UINTN           PchSpiBar0;
+  UINT32          ReadValue;
+
+  SpiInstance     = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+  if (FlashRegionType >= FlashRegionMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (FlashRegionType == FlashRegionAll) {
+    *BaseAddress  = 0;
+    *RegionSize   = SpiInstance->TotalFlashSize;
+    return EFI_SUCCESS;
+  }
+
+  PchSpiBar0      = AcquireSpiBar0 (SpiInstance);
+  ReadValue = MmioRead32 (PchSpiBar0 + (R_PCH_SPI_FREG0_FLASHD + (S_PCH_SPI_FREGX * ((UINT32) FlashRegionType))));
+  ReleaseSpiBar0 (SpiInstance);
+
+  //
+  // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+  //
+  if (ReadValue == B_PCH_SPI_FREGX_BASE_MASK) {
+    return EFI_DEVICE_ERROR;
+  }
+  *BaseAddress = ((ReadValue & B_PCH_SPI_FREGX_BASE_MASK) >> N_PCH_SPI_FREGX_BASE) <<
+                   N_PCH_SPI_FREGX_BASE_REPR;
+  //
+  // Region limit address Bits[11:0] are assumed to be FFFh
+  //
+  *RegionSize = ((((ReadValue & B_PCH_SPI_FREGX_LIMIT_MASK) >> N_PCH_SPI_FREGX_LIMIT) + 1) <<
+                  N_PCH_SPI_FREGX_LIMIT_REPR) - *BaseAddress;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read PCH Soft Strap Values
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SoftStrapAddr        PCH Soft Strap address offset from FPSBA.
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+                                  If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    VOID               *SoftStrapValue
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  UINT32            StrapFlashAddr;
+  EFI_STATUS        Status;
+
+  SpiInstance     = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+  if (ByteCount == 0) {
+    *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize;
+    return EFI_SUCCESS;
+  }
+
+  if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // PCH Strap Flash Address = FPSBA + RamAddr
+  //
+  StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr;
+
+  //
+  // Read PCH Soft straps from using execute command
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionDescriptor,
+             FlashCycleRead,
+             StrapFlashAddr,
+             ByteCount,
+             SoftStrapValue
+             );
+  return Status;
+}
+
+/**
+  Read CPU Soft Strap Values
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SoftStrapAddr        CPU Soft Strap address offset from FCPUSBA.
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle.
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+                                  If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    VOID               *SoftStrapValue
+  )
+{
+  SPI_INSTANCE      *SpiInstance;
+  UINT32            StrapFlashAddr;
+  EFI_STATUS        Status;
+
+  SpiInstance     = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+  if (ByteCount == 0) {
+    *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize;
+    return EFI_SUCCESS;
+  }
+
+  if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // CPU Strap Flash Address = FCPUSBA + RamAddr
+  //
+  StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;
+
+  //
+  // Read Cpu Soft straps from using execute command
+  //
+  Status = SendSpiCmd (
+             This,
+             FlashRegionDescriptor,
+             FlashCycleRead,
+             StrapFlashAddr,
+             ByteCount,
+             SoftStrapValue
+             );
+  return Status;
+}
+
+/**
+  This function sends the programmed SPI command to the slave device.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SpiRegionType        The SPI Region type for flash cycle which is listed in the Descriptor
+  @param[in] FlashCycleType       The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[in,out] Buffer           Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+  @retval EFI_SUCCESS             SPI command completes successfully.
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     FLASH_CYCLE_TYPE   FlashCycleType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  IN OUT UINT8              *Buffer
+  )
+{
+  EFI_STATUS      Status;
+  UINT32          Index;
+  SPI_INSTANCE    *SpiInstance;
+  UINTN           SpiBaseAddress;
+  UINTN           PchSpiBar0;
+  UINT32          HardwareSpiAddr;
+  UINT32          FlashRegionSize;
+  UINT32          SpiDataCount;
+  UINT32          FlashCycle;
+  UINT32          SmiEnSave;
+  UINT16          ABase;
+
+  Status            = EFI_SUCCESS;
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  SpiBaseAddress    = SpiInstance->PchSpiBase;
+  PchSpiBar0        = AcquireSpiBar0 (SpiInstance);
+  SpiBaseAddress    = SpiInstance->PchSpiBase;
+  ABase             = SpiInstance->PchAcpiBase;
+
+  //
+  // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+  // whose SMI handler accesses flash (e.g. for error logging)
+  //
+  // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'),
+  // clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+  // synchronization methods must be applied here or in the consumer of the
+  // SendSpiCmd. An example method is disabling the specific SMI sources
+  // whose SMI handlers access flash before flash cycle and re-enabling the SMI
+  // sources after the flash cycle .
+  //
+  SmiEnSave   = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
+  IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI));
+
+  //
+  // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect
+  //
+  if ((FlashCycleType == FlashCycleWrite) ||
+      (FlashCycleType == FlashCycleErase)) {
+    Status = DisableBiosWriteProtect ();
+    if (EFI_ERROR (Status)) {
+      goto SendSpiCmdEnd;
+    }
+  }
+  //
+  // Make sure it's safe to program the command.
+  //
+  if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {
+    Status = EFI_DEVICE_ERROR;
+    goto SendSpiCmdEnd;
+  }
+
+  Status = SpiProtocolGetRegionAddress (This, FlashRegionType, &HardwareSpiAddr, &FlashRegionSize);
+  if (EFI_ERROR (Status)) {
+    goto SendSpiCmdEnd;
+  }
+  HardwareSpiAddr += Address;
+  if ((Address + ByteCount) > FlashRegionSize) {
+    Status = EFI_INVALID_PARAMETER;
+    goto SendSpiCmdEnd;
+  }
+
+  //
+  // Check for PCH SPI hardware sequencing required commands
+  //
+  FlashCycle = 0;
+  switch (FlashCycleType) {
+    case FlashCycleRead:
+      FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ << N_PCH_SPI_HSFSC_CYCLE);
+      break;
+    case FlashCycleWrite:
+      FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE << N_PCH_SPI_HSFSC_CYCLE);
+      break;
+    case FlashCycleErase:
+      if (((ByteCount % SIZE_4KB) != 0) ||
+          ((HardwareSpiAddr % SIZE_4KB) != 0)) {
+        ASSERT (FALSE);
+        Status = EFI_INVALID_PARAMETER;
+        goto SendSpiCmdEnd;
+      }
+      break;
+    case FlashCycleReadSfdp:
+      FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_SFDP << N_PCH_SPI_HSFSC_CYCLE);
+      break;
+    case FlashCycleReadJedecId:
+      FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID << N_PCH_SPI_HSFSC_CYCLE);
+      break;
+    case FlashCycleWriteStatus:
+      FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+      break;
+    case FlashCycleReadStatus:
+      FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+      break;
+    default:
+      //
+      // Unrecognized Operation
+      //
+      ASSERT (FALSE);
+      Status = EFI_INVALID_PARAMETER;
+      goto SendSpiCmdEnd;
+      break;
+  }
+
+  do {
+    SpiDataCount = ByteCount;
+    if ((FlashCycleType == FlashCycleRead) ||
+        (FlashCycleType == FlashCycleWrite) ||
+        (FlashCycleType == FlashCycleReadSfdp)) {
+      //
+      // Trim at 256 byte boundary per operation,
+      // - PCH SPI controller requires trimming at 4KB boundary
+      // - Some SPI chips require trimming at 256 byte boundary for write operation
+      // - Trimming has limited performance impact as we can read / write atmost 64 byte
+      //   per operation
+      //
+      if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+        SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+      }
+      //
+      // Calculate the number of bytes to shift in/out during the SPI data cycle.
+      // Valid settings for the number of bytes duing each data portion of the
+      // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+      //
+      if (SpiDataCount >= 64) {
+        SpiDataCount = 64;
+      } else if ((SpiDataCount &~0x07) != 0) {
+        SpiDataCount = SpiDataCount &~0x07;
+      }
+    }
+    if (FlashCycleType == FlashCycleErase) {
+      if (((ByteCount / SIZE_64KB) != 0) &&
+          ((ByteCount % SIZE_64KB) == 0) &&
+          ((HardwareSpiAddr % SIZE_64KB) == 0)) {
+        if (HardwareSpiAddr < SpiInstance->Component1StartAddr) {
+          //
+          // Check whether Component0 support 64k Erase
+          //
+          if ((SpiInstance->SfdpVscc0Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+            SpiDataCount = SIZE_64KB;
+          } else {
+            SpiDataCount = SIZE_4KB;
+          }
+        } else {
+          //
+          // Check whether Component1 support 64k Erase
+          //
+          if ((SpiInstance->SfdpVscc1Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+            SpiDataCount = SIZE_64KB;
+          } else {
+            SpiDataCount = SIZE_4KB;
+          }
+        }
+      } else {
+        SpiDataCount = SIZE_4KB;
+      }
+      if (SpiDataCount == SIZE_4KB) {
+        FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_4K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+      } else {
+        FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_64K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+      }
+    }
+    //
+    // If it's write cycle, load data into the SPI data buffer.
+    //
+    if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {
+      if ((SpiDataCount & 0x07) != 0) {
+        //
+        // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+        //
+        for (Index = 0; Index < SpiDataCount; Index++) {
+          MmioWrite8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, Buffer[Index]);
+        }
+      } else {
+        //
+        // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+        //
+        for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+          MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, *(UINT32 *) (Buffer + Index));
+        }
+      }
+    }
+
+    //
+    // Set the Flash Address
+    //
+    MmioWrite32 (
+      (PchSpiBar0 + R_PCH_SPI_FADDR),
+      (UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK)
+      );
+
+    //
+    // Set Data count, Flash cycle, and Set Go bit to start a cycle
+    //
+    MmioAndThenOr32 (
+      PchSpiBar0 + R_PCH_SPI_HSFSC,
+      (UINT32) (~(B_PCH_SPI_HSFSC_FDBC_MASK | B_PCH_SPI_HSFSC_CYCLE_MASK)),
+      (UINT32) ((((SpiDataCount - 1) << N_PCH_SPI_HSFSC_FDBC) & B_PCH_SPI_HSFSC_FDBC_MASK) | FlashCycle | B_PCH_SPI_HSFSC_CYCLE_FGO)
+      );
+    //
+    // end of command execution
+    //
+    // Wait the SPI cycle to complete.
+    //
+    if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {
+      ASSERT (FALSE);
+      Status = EFI_DEVICE_ERROR;
+      goto SendSpiCmdEnd;
+    }
+    //
+    // If it's read cycle, load data into the call's buffer.
+    //
+    if ((FlashCycleType == FlashCycleRead) ||
+        (FlashCycleType == FlashCycleReadSfdp) ||
+        (FlashCycleType == FlashCycleReadJedecId) ||
+        (FlashCycleType == FlashCycleReadStatus)) {
+      if ((SpiDataCount & 0x07) != 0) {
+        //
+        // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+        //
+        for (Index = 0; Index < SpiDataCount; Index++) {
+          Buffer[Index] = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+        }
+      } else {
+        //
+        // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+        //
+        for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+          *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+        }
+      }
+    }
+
+    HardwareSpiAddr += SpiDataCount;
+    Buffer += SpiDataCount;
+    ByteCount -= SpiDataCount;
+  } while (ByteCount > 0);
+
+SendSpiCmdEnd:
+  //
+  // Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect
+  //
+  if ((FlashCycleType == FlashCycleWrite) ||
+      (FlashCycleType == FlashCycleErase)) {
+    EnableBiosWriteProtect ();
+  }
+  //
+  // Restore SMIs.
+  //
+  IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave);
+
+  ReleaseSpiBar0 (SpiInstance);
+  return Status;
+}
+
+/**
+  Wait execution cycle to complete on the SPI interface.
+
+  @param[in] This                 The SPI protocol instance
+  @param[in] PchSpiBar0           Spi MMIO base address
+  @param[in] ErrorCheck           TRUE if the SpiCycle needs to do the error check
+
+  @retval TRUE                    SPI cycle completed on the interface.
+  @retval FALSE                   Time out while waiting the SPI cycle to complete.
+                                  It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINTN              PchSpiBar0,
+  IN     BOOLEAN            ErrorCheck
+  )
+{
+  UINT64        WaitTicks;
+  UINT64        WaitCount;
+  UINT32        Data32;
+  SPI_INSTANCE  *SpiInstance;
+
+  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = SPI_WAIT_TIME / SPI_WAIT_PERIOD;
+  //
+  // Wait for the SPI cycle to complete.
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC);
+    if ((Data32 & B_PCH_SPI_HSFSC_SCIP) == 0) {
+      MmioWrite32 (PchSpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FCERR | B_PCH_SPI_HSFSC_FDONE);
+      if (((Data32 & B_PCH_SPI_HSFSC_FCERR) != 0) && (ErrorCheck == TRUE)) {
+        return FALSE;
+      } else {
+        return TRUE;
+      }
+    }
+    PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, SPI_WAIT_PERIOD);
+  }
+  return FALSE;
+}
diff --git a/Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.c b/Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.c
new file mode 100644
index 0000000000..268b04d25a
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.c
@@ -0,0 +1,410 @@
+/** @file
+  A DXE_RUNTIME_DRIVER providing synchronous SMI activations via the
+  EFI_SMM_CONTROL2_PROTOCOL.
+
+  We expect the PEI phase to have covered the following:
+  - ensure that the underlying QEMU machine type be X58
+    (responsible: OvmfPkg/SmmAccess/SmmAccessPei.inf)
+  - ensure that the ACPI PM IO space be configured
+    (responsible: OvmfPkg/PlatformPei/PlatformPei.inf)
+
+  Our own entry point is responsible for confirming the SMI feature and for
+  configuring it.
+
+  Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
+  Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Register/X58Ich10.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/S3SaveState.h>
+#include <Protocol/SmmControl2.h>
+
+//
+// Forward declaration.
+//
+STATIC
+VOID
+EFIAPI
+OnS3SaveStateInstalled (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  );
+
+//
+// The absolute IO port address of the SMI Control and Enable Register. It is
+// only used to carry information from the entry point function to the
+// S3SaveState protocol installation callback, strictly before the runtime
+// phase.
+//
+STATIC UINTN mSmiEnable;
+
+//
+// Event signaled when an S3SaveState protocol interface is installed.
+//
+STATIC EFI_EVENT mS3SaveStateInstalled;
+
+/**
+  Clear the SMI status
+
+  @retval EFI_SUCCESS             The function completes successfully
+  @retval EFI_DEVICE_ERROR        Something error occurred
+
+**/
+EFI_STATUS
+EFIAPI
+SmmClear(
+  VOID
+)
+{
+  EFI_STATUS  Status;
+  UINT32      OutputData;
+  UINT32      OutputPort;
+  UINT32     PmBase;
+
+  Status = EFI_SUCCESS;
+  PmBase = ICH10_PMBASE_IO;
+
+  OutputPort = PmBase + ICH10_PMBASE_OFS_SMI_STS;
+  OutputData = ICH10_SMI_STS_APM;
+  IoWrite32(
+    (UINTN)OutputPort,
+    (UINT32)(OutputData)
+  );
+
+  ///
+  /// Set the EOS Bit
+  ///
+  OutputPort = PmBase + ICH10_PMBASE_OFS_SMI_EN;
+  OutputData = IoRead32((UINTN)OutputPort);
+  OutputData |= ICH10_SMI_EN_EOS;
+  IoWrite32(
+    (UINTN)OutputPort,
+    (UINT32)(OutputData)
+  );
+
+  ///
+  /// There is no need to read EOS back and check if it is set.
+  /// This can lead to a reading of zero if an SMI occurs right after the SMI_EN port read
+  /// but before the data is returned to the CPU.
+  /// SMM Dispatcher should make sure that EOS is set after all SMI sources are processed.
+  ///
+  return Status;
+}
+
+/**
+  Invokes SMI activation from either the preboot or runtime environment.
+
+  This function generates an SMI.
+
+  @param[in]     This                The EFI_SMM_CONTROL2_PROTOCOL instance.
+  @param[in,out] CommandPort         The value written to the command port.
+  @param[in,out] DataPort            The value written to the data port.
+  @param[in]     Periodic            Optional mechanism to engender a periodic
+                                     stream.
+  @param[in]     ActivationInterval  Optional parameter to repeat at this
+                                     period one time or, if the Periodic
+                                     Boolean is set, periodically.
+
+  @retval EFI_SUCCESS            The SMI/PMI has been engendered.
+  @retval EFI_DEVICE_ERROR       The timing is unsupported.
+  @retval EFI_INVALID_PARAMETER  The activation period is unsupported.
+  @retval EFI_INVALID_PARAMETER  The last periodic activation has not been
+                                 cleared.
+  @retval EFI_NOT_STARTED        The SMM base service has not been initialized.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmControl2DxeTrigger (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL  *This,
+  IN OUT UINT8                        *CommandPort       OPTIONAL,
+  IN OUT UINT8                        *DataPort          OPTIONAL,
+  IN BOOLEAN                          Periodic           OPTIONAL,
+  IN UINTN                            ActivationInterval OPTIONAL
+  )
+{
+  EFI_STATUS  Status;
+  //
+  // No support for queued or periodic activation.
+  //
+  if (Periodic || ActivationInterval > 0) {
+    return EFI_DEVICE_ERROR;
+  }
+  ///
+  /// Clear any pending the APM SMI
+  ///
+  Status = SmmClear();
+  //
+  // The so-called "Advanced Power Management Status Port Register" is in fact
+  // a generic data passing register, between the caller and the SMI
+  // dispatcher. The ICH9 spec calls it "scratchpad register" --  calling it
+  // "status" elsewhere seems quite the misnomer. Status registers usually
+  // report about hardware status, while this register is fully governed by
+  // software.
+  //
+  // Write to the status register first, as this won't trigger the SMI just
+  // yet. Then write to the control register.
+  //
+  IoWrite8 (ICH10_APM_STS, DataPort    == NULL ? 0 : *DataPort);
+  IoWrite8 (ICH10_APM_CNT, CommandPort == NULL ? 0 : *CommandPort);
+  return EFI_SUCCESS;
+}
+
+/**
+  Clears any system state that was created in response to the Trigger() call.
+
+  This function acknowledges and causes the deassertion of the SMI activation
+  source.
+
+  @param[in] This                The EFI_SMM_CONTROL2_PROTOCOL instance.
+  @param[in] Periodic            Optional parameter to repeat at this period
+                                 one time
+
+  @retval EFI_SUCCESS            The SMI/PMI has been engendered.
+  @retval EFI_DEVICE_ERROR       The source could not be cleared.
+  @retval EFI_INVALID_PARAMETER  The service did not support the Periodic input
+                                 argument.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SmmControl2DxeClear (
+  IN CONST EFI_SMM_CONTROL2_PROTOCOL  *This,
+  IN BOOLEAN                          Periodic OPTIONAL
+  )
+{
+  EFI_STATUS  Status;
+
+  if (Periodic) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // The PI spec v1.4 explains that Clear() is only supposed to clear software
+  // status; it is not in fact responsible for deasserting the SMI. It gives
+  // two reasons for this: (a) many boards clear the SMI automatically when
+  // entering SMM, (b) if Clear() actually deasserted the SMI, then it could
+  // incorrectly suppress an SMI that was asynchronously asserted between the
+  // last return of the SMI handler and the call made to Clear().
+  //
+  // In fact QEMU automatically deasserts CPU_INTERRUPT_SMI in:
+  // - x86_cpu_exec_interrupt() [target-i386/seg_helper.c], and
+  // - kvm_arch_pre_run() [target-i386/kvm.c].
+  //
+  // So, nothing to do here.
+  //
+  Status = SmmClear();
+
+  return EFI_SUCCESS;
+}
+
+STATIC EFI_SMM_CONTROL2_PROTOCOL mControl2 = {
+  &SmmControl2DxeTrigger,
+  &SmmControl2DxeClear,
+  MAX_UINTN // MinimumTriggerPeriod -- we don't support periodic SMIs
+};
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+SmmControl2DxeEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  UINT32     PmBase;
+  UINT32     SmiEnableVal;
+  EFI_STATUS Status;
+
+  //
+  // This module should only be included if SMRAM support is required.
+  //
+  ASSERT (FeaturePcdGet (PcdSmmSmramRequire));
+
+  //
+  // Calculate the absolute IO port address of the SMI Control and Enable
+  // Register. (As noted at the top, the PEI phase has left us with a working
+  // ACPI PM IO space.)
+  //
+  PmBase = PciRead32 (POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE)) &
+             ICH10_PMBASE_MASK;
+  mSmiEnable = PmBase + ICH10_PMBASE_OFS_SMI_EN;
+
+  //
+  // If APMC_EN is pre-set in SMI_EN, that's QEMU's way to tell us that SMI
+  // support is not available. (For example due to KVM lacking it.) Otherwise,
+  // this bit is clear after each reset.
+  //
+  SmiEnableVal = IoRead32 (mSmiEnable);
+  if ((SmiEnableVal & ICH10_SMI_EN_APMC_EN) != 0) {
+    DEBUG ((EFI_D_ERROR, "%a: this X58 implementation lacks SMI\n",
+      __FUNCTION__));
+  }
+
+  //
+  // Otherwise, configure the board to inject an SMI when ICH10_APM_CNT is
+  // written to. (See the Trigger() method above.)
+  //
+  SmiEnableVal |= ICH10_SMI_EN_APMC_EN | ICH10_SMI_EN_GBL_SMI_EN;
+  IoWrite32 (mSmiEnable, SmiEnableVal);
+
+  //
+  // Prevent software from undoing the above (until platform reset).
+  //
+  PciOr16 (POWER_MGMT_REGISTER_ICH10 (ICH10_GEN_PMCON_1),
+            ICH10_GEN_PMCON_1_SMI_LOCK);
+
+  //
+  // If we can clear GBL_SMI_EN now, that means QEMU's SMI support is not
+  // appropriate.
+  //
+  IoWrite32 (mSmiEnable, SmiEnableVal & ~(UINT32)ICH10_SMI_EN_GBL_SMI_EN);
+  if (IoRead32 (mSmiEnable) != SmiEnableVal) {
+    DEBUG ((EFI_D_ERROR, "%a: failed to lock down GBL_SMI_EN\n",
+      __FUNCTION__));
+    goto FatalError;
+  }
+
+  VOID *Registration;
+
+  //
+  // On S3 resume the above register settings have to be repeated. Register a
+  // protocol notify callback that, when boot script saving becomes
+  // available, saves operations equivalent to the above to the boot script.
+  //
+  Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+                  OnS3SaveStateInstalled, NULL /* Context */,
+                  &mS3SaveStateInstalled);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: CreateEvent: %r\n", __FUNCTION__, Status));
+    goto FatalError;
+  }
+
+  Status = gBS->RegisterProtocolNotify (&gEfiS3SaveStateProtocolGuid,
+                  mS3SaveStateInstalled, &Registration);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: RegisterProtocolNotify: %r\n", __FUNCTION__,
+      Status));
+    goto ReleaseEvent;
+  }
+
+  //
+  // Kick the event right now -- maybe the boot script is already saveable.
+  //
+  Status = gBS->SignalEvent (mS3SaveStateInstalled);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: SignalEvent: %r\n", __FUNCTION__, Status));
+    goto ReleaseEvent;
+  }
+
+  //
+  // We have no pointers to convert to virtual addresses. The handle itself
+  // doesn't matter, as protocol services are not accessible at runtime.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+                  &gEfiSmmControl2ProtocolGuid, &mControl2,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: InstallMultipleProtocolInterfaces: %r\n",
+      __FUNCTION__, Status));
+    goto ReleaseEvent;
+  }
+
+  return EFI_SUCCESS;
+
+ReleaseEvent:
+  if (mS3SaveStateInstalled != NULL) {
+    gBS->CloseEvent (mS3SaveStateInstalled);
+  }
+
+FatalError:
+  //
+  // We really don't want to continue in this case.
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Notification callback for S3SaveState installation.
+
+  @param[in] Event    Event whose notification function is being invoked.
+
+  @param[in] Context  The pointer to the notification function's context, which
+                      is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+OnS3SaveStateInstalled (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_S3_SAVE_STATE_PROTOCOL *S3SaveState;
+  UINT32                     SmiEnOrMask, SmiEnAndMask;
+  UINT16                     GenPmCon1OrMask, GenPmCon1AndMask;
+
+  ASSERT (Event == mS3SaveStateInstalled);
+
+  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid,
+                  NULL /* Registration */, (VOID **)&S3SaveState);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // These operations were originally done, verified and explained in the entry
+  // point function of the driver.
+  //
+  SmiEnOrMask  = ICH10_SMI_EN_APMC_EN | ICH10_SMI_EN_GBL_SMI_EN;
+  SmiEnAndMask = MAX_UINT32;
+  Status = S3SaveState->Write (
+                          S3SaveState,
+                          EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE,
+                          EfiBootScriptWidthUint32,
+                          (UINT64)mSmiEnable,
+                          &SmiEnOrMask,
+                          &SmiEnAndMask
+                          );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE: %r\n",
+      __FUNCTION__, Status));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+
+  GenPmCon1OrMask  = ICH10_GEN_PMCON_1_SMI_LOCK;
+  GenPmCon1AndMask = MAX_UINT16;
+  Status = S3SaveState->Write (
+                          S3SaveState,
+                          EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE,
+                          EfiBootScriptWidthUint16,
+                          (UINT64)POWER_MGMT_REGISTER_ICH10 (ICH10_GEN_PMCON_1),
+                          &GenPmCon1OrMask,
+                          &GenPmCon1AndMask
+                          );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR,
+      "%a: EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE: %r\n", __FUNCTION__,
+      Status));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+
+  DEBUG ((EFI_D_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));
+  gBS->CloseEvent (Event);
+  mS3SaveStateInstalled = NULL;
+}
diff --git a/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c b/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c
new file mode 100644
index 0000000000..0baf730a48
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.c
@@ -0,0 +1,175 @@
+/** @file
+  PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PchSpi.h"
+
+//
+// Global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE          *mSpiInstance;
+//
+// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
+// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+// won't overlap with SMRAM range, and trusted.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32                mSpiResvMmioAddr;
+
+/**
+  <b>SPI Runtime SMM Module Entry Point</b>\n
+  - <b>Introduction</b>\n
+    The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM.
+
+  - @pre
+    - EFI_SMM_BASE2_PROTOCOL
+      - Documented in System Management Mode Core Interface Specification .
+
+  - @result
+    The SPI SMM driver produces @link _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL @endlink with GUID
+    gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
+
+  - <b>Integration Check List</b>\n
+    - This driver supports Descriptor Mode only.
+    - This driver supports Hardware Sequence only.
+    - When using SMM SPI Protocol to perform flash access in an SMI handler,
+      and the SMI occurrence is asynchronous to normal mode code execution,
+      proper synchronization mechanism must be applied, e.g. disable SMI before
+      the normal mode SendSpiCmd() starts and re-enable SMI after
+      the normal mode SendSpiCmd() completes.
+      @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
+      SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
+      not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]).
+      So the synchronization at caller level is likely needed.
+
+  @param[in] ImageHandle          Image handle of this driver.
+  @param[in] SystemTable          Global system service table.
+
+  @retval EFI_SUCCESS             Initialization complete.
+  @exception EFI_UNSUPPORTED      The chipset is unsupported by this driver.
+  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to initialize the driver.
+  @retval EFI_DEVICE_ERROR        Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+  IN EFI_HANDLE            ImageHandle,
+  IN EFI_SYSTEM_TABLE      *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Init PCH spi reserved MMIO address.
+  //
+  mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+
+  ///
+  /// Allocate pool for SPI protocol instance
+  ///
+  Status = gSmst->SmmAllocatePool (
+                    EfiRuntimeServicesData, /// MemoryType don't care
+                    sizeof (SPI_INSTANCE),
+                    (VOID **) &mSpiInstance
+                    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (mSpiInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+  ///
+  /// Initialize the SPI protocol instance
+  ///
+  Status = SpiProtocolConstructor (mSpiInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Install the SMM EFI_SPI_PROTOCOL interface
+  //
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &(mSpiInstance->Handle),
+                    &gEfiSmmSpiProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &(mSpiInstance->SpiProtocol)
+                    );
+  if (EFI_ERROR (Status)) {
+    gSmst->SmmFreePool (mSpiInstance);
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Acquire PCH spi mmio address.
+  It is not expected for this BAR0 to change because the SPI device is hidden
+  from the OS for SKL PCH LP/H B stepping and above (refer to section 3.5.1),
+  but if it is ever different from the preallocated address, reassign it back.
+  In SMM, it always override the BAR0 and returns the reserved MMIO range for SPI.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval PchSpiBar0              return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+  IN  SPI_INSTANCE                *SpiInstance
+  )
+{
+  //
+  // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+  //
+  return mSpiResvMmioAddr;
+}
+
+/**
+  Release pch spi mmio address. Do nothing.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+  IN  SPI_INSTANCE                *SpiInstance
+  )
+{
+}
+
+/**
+  This function is a hook for Spi to disable BIOS Write Protect
+
+  @retval EFI_SUCCESS             The protocol instance was properly initialized
+  @retval EFI_ACCESS_DENIED       The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+  VOID
+  )
+{
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+  VOID
+  )
+{
+}
diff --git a/Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec b/Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec
new file mode 100644
index 0000000000..ad0a599fc5
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Ich10Pkg.dec
@@ -0,0 +1,26 @@
+## @file
+# Copyright (c) 2014 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = Ich10Pkg
+  PACKAGE_GUID                   = 4E97AC4B-F64C-4008-BBDE-01CC3B0BAA6B
+  PACKAGE_VERSION                = 0.91
+
+[Includes]
+  Include
+
+[Ppis]
+
+[Guids]
+  gEfiPchTokenSpaceGuid = { 0x89a1b278, 0xa1a1, 0x4df7, { 0xb1, 0x37, 0xde, 0x5a, 0xd7, 0xc4, 0x79, 0x13 } }
+[Protocols]
+  gEfiSmmSpiProtocolGuid = {0xbd75fe35, 0xfdce, 0x49d7, {0xa9, 0xdd, 0xb2, 0x6f, 0x1f, 0xc6, 0xb4, 0x37}}
+
+[PcdsFixedAtBuild]
+  gEfiPchTokenSpaceGuid.PcdFlashAreaBaseAddress|0xFFE00000|UINT32|0x10000001
+  gEfiPchTokenSpaceGuid.PcdFlashAreaSize|0x00200000|UINT32|0x10000002
\ No newline at end of file
diff --git a/Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc b/Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
new file mode 100644
index 0000000000..f788fb89d9
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
@@ -0,0 +1,12 @@
+## @file
+#  Component description file for the Simics Ich10 SiPkg DXE libraries.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[LibraryClasses.common]
+  ResetSystemLib|$(PCH_PKG)/Library/ResetSystemLib/ResetSystemLib.inf
+  PchSpiCommonLib|$(PCH_PKG)/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
diff --git a/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf b/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
new file mode 100644
index 0000000000..8c9d3c4421
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the Simics Ich10 SiPkg DXE drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
diff --git a/Silicon/Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf b/Silicon/Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf
new file mode 100644
index 0000000000..079b81574b
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchPreMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the Ich10 SiPkg PEI drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
diff --git a/Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf b/Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
new file mode 100644
index 0000000000..8211a8a627
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
@@ -0,0 +1,13 @@
+## @file
+#  Component description file for the Simics Ich10 SiPkg DXE drivers.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly == FALSE
+  INF  $(PCH_PKG)/SmmControl/RuntimeDxe/SmmControl2Dxe.inf
+  INF  $(PCH_PKG)/Spi/Smm/PchSpiSmm.inf
+!endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/Library/SpiFlashCommonLib.h b/Silicon/Intel/SimicsIch10Pkg/Include/Library/SpiFlashCommonLib.h
new file mode 100644
index 0000000000..53c11bb59a
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/Library/SpiFlashCommonLib.h
@@ -0,0 +1,98 @@
+/** @file
+  The header file includes the common header files, defines
+  internal structure and functions used by SpiFlashCommonLib.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SPI_FLASH_COMMON_LIB_H__
+#define __SPI_FLASH_COMMON_LIB_H__
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define SECTOR_SIZE_4KB   0x1000      // Common 4kBytes sector size
+/**
+  Enable block protection on the Serial Flash device.
+
+  @retval     EFI_SUCCESS       Opertion is successful.
+  @retval     EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+  VOID
+  );
+
+/**
+  Read NumBytes bytes of data from the address specified by
+  PAddress into Buffer.
+
+  @param[in]      Address       The starting physical address of the read.
+  @param[in,out]  NumBytes      On input, the number of bytes to read. On output, the number
+                                of bytes actually read.
+  @param[out]     Buffer        The destination data buffer for the read.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+  IN     UINTN                        Address,
+  IN OUT UINT32                       *NumBytes,
+     OUT UINT8                        *Buffer
+  );
+
+/**
+  Write NumBytes bytes of data from Buffer to the address specified by
+  PAddresss.
+
+  @param[in]      Address         The starting physical address of the write.
+  @param[in,out]  NumBytes        On input, the number of bytes to write. On output,
+                                  the actual number of bytes written.
+  @param[in]      Buffer          The source data buffer for the write.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+  IN     UINTN                      Address,
+  IN OUT UINT32                     *NumBytes,
+  IN     UINT8                      *Buffer
+  );
+
+/**
+  Erase the block starting at Address.
+
+  @param[in]  Address         The starting physical address of the block to be erased.
+                              This library assume that caller garantee that the PAddress
+                              is at the starting address of this block.
+  @param[in]  NumBytes        On input, the number of bytes of the logical block to be erased.
+                              On output, the actual number of bytes erased.
+
+  @retval     EFI_SUCCESS.      Opertion is successful.
+  @retval     EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+  IN    UINTN                     Address,
+  IN    UINTN                     *NumBytes
+  );
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h b/Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h
new file mode 100644
index 0000000000..8be6ecd83b
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/PchAccess.h
@@ -0,0 +1,43 @@
+/** @file
+  Macros that simplify accessing PCH devices's PCI registers.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_ACCESS_H_
+#define _PCH_ACCESS_H_
+
+#include "PchReservedResources.h"
+
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_SECOND
+#define STALL_ONE_SECOND 1000000
+#endif
+
+
+///
+/// The default PCH PCI bus number
+///
+#define DEFAULT_PCI_BUS_NUMBER_PCH  0
+
+//
+// Default Vendor ID and Subsystem ID
+//
+#define V_PCH_INTEL_VENDOR_ID   0x8086      ///< Default Intel PCH Vendor ID
+#define V_PCH_DEFAULT_SID       0x7270      ///< Default Intel PCH Subsystem ID
+#define V_PCH_DEFAULT_SVID_SID  (V_INTEL_VENDOR_ID + (V_PCH_DEFAULT_SID << 16))   ///< Default INTEL PCH Vendor ID and Subsystem ID
+
+//
+// Include device register definitions
+//
+
+#include "Register/PchRegsPmc.h"
+
+#include "Register/PchRegsSpi.h"
+
+#endif
+
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h b/Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h
new file mode 100644
index 0000000000..35bb5741a8
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/PchLimits.h
@@ -0,0 +1,94 @@
+/** @file
+  Build time limits of PCH resources.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_LIMITS_H_
+#define _PCH_LIMITS_H_
+
+//
+// PCIe limits
+//
+#define PCH_MAX_PCIE_ROOT_PORTS             PCH_H_PCIE_MAX_ROOT_PORTS
+#define PCH_H_PCIE_MAX_ROOT_PORTS           20
+#define PCH_LP_PCIE_MAX_ROOT_PORTS          12
+
+#define PCH_MAX_PCIE_CONTROLLERS            PCH_H_PCIE_MAX_CONTROLLERS
+#define PCH_PCIE_CONTROLLER_PORTS           4
+#define PCH_H_PCIE_MAX_CONTROLLERS          (PCH_H_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+#define PCH_LP_PCIE_MAX_CONTROLLERS         (PCH_LP_PCIE_MAX_ROOT_PORTS / PCH_PCIE_CONTROLLER_PORTS)
+
+//
+// PCIe clocks limits
+//
+#define PCH_LP_PCIE_MAX_CLK_REQ             6
+#define PCH_H_PCIE_MAX_CLK_REQ              16
+
+//
+// RST PCIe Storage Cycle Router limits
+//
+#define PCH_MAX_RST_PCIE_STORAGE_CR         3
+
+//
+// SATA limits
+//
+#define PCH_MAX_SATA_PORTS                  PCH_H_AHCI_MAX_PORTS
+#define PCH_H_AHCI_MAX_PORTS                8       ///< Max number of sata ports in SKL PCH H
+#define PCH_LP_AHCI_MAX_PORTS               3       ///< Max number of sata ports in SKL PCH LP
+#define PCH_SATA_MAX_DEVICES_PER_PORT       1       ///< Max support device numner per port, Port Multiplier is not support.
+
+//
+// USB limits
+//
+#define PCH_MAX_USB2_PORTS                  PCH_H_XHCI_MAX_USB2_PORTS
+
+#define PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS  14      ///< Max Physical Connector XHCI, not counting virtual ports like USB-R.
+#define PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS 10      ///< Max Physical Connector XHCI, not counting virtual ports like USB-R.
+
+#define PCH_H_XHCI_MAX_USB2_PORTS           16      ///< 14 High Speed lanes + Including two ports reserved for USBr
+#define PCH_LP_XHCI_MAX_USB2_PORTS          12      ///< 10 High Speed lanes + Including two ports reserved for USBr
+
+#define PCH_MAX_USB3_PORTS                  PCH_H_XHCI_MAX_USB3_PORTS
+
+#define PCH_H_XHCI_MAX_USB3_PORTS           10      ///< 10 Super Speed lanes
+#define PCH_LP_XHCI_MAX_USB3_PORTS          6       ///< 6 Super Speed lanes
+
+#define PCH_XHCI_MAX_SSIC_PORT_COUNT        2       ///< 2 SSIC ports in SKL PCH-LP and SKL PCH-H
+
+//
+// SerialIo limits
+//
+#define PCH_SERIALIO_MAX_CONTROLLERS         11  ///< Number of SerialIo controllers, this includes I2C, SPI and UART
+#define PCH_SERIALIO_MAX_I2C_CONTROLLERS      6  ///< Number of SerialIo I2C controllers
+#define PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS   6  ///< Number of SerialIo I2C controllers for PCH-LP
+#define PCH_H_SERIALIO_MAX_I2C_CONTROLLERS    4  ///< Number of SerialIo I2C controllers for PCH-H
+#define PCH_SERIALIO_MAX_SPI_CONTROLLERS      2  ///< Number of SerialIo SPI controllers
+#define PCH_SERIALIO_MAX_UART_CONTROLLERS     3  ///< Number of SerialIo UART controllers
+
+//
+// ISH limits
+//
+#define PCH_ISH_MAX_GP_PINS                   8
+#define PCH_ISH_MAX_UART_CONTROLLERS          2
+#define PCH_ISH_MAX_I2C_CONTROLLERS           3
+#define PCH_ISH_MAX_SPI_CONTROLLERS           1
+
+//
+// SCS limits
+//
+#define PCH_SCS_MAX_CONTROLLERS            3  ///< Number of Storage and Communication Subsystem controllers, this includes eMMC, SDIO, SDCARD
+
+//
+// Flash Protection Range Register
+//
+#define PCH_FLASH_PROTECTED_RANGES         5
+
+//
+// Number of eSPI slaves
+//
+#define PCH_ESPI_MAX_SLAVE_ID              2
+#endif // _PCH_LIMITS_H_
+
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/PchReservedResources.h b/Silicon/Intel/SimicsIch10Pkg/Include/PchReservedResources.h
new file mode 100644
index 0000000000..5e978237dd
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/PchReservedResources.h
@@ -0,0 +1,60 @@
+/** @file
+  PCH preserved MMIO resource definitions.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_PRESERVED_RESOURCES_H_
+#define _PCH_PRESERVED_RESOURCES_H_
+
+/**
+  PCH preserved MMIO range, 24 MB, from 0xFD000000 to 0xFE7FFFFF
+
+  Detailed recommended static allocation
+  +-------------------------------------------------------------------------+
+  | Size        | Start       | End         | Usage                         |
+  | 16 MB       | 0xFD000000  | 0xFDFFFFFF  | SBREG                         |
+  | 64 KB       | 0xFE000000  | 0xFE00FFFF  | PMC MBAR                      |
+  | 4 KB        | 0xFE010000  | 0xFE010FFF  | SPI BAR0                      |
+  | 88 KB       | 0xFE020000  | 0xFE035FFF  | SerialIo BAR in ACPI mode     |
+  | 24 KB       | 0xFE036000  | 0xFE03BFFF  | Unused                        |
+  | 4 KB        | 0xFE03C000  | 0xFE03CFFF  | Thermal Device in ACPI mode   |
+  | 524 KB      | 0xFE03D000  | 0xFE0BFFFF  | Unused                        |
+  | 256 KB      | 0xFE0C0000  | 0xFE0FFFFF  | TraceHub FW BAR               |
+  | 1 MB        | 0xFE100000  | 0xFE1FFFFF  | TraceHub MTB BAR              |
+  | 2 MB        | 0xFE200000  | 0xFE3FFFFF  | TraceHub SW BAR               |
+  | 64 KB       | 0xFE400000  | 0xFE40FFFF  | CIO2 MMIO BAR in ACPI mode    |
+  | 2 MB - 64KB | 0xFE410000  | 0xFE5FFFFF  | Unused                        |
+  | 2 MB        | 0xFE600000  | 0xFE7FFFFF  | Temp address                  |
+  +-------------------------------------------------------------------------+
+**/
+#define PCH_PRESERVED_BASE_ADDRESS      0xFD000000     ///< Pch preserved MMIO base address
+#define PCH_PRESERVED_MMIO_SIZE         0x01800000     ///< 24MB
+#define PCH_PCR_BASE_ADDRESS            0xFD000000     ///< SBREG MMIO base address
+#define PCH_PCR_MMIO_SIZE               0x01000000     ///< 16MB
+#define PCH_PWRM_BASE_ADDRESS           0xFE000000     ///< PMC MBAR MMIO base address
+#define PCH_PWRM_MMIO_SIZE              0x00010000     ///< 64KB
+#define PCH_SPI_BASE_ADDRESS            0xFED1C000 + 0x3800     ///< SPI MBAR MMIO base address
+#define PCH_SPI_MMIO_SIZE               0x00001000     ///< 4KB
+#define PCH_SERIAL_IO_BASE_ADDRESS      0xFE020000     ///< SerialIo MMIO base address
+#define PCH_SERIAL_IO_MMIO_SIZE         0x00016000     ///< 88KB
+#define PCH_THERMAL_BASE_ADDRESS        0xFE03C000     ///< Thermal Device in ACPI mode
+#define PCH_THERMAL_MMIO_SIZE           0x00001000     ///< 4KB
+#define PCH_TRACE_HUB_FW_BASE_ADDRESS   0xFE0C0000     ///< TraceHub FW MMIO base address
+#define PCH_TRACE_HUB_FW_MMIO_SIZE      0x00040000     ///< 256KB
+#define PCH_TRACE_HUB_MTB_BASE_ADDRESS  0xFE100000     ///< TraceHub MTB MMIO base address
+#define PCH_TRACE_HUB_MTB_MMIO_SIZE     0x00100000     ///< 1MB
+#define PCH_TRACE_HUB_SW_BASE_ADDRESS   0xFE200000     ///< TraceHub SW MMIO base address
+#define PCH_TRACE_HUB_SW_MMIO_SIZE      0x00200000     ///< 2MB
+#define PCH_CIO2_BASE_ADDRESS           0xFE400000     ///< CIO2 MMIO BAR in ACPI mode
+#define PCH_CIO2_MMIO_SIZE              0x00010000     ///< 64KB
+#define PCH_TEMP_BASE_ADDRESS           0xFE600000     ///< preserved temp address for misc usage
+#define PCH_TEMP_MMIO_SIZE              0x00200000     ///< 2MB
+
+#define RCRB                            0xFED1C000
+#define SPIBAR                            0x3800
+
+#endif // _PCH_PRESERVED_RESOURCES_H_
+
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/Protocol/Spi.h b/Silicon/Intel/SimicsIch10Pkg/Include/Protocol/Spi.h
new file mode 100644
index 0000000000..b0c5b3d0e6
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/Protocol/Spi.h
@@ -0,0 +1,295 @@
+/** @file
+  This file defines the PCH SPI Protocol which implements the
+  Intel(R) PCH SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SPI_PROTOCOL_H_
+#define _PCH_SPI_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                   gEfiSpiProtocolGuid;
+extern EFI_GUID                   gEfiSmmSpiProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SPI_PROTOCOL  EFI_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+
+/**
+  Flash Region Type
+**/
+typedef enum {
+  FlashRegionDescriptor,
+  FlashRegionBios,
+  FlashRegionMe,
+  FlashRegionGbE,
+  FlashRegionPlatformData,
+  FlashRegionDer,
+  FlashRegionAll,
+  FlashRegionMax
+} FLASH_REGION_TYPE;
+
+
+//
+// Protocol member functions
+//
+
+/**
+  Read data from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[out] Buffer              The Pointer to caller-allocated buffer containing the dada received.
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *Buffer
+  );
+
+/**
+  Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[in] Buffer               Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *Buffer
+  );
+
+/**
+  Erase some area on the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_ERASE) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount
+  );
+
+/**
+  Read SFDP data from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] Address              The starting byte address for SFDP data read.
+  @param[in] ByteCount            Number of bytes in SFDP data portion of the SPI cycle
+  @param[out] SfdpData            The Pointer to caller-allocated buffer containing the SFDP data received
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_SFDP) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *SfdpData
+  );
+
+/**
+  Read Jedec Id from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] ByteCount            Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+  @param[out] JedecId             The Pointer to caller-allocated buffer containing JEDEC ID received
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *JedecId
+  );
+
+/**
+  Write the status register in the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+  @param[in] StatusValue          The Pointer to caller-allocated buffer containing the value of Status register writing
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *StatusValue
+  );
+
+/**
+  Read status register in the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+  @param[out] StatusValue         The Pointer to caller-allocated buffer containing the value of Status register received.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_STATUS) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *StatusValue
+  );
+
+/**
+  Get the SPI region base and size, based on the enum type
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for for the base address which is listed in the Descriptor.
+  @param[out] BaseAddress         The Flash Linear Address for the Region 'n' Base
+  @param[out] RegionSize          The size for the Region 'n'
+
+  @retval EFI_SUCCESS             Read success
+  @retval EFI_INVALID_PARAMETER   Invalid region type given
+  @retval EFI_DEVICE_ERROR        The region is not used
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  OUT    UINT32             *BaseAddress,
+  OUT    UINT32             *RegionSize
+  );
+
+/**
+  Read PCH Soft Strap Values
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SoftStrapAddr        PCH Soft Strap address offset from FPSBA.
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+                                  If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    VOID               *SoftStrapValue
+  );
+
+/**
+  Read CPU Soft Strap Values
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SoftStrapAddr        CPU Soft Strap address offset from FCPUSBA.
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle.
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+                                  If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    VOID               *SoftStrapValue
+  );
+
+/**
+  These protocols/PPI allows a platform module to perform SPI operations through the
+  Intel PCH SPI Host Controller Interface.
+**/
+struct _PCH_SPI_PROTOCOL {
+  /**
+    This member specifies the revision of this structure. This field is used to
+    indicate backwards compatible changes to the protocol.
+  **/
+  UINT8                             Revision;
+  PCH_SPI_FLASH_READ                FlashRead;          ///< Read data from the flash part.
+  PCH_SPI_FLASH_WRITE               FlashWrite;         ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+  PCH_SPI_FLASH_ERASE               FlashErase;         ///< Erase some area on the flash part.
+  PCH_SPI_FLASH_READ_SFDP           FlashReadSfdp;      ///< Read SFDP data from the flash part.
+  PCH_SPI_FLASH_READ_JEDEC_ID       FlashReadJedecId;   ///< Read Jedec Id from the flash part.
+  PCH_SPI_FLASH_WRITE_STATUS        FlashWriteStatus;   ///< Write the status register in the flash part.
+  PCH_SPI_FLASH_READ_STATUS         FlashReadStatus;    ///< Read status register in the flash part.
+  PCH_SPI_GET_REGION_ADDRESS        GetRegionAddress;   ///< Get the SPI region base and size
+  PCH_SPI_READ_PCH_SOFTSTRAP        ReadPchSoftStrap;   ///< Read PCH Soft Strap Values
+  PCH_SPI_READ_CPU_SOFTSTRAP        ReadCpuSoftStrap;   ///< Read CPU Soft Strap Values
+};
+
+/**
+  PCH SPI PPI/PROTOCOL revision number
+
+  Revision 1:   Initial version
+**/
+#define PCH_SPI_SERVICES_REVISION       1
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsPmc.h b/Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsPmc.h
new file mode 100644
index 0000000000..4c495475cb
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsPmc.h
@@ -0,0 +1,647 @@
+/** @file
+  Register names for PCH PMC device
+
+  Conventions:
+
+  - Prefixes:
+    Definitions beginning with "R_" are registers
+    Definitions beginning with "B_" are bits within registers
+    Definitions beginning with "V_" are meaningful values within the bits
+    Definitions beginning with "S_" are register sizes
+    Definitions beginning with "N_" are the bit position
+  - In general, PCH registers are denoted by "_PCH_" in register names
+  - Registers / bits that are different between PCH generations are denoted by
+    "_PCH_[generation_name]_" in register/bit names.
+  - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+    Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+    e.g., "_PCH_H_", "_PCH_LP_"
+    Registers / bits names without _H_ or _LP_ apply for both H and LP.
+  - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+    at the end of the register/bit names
+  - Registers / bits of new devices introduced in a PCH generation will be just named
+    as "_PCH_" without [generation_name] inserted.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_REGS_PMC_H_
+#define _PCH_REGS_PMC_H_
+
+//
+// PMC Registers (D31:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_PMC                           31
+#define PCI_FUNCTION_NUMBER_PCH_PMC                         2
+
+#define R_PCH_PMC_PM_DATA_BAR                               0x10
+#define B_PCH_PMC_PM_DATA_BAR                               0xFFFFC000
+#define R_PCH_PMC_ACPI_BASE                                 0x40
+#define B_PCH_PMC_ACPI_BASE_BAR                             0xFFFC
+#define R_PCH_PMC_ACPI_CNT                                  0x44
+#define B_PCH_PMC_ACPI_CNT_PWRM_EN                          BIT8                          ///< PWRM enable
+#define B_PCH_PMC_ACPI_CNT_ACPI_EN                          BIT7                          ///< ACPI eanble
+#define B_PCH_PMC_ACPI_CNT_SCIS                             (BIT2 | BIT1 | BIT0)          ///< SCI IRQ select
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ9                        0
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ10                       1
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ11                       2
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ20                       4
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ21                       5
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ22                       6
+#define V_PCH_PMC_ACPI_CNT_SCIS_IRQ23                       7
+#define R_PCH_PMC_PWRM_BASE                                 0x48
+#define B_PCH_PMC_PWRM_BASE_BAR                             0xFFFF0000                    ///< PWRM must be 64KB alignment to align the source decode.
+#define R_PCH_PMC_GEN_PMCON_A                               0xA0
+#define B_PCH_PMC_GEN_PMCON_A_DC_PP_DIS                     BIT30
+#define B_PCH_PMC_GEN_PMCON_A_DSX_PP_DIS                    BIT29
+#define B_PCH_PMC_GEN_PMCON_A_AG3_PP_EN                     BIT28
+#define B_PCH_PMC_GEN_PMCON_A_SX_PP_EN                      BIT27
+#define B_PCH_PMC_GEN_PMCON_A_DISB                          BIT23
+#define B_PCH_PMC_GEN_PMCON_A_MEM_SR                        BIT21
+#define B_PCH_PMC_GEN_PMCON_A_MS4V                          BIT18
+#define B_PCH_PMC_GEN_PMCON_A_GBL_RST_STS                   BIT16
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_OPI_PLL_SD_INC0         BIT13
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_SPXB_CG_INC0            BIT12
+#define B_PCH_PMC_GEN_PMCON_A_BIOS_PCI_EXP_EN               BIT10
+#define B_PCH_PMC_GEN_PMCON_A_PWRBTN_LVL                    BIT9
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_C0                BIT7
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_OPI_ON            BIT6
+#define B_PCH_PMC_GEN_PMCON_A_ALLOW_L1LOW_BCLKREQ_ON        BIT5
+#define B_PCH_PMC_GEN_PMCON_A_SMI_LOCK                      BIT4
+#define B_PCH_PMC_GEN_PMCON_A_ESPI_SMI_LOCK                 BIT3             ///< ESPI SMI lock
+#define B_PCH_PMC_GEN_PMCON_A_PER_SMI_SEL                   0x0003
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_64S                   0x0000
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_32S                   0x0001
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_16S                   0x0002
+#define V_PCH_PMC_GEN_PMCON_A_PER_SMI_8S                    0x0003
+#define R_PCH_PMC_GEN_PMCON_B                               0xA4
+#define B_PCH_PMC_GEN_PMCON_B_SLPSX_STR_POL_LOCK            BIT18            ///< Lock down SLP_S3/SLP_S4 Minimum Assertion width
+#define B_PCH_PMC_GEN_PMCON_B_ACPI_BASE_LOCK                BIT17            ///< Lock ACPI BASE at 0x40, only cleared by reset when set
+#define B_PCH_PMC_GEN_PMCON_B_PM_DATA_BAR_DIS               BIT16
+#define B_PCH_PMC_GEN_PMCON_B_PME_B0_S5_DIS                 BIT15
+#define B_PCH_PMC_GEN_PMCON_B_SUS_PWR_FLR                   BIT14
+#define B_PCH_PMC_GEN_PMCON_B_WOL_EN_OVRD                   BIT13
+#define B_PCH_PMC_GEN_PMCON_B_DISABLE_SX_STRETCH            BIT12
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW                    0xC00
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_60US               0x000
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_1MS                0x400
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_50MS               0x800
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S3_MAW_2S                 0xC00
+#define B_PCH_PMC_GEN_PMCON_B_HOST_RST_STS                  BIT9
+#define B_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL                    0xC0
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_64MS               0xC0
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_32MS               0x80
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_16MS               0x40
+#define V_PCH_PMC_GEN_PMCON_B_SWSMI_RTSL_1_5MS              0x00
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW                    0x30
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_1S                 0x30
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_2S                 0x20
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_3S                 0x10
+#define V_PCH_PMC_GEN_PMCON_B_SLP_S4_MAW_4S                 0x00
+#define B_PCH_PMC_GEN_PMCON_B_SLP_S4_ASE                    BIT3
+#define B_PCH_PMC_GEN_PMCON_B_RTC_PWR_STS                   BIT2
+#define B_PCH_PMC_GEN_PMCON_B_PWR_FLR                       BIT1
+#define B_PCH_PMC_GEN_PMCON_B_AFTERG3_EN                    BIT0
+#define R_PCH_PMC_BM_CX_CNF                                 0xA8
+#define B_PCH_PMC_BM_CX_CNF_STORAGE_BREAK_EN                BIT31
+#define B_PCH_PMC_BM_CX_CNF_PCIE_BREAK_EN                   BIT30
+#define B_PCH_PMC_BM_CX_CNF_AZ_BREAK_EN                     BIT24
+#define B_PCH_PMC_BM_CX_CNF_DPSN_BREAK_EN                   BIT19
+#define B_PCH_PMC_BM_CX_CNF_XHCI_BREAK_EN                   BIT17
+#define B_PCH_PMC_BM_CX_CNF_SATA3_BREAK_EN                  BIT16
+#define B_PCH_PMC_BM_CX_CNF_SCRATCHPAD                      BIT15
+#define B_PCH_PMC_BM_CX_CNF_PHOLD_BM_STS_BLOCK              BIT14
+#define B_PCH_PMC_BM_CX_CNF_MASK_CF                         BIT11
+#define B_PCH_PMC_BM_CX_CNF_BM_STS_ZERO_EN                  BIT10
+#define B_PCH_PMC_BM_CX_CNF_PM_SYNC_MSG_MODE                BIT9
+#define R_PCH_PMC_ETR3                                      0xAC
+#define B_PCH_PMC_ETR3_CF9LOCK                              BIT31           ///< CF9h Lockdown
+#define B_PCH_PMC_ETR3_USB_CACHE_DIS                        BIT21
+#define B_PCH_PMC_ETR3_CF9GR                                BIT20           ///< CF9h Global Reset
+#define B_PCH_PMC_ETR3_SKIP_HOST_RST_HS                     BIT19
+#define B_PCH_PMC_ETR3_CWORWRE                              BIT18
+
+//
+// ACPI and legacy I/O register offsets from ACPIBASE
+//
+#define R_PCH_ACPI_PM1_STS                        0x00
+#define S_PCH_ACPI_PM1_STS                        2
+#define B_PCH_ACPI_PM1_STS_WAK                    BIT15
+#define B_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS        BIT14
+#define B_PCH_ACPI_PM1_STS_PRBTNOR                BIT11
+#define B_PCH_ACPI_PM1_STS_RTC                    BIT10
+#define B_PCH_ACPI_PM1_STS_PWRBTN                 BIT8
+#define B_PCH_ACPI_PM1_STS_GBL                    BIT5
+#define B_PCH_ACPI_PM1_STS_BM                     BIT4
+#define B_PCH_ACPI_PM1_STS_TMROF                  BIT0
+#define N_PCH_ACPI_PM1_STS_WAK                    15
+#define N_PCH_ACPI_PM1_STS_PCIEXP_WAKE_STS        14
+#define N_PCH_ACPI_PM1_STS_PRBTNOR                11
+#define N_PCH_ACPI_PM1_STS_RTC                    10
+#define N_PCH_ACPI_PM1_STS_PWRBTN                 8
+#define N_PCH_ACPI_PM1_STS_GBL                    5
+#define N_PCH_ACPI_PM1_STS_BM                     4
+#define N_PCH_ACPI_PM1_STS_TMROF                  0
+
+#define R_PCH_ACPI_PM1_EN                         0x02
+#define S_PCH_ACPI_PM1_EN                         2
+#define B_PCH_ACPI_PM1_EN_PCIEXP_WAKE_DIS         BIT14
+#define B_PCH_ACPI_PM1_EN_RTC                     BIT10
+#define B_PCH_ACPI_PM1_EN_PWRBTN                  BIT8
+#define B_PCH_ACPI_PM1_EN_GBL                     BIT5
+#define B_PCH_ACPI_PM1_EN_TMROF                   BIT0
+#define N_PCH_ACPI_PM1_EN_PCIEXP_WAKE_DIS         14
+#define N_PCH_ACPI_PM1_EN_RTC                     10
+#define N_PCH_ACPI_PM1_EN_PWRBTN                  8
+#define N_PCH_ACPI_PM1_EN_GBL                     5
+#define N_PCH_ACPI_PM1_EN_TMROF                   0
+
+#define R_PCH_ACPI_PM1_CNT                        0x04
+#define S_PCH_ACPI_PM1_CNT                        4
+#define B_PCH_ACPI_PM1_CNT_SLP_EN                 BIT13
+#define B_PCH_ACPI_PM1_CNT_SLP_TYP                (BIT12 | BIT11 | BIT10)
+#define V_PCH_ACPI_PM1_CNT_S0                     0
+#define V_PCH_ACPI_PM1_CNT_S1                     BIT10
+#define V_PCH_ACPI_PM1_CNT_S3                     (BIT12 | BIT10)
+#define V_PCH_ACPI_PM1_CNT_S4                     (BIT12 | BIT11)
+#define V_PCH_ACPI_PM1_CNT_S5                     (BIT12 | BIT11 | BIT10)
+#define B_PCH_ACPI_PM1_CNT_GBL_RLS                BIT2
+#define B_PCH_ACPI_PM1_CNT_BM_RLD                 BIT1
+#define B_PCH_ACPI_PM1_CNT_SCI_EN                 BIT0
+
+#define R_PCH_ACPI_PM1_TMR                        0x08
+#define V_PCH_ACPI_TMR_FREQUENCY                  3579545
+#define B_PCH_ACPI_PM1_TMR_VAL                    0xFFFFFF
+#define V_PCH_ACPI_PM1_TMR_MAX_VAL                0x1000000       ///< The timer is 24 bit overflow
+
+#define R_PCH_SMI_EN                              0x30
+#define S_PCH_SMI_EN                              4
+#define B_PCH_SMI_EN_LEGACY_USB3                  BIT31
+#define B_PCH_SMI_EN_GPIO_UNLOCK_SMI              BIT27
+#define B_PCH_SMI_EN_LEGACY_USB2                  BIT17
+#define B_PCH_SMI_EN_PERIODIC                     BIT14
+#define B_PCH_SMI_EN_TCO                          BIT13
+#define B_PCH_SMI_EN_MCSMI                        BIT11
+#define B_PCH_SMI_EN_BIOS_RLS                     BIT7
+#define B_PCH_SMI_EN_SWSMI_TMR                    BIT6
+#define B_PCH_SMI_EN_APMC                         BIT5
+#define B_PCH_SMI_EN_ON_SLP_EN                    BIT4
+#define B_PCH_SMI_EN_LEGACY_USB                   BIT3
+#define B_PCH_SMI_EN_BIOS                         BIT2
+#define B_PCH_SMI_EN_EOS                          BIT1
+#define B_PCH_SMI_EN_GBL_SMI                      BIT0
+#define N_PCH_SMI_EN_LEGACY_USB3                  31
+#define N_PCH_SMI_EN_ESPI                         28
+#define N_PCH_SMI_EN_GPIO_UNLOCK                  27
+#define N_PCH_SMI_EN_INTEL_USB2                   18
+#define N_PCH_SMI_EN_LEGACY_USB2                  17
+#define N_PCH_SMI_EN_PERIODIC                     14
+#define N_PCH_SMI_EN_TCO                          13
+#define N_PCH_SMI_EN_MCSMI                        11
+#define N_PCH_SMI_EN_BIOS_RLS                     7
+#define N_PCH_SMI_EN_SWSMI_TMR                    6
+#define N_PCH_SMI_EN_APMC                         5
+#define N_PCH_SMI_EN_ON_SLP_EN                    4
+#define N_PCH_SMI_EN_LEGACY_USB                   3
+#define N_PCH_SMI_EN_BIOS                         2
+#define N_PCH_SMI_EN_EOS                          1
+#define N_PCH_SMI_EN_GBL_SMI                      0
+
+#define R_PCH_SMI_STS                             0x34
+#define S_PCH_SMI_STS                             4
+#define B_PCH_SMI_STS_LEGACY_USB3                 BIT31
+#define B_PCH_SMI_STS_GPIO_UNLOCK                 BIT27
+#define B_PCH_SMI_STS_SPI                         BIT26
+#define B_PCH_SMI_STS_MONITOR                     BIT21
+#define B_PCH_SMI_STS_PCI_EXP                     BIT20
+#define B_PCH_SMI_STS_PATCH                       BIT19
+#define B_PCH_SMI_STS_INTEL_USB2                  BIT18
+#define B_PCH_SMI_STS_LEGACY_USB2                 BIT17
+#define B_PCH_SMI_STS_SMBUS                       BIT16
+#define B_PCH_SMI_STS_SERIRQ                      BIT15
+#define B_PCH_SMI_STS_PERIODIC                    BIT14
+#define B_PCH_SMI_STS_TCO                         BIT13
+#define B_PCH_SMI_STS_DEVMON                      BIT12
+#define B_PCH_SMI_STS_MCSMI                       BIT11
+#define B_PCH_SMI_STS_GPIO_SMI                    BIT10
+#define B_PCH_SMI_STS_GPE0                        BIT9
+#define B_PCH_SMI_STS_PM1_STS_REG                 BIT8
+#define B_PCH_SMI_STS_SWSMI_TMR                   BIT6
+#define B_PCH_SMI_STS_APM                         BIT5
+#define B_PCH_SMI_STS_ON_SLP_EN                   BIT4
+#define B_PCH_SMI_STS_LEGACY_USB                  BIT3
+#define B_PCH_SMI_STS_BIOS                        BIT2
+#define N_PCH_SMI_STS_LEGACY_USB3                 31
+#define N_PCH_SMI_STS_ESPI                        28
+#define N_PCH_SMI_STS_GPIO_UNLOCK                 27
+#define N_PCH_SMI_STS_SPI                         26
+#define N_PCH_SMI_STS_MONITOR                     21
+#define N_PCH_SMI_STS_PCI_EXP                     20
+#define N_PCH_SMI_STS_PATCH                       19
+#define N_PCH_SMI_STS_INTEL_USB2                  18
+#define N_PCH_SMI_STS_LEGACY_USB2                 17
+#define N_PCH_SMI_STS_SMBUS                       16
+#define N_PCH_SMI_STS_SERIRQ                      15
+#define N_PCH_SMI_STS_PERIODIC                    14
+#define N_PCH_SMI_STS_TCO                         13
+#define N_PCH_SMI_STS_DEVMON                      12
+#define N_PCH_SMI_STS_MCSMI                       11
+#define N_PCH_SMI_STS_GPIO_SMI                    10
+#define N_PCH_SMI_STS_GPE0                        9
+#define N_PCH_SMI_STS_PM1_STS_REG                 8
+#define N_PCH_SMI_STS_SWSMI_TMR                   6
+#define N_PCH_SMI_STS_APM                         5
+#define N_PCH_SMI_STS_ON_SLP_EN                   4
+#define N_PCH_SMI_STS_LEGACY_USB                  3
+#define N_PCH_SMI_STS_BIOS                        2
+
+#define R_PCH_ACPI_GPE_CNTL                       0x40
+#define B_PCH_ACPI_GPE_CNTL_SWGPE_CTRL            BIT17
+
+#define R_PCH_DEVACT_STS                          0x44
+#define S_PCH_DEVACT_STS                          2
+#define B_PCH_DEVACT_STS_MASK                     0x13E1
+#define B_PCH_DEVACT_STS_KBC                      BIT12
+#define B_PCH_DEVACT_STS_PIRQDH                   BIT9
+#define B_PCH_DEVACT_STS_PIRQCG                   BIT8
+#define B_PCH_DEVACT_STS_PIRQBF                   BIT7
+#define B_PCH_DEVACT_STS_PIRQAE                   BIT6
+#define B_PCH_DEVACT_STS_D0_TRP                   BIT0
+#define N_PCH_DEVACT_STS_KBC                      12
+#define N_PCH_DEVACT_STS_PIRQDH                   9
+#define N_PCH_DEVACT_STS_PIRQCG                   8
+#define N_PCH_DEVACT_STS_PIRQBF                   7
+#define N_PCH_DEVACT_STS_PIRQAE                   6
+
+#define R_PCH_ACPI_PM2_CNT                        0x50
+#define B_PCH_ACPI_PM2_CNT_ARB_DIS                BIT0
+
+#define R_PCH_OC_WDT_CTL                          0x54
+#define B_PCH_OC_WDT_CTL_RLD                      BIT31
+#define B_PCH_OC_WDT_CTL_ICCSURV_STS              BIT25
+#define B_PCH_OC_WDT_CTL_NO_ICCSURV_STS           BIT24
+#define B_PCH_OC_WDT_CTL_FORCE_ALL                BIT15
+#define B_PCH_OC_WDT_CTL_EN                       BIT14
+#define B_PCH_OC_WDT_CTL_ICCSURV                  BIT13
+#define B_PCH_OC_WDT_CTL_LCK                      BIT12
+#define B_PCH_OC_WDT_CTL_TOV_MASK                 0x3FF
+#define B_PCH_OC_WDT_CTL_FAILURE_STS              BIT23
+#define B_PCH_OC_WDT_CTL_UNXP_RESET_STS           BIT22
+#define B_PCH_OC_WDT_CTL_AFTER_POST               0x3F0000
+#define V_PCH_OC_WDT_CTL_STATUS_FAILURE           1
+#define V_PCH_OC_WDT_CTL_STATUS_OK                0
+
+#define R_PCH_ACPI_GPE0_STS_31_0                  0x80
+#define R_PCH_ACPI_GPE0_STS_63_32                 0x84
+#define R_PCH_ACPI_GPE0_STS_95_64                 0x88
+#define R_PCH_ACPI_GPE0_STS_127_96                0x8C
+#define S_PCH_ACPI_GPE0_STS_127_96                4
+#define B_PCH_ACPI_GPE0_STS_127_96_WADT           BIT18
+#define B_PCH_ACPI_GPE0_STS_127_96_LAN_WAKE       BIT16
+#define B_PCH_ACPI_GPE0_STS_127_96_PME_B0         BIT13
+#define B_PCH_ACPI_GPE0_STS_127_96_ME_SCI         BIT12
+#define B_PCH_ACPI_GPE0_STS_127_96_PME            BIT11
+#define B_PCH_ACPI_GPE0_STS_127_96_BATLOW         BIT10
+#define B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP        BIT9
+#define B_PCH_ACPI_GPE0_STS_127_96_RI             BIT8
+#define B_PCH_ACPI_GPE0_STS_127_96_SMB_WAK        BIT7
+#define B_PCH_ACPI_GPE0_STS_127_96_TC0SCI         BIT6
+#define B_PCH_ACPI_GPE0_STS_127_96_SWGPE          BIT2
+#define B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG       BIT1
+#define N_PCH_ACPI_GPE0_STS_127_96_PME_B0         13
+#define N_PCH_ACPI_GPE0_STS_127_96_PME            11
+#define N_PCH_ACPI_GPE0_STS_127_96_BATLOW         10
+#define N_PCH_ACPI_GPE0_STS_127_96_PCI_EXP        9
+#define N_PCH_ACPI_GPE0_STS_127_96_RI             8
+#define N_PCH_ACPI_GPE0_STS_127_96_SMB_WAK        7
+#define N_PCH_ACPI_GPE0_STS_127_96_TC0SCI         6
+#define N_PCH_ACPI_GPE0_STS_127_96_SWGPE          2
+#define N_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG       1
+
+#define R_PCH_ACPI_GPE0_EN_31_0                   0x90
+#define R_PCH_ACPI_GPE0_EN_63_32                  0x94
+#define R_PCH_ACPI_GPE0_EN_95_64                  0x98
+#define R_PCH_ACPI_GPE0_EN_127_96                 0x9C
+#define S_PCH_ACPI_GPE0_EN_127_96                 4
+#define B_PCH_ACPI_GPE0_EN_127_96_WADT            BIT18
+#define B_PCH_ACPI_GPE0_EN_127_96_LAN_WAKE        BIT16
+#define B_PCH_ACPI_GPE0_EN_127_96_PME_B0          BIT13
+#define B_PCH_ACPI_GPE0_EN_127_96_ME_SCI          BIT12
+#define B_PCH_ACPI_GPE0_EN_127_96_PME             BIT11
+#define B_PCH_ACPI_GPE0_EN_127_96_BATLOW          BIT10
+#define B_PCH_ACPI_GPE0_EN_127_96_PCI_EXP         BIT9
+#define B_PCH_ACPI_GPE0_EN_127_96_RI              BIT8
+#define B_PCH_ACPI_GPE0_EN_127_96_TC0SCI          BIT6
+#define B_PCH_ACPI_GPE0_EN_127_96_SWGPE           BIT2
+#define B_PCH_ACPI_GPE0_EN_127_96_HOT_PLUG        BIT1
+#define N_PCH_ACPI_GPE0_EN_127_96_PME_B0          13
+#define N_PCH_ACPI_GPE0_EN_127_96_USB3            12
+#define N_PCH_ACPI_GPE0_EN_127_96_PME             11
+#define N_PCH_ACPI_GPE0_EN_127_96_BATLOW          10
+#define N_PCH_ACPI_GPE0_EN_127_96_PCI_EXP         9
+#define N_PCH_ACPI_GPE0_EN_127_96_RI              8
+#define N_PCH_ACPI_GPE0_EN_127_96_TC0SCI          6
+#define N_PCH_ACPI_GPE0_EN_127_96_SWGPE           2
+#define N_PCH_ACPI_GPE0_EN_127_96_HOT_PLUG        1
+
+
+//
+// TCO register I/O map
+//
+#define R_PCH_TCO_RLD                             0x0
+#define R_PCH_TCO_DAT_IN                          0x2
+#define R_PCH_TCO_DAT_OUT                         0x3
+#define R_PCH_TCO1_STS                            0x04
+#define S_PCH_TCO1_STS                            2
+#define B_PCH_TCO1_STS_DMISERR                    BIT12
+#define B_PCH_TCO1_STS_DMISMI                     BIT10
+#define B_PCH_TCO1_STS_DMISCI                     BIT9
+#define B_PCH_TCO1_STS_BIOSWR                     BIT8
+#define B_PCH_TCO1_STS_NEWCENTURY                 BIT7
+#define B_PCH_TCO1_STS_TIMEOUT                    BIT3
+#define B_PCH_TCO1_STS_TCO_INT                    BIT2
+#define B_PCH_TCO1_STS_SW_TCO_SMI                 BIT1
+#define B_PCH_TCO1_STS_NMI2SMI                    BIT0
+#define N_PCH_TCO1_STS_DMISMI                     10
+#define N_PCH_TCO1_STS_BIOSWR                     8
+#define N_PCH_TCO1_STS_NEWCENTURY                 7
+#define N_PCH_TCO1_STS_TIMEOUT                    3
+#define N_PCH_TCO1_STS_SW_TCO_SMI                 1
+#define N_PCH_TCO1_STS_NMI2SMI                    0
+
+#define R_PCH_TCO2_STS                            0x06
+#define S_PCH_TCO2_STS                            2
+#define B_PCH_TCO2_STS_SMLINK_SLV_SMI             BIT4
+#define B_PCH_TCO2_STS_BAD_BIOS                   BIT3
+#define B_PCH_TCO2_STS_BOOT                       BIT2
+#define B_PCH_TCO2_STS_SECOND_TO                  BIT1
+#define B_PCH_TCO2_STS_INTRD_DET                  BIT0
+#define N_PCH_TCO2_STS_INTRD_DET                  0
+
+#define R_PCH_TCO1_CNT                            0x08
+#define S_PCH_TCO1_CNT                            2
+#define B_PCH_TCO_CNT_LOCK                        BIT12
+#define B_PCH_TCO_CNT_TMR_HLT                     BIT11
+#define B_PCH_TCO_CNT_NMI2SMI_EN                  BIT9
+#define B_PCH_TCO_CNT_NMI_NOW                     BIT8
+#define N_PCH_TCO_CNT_NMI2SMI_EN                  9
+
+#define R_PCH_TCO2_CNT                            0x0A
+#define S_PCH_TCO2_CNT                            2
+#define B_PCH_TCO2_CNT_OS_POLICY                  0x0030
+#define B_PCH_TCO2_CNT_GPI11_ALERT_DISABLE        0x0008
+#define B_PCH_TCO2_CNT_INTRD_SEL                  0x0006
+#define N_PCH_TCO2_CNT_INTRD_SEL                  2
+
+#define R_PCH_TCO_MESSAGE1                        0x0C
+#define R_PCH_TCO_MESSAGE2                        0x0D
+#define R_PCH_TCO_WDCNT                           0x0E
+#define R_PCH_TCO_SW_IRQ_GEN                      0x10
+#define B_PCH_TCO_IRQ12_CAUSE                     BIT1
+#define B_PCH_TCO_IRQ1_CAUSE                      BIT0
+#define R_PCH_TCO_TMR                             0x12
+
+//
+// PWRM Registers
+//
+#define R_PCH_WADT_AC                                       0x0                         ///< Wake Alarm Device Timer: AC
+#define R_PCH_WADT_DC                                       0x4                         ///< Wake Alarm Device Timer: DC
+#define R_PCH_WADT_EXP_AC                                   0x8                         ///< Wake Alarm Device Expired Timer: AC
+#define R_PCH_WADT_EXP_DC                                   0xC                         ///< Wake Alarm Device Expired Timer: DC
+#define R_PCH_PWRM_PRSTS                                    0x10                        ///< Power and Reset Status
+#define B_PCH_PWRM_PRSTS_VE_WD_TMR_STS                      BIT7                        ///< VE Watchdog Timer Status
+#define B_PCH_PWRM_PRSTS_WOL_OVR_WK_STS                     BIT5
+#define B_PCH_PWRM_PRSTS_FIELD_1                            BIT4
+#define B_PCH_PWRM_PRSTS_ME_WAKE_STS                        BIT0
+#define R_PCH_PWRM_14                                       0x14
+#define R_PCH_PWRM_CFG                                      0x18                        ///< Power Management Configuration
+#define B_PCH_PWRM_CFG_ALLOW_24_OSC_SD                      BIT29                       ///< Allow 24MHz Crystal Oscillator Shutdown
+#define B_PCH_PWRM_CFG_ALLOW_USB2_CORE_PG                   BIT25                       ///< Allow USB2 Core Power Gating
+#define B_PCH_PWRM_CFG_RTC_DS_WAKE_DIS                      BIT21                       ///< RTC Wake from Deep S4/S5 Disable
+#define B_PCH_PWRM_CFG_SSMAW_MASK                           (BIT19 | BIT18)             ///< SLP_SUS# Min Assertion Width
+#define V_PCH_PWRM_CFG_SSMAW_4S                             (BIT19 | BIT18)             ///< 4 seconds
+#define V_PCH_PWRM_CFG_SSMAW_1S                             BIT19                       ///< 1 second
+#define V_PCH_PWRM_CFG_SSMAW_0_5S                           BIT18                       ///< 0.5 second (500ms)
+#define V_PCH_PWRM_CFG_SSMAW_0S                             0                           ///< 0 second
+#define B_PCH_PWRM_CFG_SAMAW_MASK                           (BIT17 | BIT16)             ///< SLP_A# Min Assertion Width
+#define V_PCH_PWRM_CFG_SAMAW_2S                             (BIT17 | BIT16)             ///< 2 seconds
+#define V_PCH_PWRM_CFG_SAMAW_98ms                           BIT17                       ///< 98ms
+#define V_PCH_PWRM_CFG_SAMAW_4S                             BIT16                       ///< 4 seconds
+#define V_PCH_PWRM_CFG_SAMAW_0S                             0                           ///< 0 second
+#define B_PCH_PWRM_CFG_RPCD_MASK                            (BIT9 | BIT8)               ///< Reset Power Cycle Duration
+#define V_PCH_PWRM_CFG_RPCD_1S                              (BIT9 | BIT8)               ///< 1-2 seconds
+#define V_PCH_PWRM_CFG_RPCD_2S                              BIT9                        ///< 2-3 seconds
+#define V_PCH_PWRM_CFG_RPCD_3S                              BIT8                        ///< 3-4 seconds
+#define V_PCH_PWRM_CFG_RPCD_4S                              0                           ///< 4-5 seconds (Default)
+#define R_PCH_PWRM_PCH_PM_STS                               0x1C                        ///< Contains misc. fields used to record PCH power management events
+#define B_PCH_PWRM_PCH_PM_STS_PMC_MSG_FULL_STS              BIT24                       ///< MTPMC transport mechanism full indication
+#define R_PCH_PWRM_MTPMC                                    0x20                        ///< Message to PMC
+#define V_PCH_PWRM_MTPMC_COMMAND_PG_LANE_0_15               0xE                         ///< Command to override lanes 0-15 power gating
+#define V_PCH_PWRM_MTPMC_COMMAND_PG_LANE_16_31              0xF                         ///< Command to override lanes 16-31 power gating
+#define B_PCH_PWRM_MTPMC_PG_CMD_DATA                        0xFFFF0000                  ///< Data part of PowerGate Message to PMC
+#define N_PCH_PWRM_MTPMC_PG_CMD_DATA                        16
+#define R_PCH_PWRM_PCH_PM_STS2                              0x24                        ///< PCH Power Management Status
+#define R_PCH_PWRM_S3_PWRGATE_POL                           0x28                        ///< S3 Power Gating Policies
+#define B_PCH_PWRM_S3DC_GATE_SUS                            BIT1                        ///< Deep S3 Enable in DC Mode
+#define B_PCH_PWRM_S3AC_GATE_SUS                            BIT0                        ///< Deep S3 Enable in AC Mode
+#define R_PCH_PWRM_S4_PWRGATE_POL                           0x2C                        ///< Deep S4 Power Policies
+#define B_PCH_PWRM_S4DC_GATE_SUS                            BIT1                        ///< Deep S4 Enable in DC Mode
+#define B_PCH_PWRM_S4AC_GATE_SUS                            BIT0                        ///< Deep S4 Enable in AC Mode
+#define R_PCH_PWRM_S5_PWRGATE_POL                           0x30                        ///< Deep S5 Power Policies
+#define B_PCH_PWRM_S5DC_GATE_SUS                            BIT15                       ///< Deep S5 Enable in DC Mode
+#define B_PCH_PWRM_S5AC_GATE_SUS                            BIT14                       ///< Deep S5 Enable in AC Mode
+#define R_PCH_PWRM_DSX_CFG                                  0x34                        ///< Deep SX Configuration
+#define B_PCH_PWRM_DSX_CFG_WAKE_PIN_DSX_EN                  BIT2                        ///< WAKE# Pin DeepSx Enable
+#define B_PCH_PWRM_DSX_CFG_ACPRES_PD_DSX_DIS                BIT1                        ///< AC_PRESENT pin pulldown in DeepSx disable
+#define B_PCH_PWRM_DSX_CFG_LAN_WAKE_EN                      BIT0                        ///< LAN_WAKE Pin DeepSx Enable
+#define R_PCH_PWRM_CFG2                                     0x3C                        ///< Power Management Configuration Reg 2
+#define B_PCH_PWRM_CFG2_PBOP                                (BIT31 | BIT30 | BIT29)     ///< Power Button Override Period (PBOP)
+#define N_PCH_PWRM_CFG2_PBOP                                29                          ///< Power Button Override Period (PBOP)
+#define B_PCH_PWRM_CFG2_PB_DIS                              BIT28                       ///< Power Button Native Mode Disable (PB_DIS)
+#define B_PCH_PWRM_CFG2_DRAM_RESET_CTL                      BIT26                       ///< DRAM RESET# control
+#define R_PCH_PWRM_EN_SN_SLOW_RING                          0x48                        ///< Enable Snoop Request to SLOW_RING
+#define R_PCH_PWRM_EN_SN_SLOW_RING2                         0x4C                        ///< Enable Snoop Request to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_SN_SA                                 0x50                        ///< Enable Snoop Request to SA
+#define R_PCH_PWRM_EN_SN_SA2                                0x54                        ///< Enable Snoop Request to SA 2nd Reg
+#define R_PCH_PWRM_EN_SN_SLOW_RING_CF                       0x58                        ///< Enable Snoop Request to SLOW_RING_CF
+#define R_PCH_PWRM_EN_NS_SA                                 0x68                        ///< Enable Non-Snoop Request to SA
+#define R_PCH_PWRM_EN_CW_SLOW_RING                          0x80                        ///< Enable Clock Wake to SLOW_RING
+#define R_PCH_PWRM_EN_CW_SLOW_RING2                         0x84                        ///< Enable Clock Wake to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_CW_SA                                 0x88                        ///< Enable Clock Wake to SA
+#define R_PCH_PWRM_EN_CW_SA2                                0x8C                        ///< Enable Clock Wake to SA 2nd Reg
+#define R_PCH_PWRM_EN_CW_SLOW_RING_CF                       0x98                        ///< Enable Clock Wake to SLOW_RING_CF
+#define R_PCH_PWRM_EN_PA_SLOW_RING                          0xA8                        ///< Enable Pegged Active to SLOW_RING
+#define R_PCH_PWRM_EN_PA_SLOW_RING2                         0xAC                        ///< Enable Pegged Active to SLOW_RING 2nd Reg
+#define R_PCH_PWRM_EN_PA_SA                                 0xB0                        ///< Enable Pegged Active to SA
+#define R_PCH_PWRM_EN_PA_SA2                                0xB4                        ///< Enable Pegged Active to SA 2nd Reg
+#define R_PCH_PWRM_EN_MISC_EVENT                            0xC0                        ///< Enable Misc PM_SYNC Events
+#define R_PCH_PWRM_PMSYNC_TPR_CONFIG                        0xC4
+#define B_PCH_PWRM_PMSYNC_TPR_CONFIG_LOCK                   BIT31
+#define B_PCH_PWRM_PMSYNC_PCH2CPU_TT_EN                     BIT26
+#define B_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE                  (BIT25 | BIT24)
+#define N_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE                  24
+#define V_PCH_PWRM_PMSYNC_PCH2CPU_TT_STATE_1                1
+#define R_PCH_PWRM_PMSYNC_MISC_CFG                          0xC8
+#define B_PCH_PWRM_PMSYNC_PM_SYNC_LOCK                      BIT15                       ///< PM_SYNC Configuration Lock
+#define B_PCH_PWRM_PMSYNC_GPIO_D_SEL                        BIT11
+#define B_PCH_PWRM_PMSYNC_GPIO_C_SEL                        BIT10
+#define R_PCH_PWRM_PM_SYNC_STATE_HYS                        0xD0                        ///< PM_SYNC State Hysteresis
+#define R_PCH_PWRM_PM_SYNC_MODE                             0xD4                        ///< PM_SYNC Pin Mode
+#define R_PCH_PWRM_CFG3                                     0xE0                        ///< Power Management Configuration Reg 3
+#define B_PCH_PWRM_CFG3_DSX_WLAN_PP_EN                      BIT16                       ///< Deep-Sx WLAN Phy Power Enable
+#define B_PCH_PWRM_CFG3_HOST_WLAN_PP_EN                     BIT17                       ///< Host Wireless LAN Phy Power Enable
+#define B_PCH_PWRM_CFG3_PWRG_LOCK                           BIT2                        ///< Lock power gating override messages
+#define R_PCH_PWRM_PM_DOWN_PPB_CFG                          0xE4                        ///< PM_DOWN PCH_POWER_BUDGET CONFIGURATION
+#define R_PCH_PWRM_CFG4                                     0xE8                        ///< Power Management Configuration Reg 4
+#define B_PCH_PWRM_CFG4_U2_PHY_PG_EN                        BIT30                       ///< USB2 PHY SUS Well Power Gating Enable
+#define B_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR                   (0x000001FF)                ///< CPU I/O VR Ramp Duration, [8:0]
+#define N_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR                   0
+#define V_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR_70US              0x007
+#define V_PCH_PWRM_CFG4_CPU_IOVR_RAMP_DUR_240US             0x018
+#define R_PCH_PWRM_CPU_EPOC                                 0xEC
+#define R_PCH_PWRM_VR_MISC_CTL                              0x100
+#define B_PCH_PWRM_VR_MISC_CTL_VIDSOVEN                     BIT3
+#define R_PCH_PWRM_GPIO_CFG                                 0x120
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW2                        (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW2                        8
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW1                        (BIT7 | BIT6 | BIT5 | BIT4)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW1                        4
+#define B_PCH_PWRM_GPIO_CFG_GPE0_DW0                        (BIT3 | BIT2 | BIT1 | BIT0)
+#define N_PCH_PWRM_GPIO_CFG_GPE0_DW0                        0
+#define R_PCH_PWRM_PM_SYNC_MODE_C0                          0xF4                        ///< PM_SYNC Pin Mode in C0
+#define R_PCH_PWRM_ACPI_TMR_CTL                             0xFC
+#define B_PCH_PWRM_ACPI_TMR_DIS                             BIT1
+#define R_PCH_PWRM_124                                      0x124
+#define R_PCH_PWRM_SLP_S0_RESIDENCY_COUNTER                 0x13C
+#define R_PCH_PWRM_MODPHY_PM_CFG1                           0x200
+#define R_PCH_PWRM_MODPHY_PM_CFG1_MLSXSWPGP                 0xFFFF
+#define R_PCH_PWRM_MODPHY_PM_CFG2                           0x204    ///< ModPHY Power Management Configuration Reg 2
+#define B_PCH_PWRM_MODPHY_PM_CFG2_MLSPDDGE                  BIT30    ///< ModPHY Lane SUS Power Domain Dynamic Gating Enable
+#define B_PCH_PWRM_MODPHY_PM_CFG2_EMFC                      BIT29    ///< Enable ModPHY FET Control
+#define B_PCH_PWRM_MODPHY_PM_CFG2_EFRT                      (BIT28 | BIT27 | BIT26 | BIT25 | BIT24)    ///< External FET Ramp Time
+#define N_PCH_PWRM_MODPHY_PM_CFG2_EFRT                      24
+#define V_PCH_PWRM_MODPHY_PM_CFG2_EFRT_200US                0x0A
+#define B_PCH_PWRM_MODPHY_PM_CFG2_ASLOR_UFS                 BIT16    ///< UFS ModPHY SPD SPD Override
+#define R_PCH_PWRM_MODPHY_PM_CFG3                           0x208    ///< ModPHY Power Management Configuration Reg 3
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_UFS             BIT16    ///< UFS ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_XDCI            BIT15    ///< xDCI ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_XHCI            BIT14    ///< xHCI ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_GBE             BIT13    ///< GbE ModPHY SPD RT Request
+#define B_PCH_PWRM_MODPHY_PM_CFG3_MSPDRTREQ_SATA            BIT12    ///< SATA ModPHY SPD RT Request
+#define R_PCH_PWRM_30C                                      0x30C
+#define R_PCH_PWRM_OBFF_CFG                                 0x314             ///< OBFF Configuration
+#define R_PCH_PWRM_31C                                      0x31C
+#define R_PCH_PWRM_CPPM_MISC_CFG                            0x320             ///< CPPM Miscellaneous Configuration
+#define R_PCH_PWRM_CPPM_CG_POL1A                            0x324             ///< CPPM Clock Gating Policy Reg 1
+#define R_PCH_PWRM_CPPM_CG_POL2A                            0x340             ///< CPPM Clock Gating Policy Reg 3
+#define R_PCH_PWRM_34C                                      0x34C
+#define R_PCH_PWRM_CPPM_CG_POL3A                            0x3A8             ///< CPPM Clock Gating Policy Reg 5
+#define B_PCH_PWRM_CPPM_CG_POLXA_CPPM_GX_QUAL               BIT30             ///< CPPM Shutdown Qualifier Enable for Clock Source Group X
+#define B_PCH_PWRM_CPPM_CG_POLXA_LTR_GX_THRESH              (0x000001FF)      ///< LTR Threshold for Clock Source Group X, [8:0]
+#define R_PCH_PWRM_3D0                                      0x3D0
+#define R_PCH_PWRM_CPPM_MPG_POL1A                           0x3E0             ///< CPPM ModPHY Gating Policy Reg 1A
+#define B_PCH_PWRM_CPPM_MPG_POL1A_CPPM_MODPHY_QUAL          BIT30             ///< CPPM Shutdown Qualifier Enable for ModPHY
+#define B_PCH_PWRM_CPPM_MPG_POL1A_LT_MODPHY_SEL             BIT29             ///< ASLT/PLT Selection for ModPHY
+#define B_PCH_PWRM_CPPM_MPG_POL1A_LTR_MODPHY_THRESH         (0x000001FF)      ///< LTR Threshold for ModPHY, [8:0]
+#define R_PCH_PWRM_CS_SD_CTL1                               0x3E8             ///< Clock Source Shutdown Control Reg 1
+#define B_PCH_PWRM_CS_SD_CTL1_CS5_CTL_CFG                   (BIT22 | BIT21 | BIT20)    ///< Clock Source 5 Control Configuration
+#define N_PCH_PWRM_CS_SD_CTL1_CS5_CTL_CFG                   20
+#define B_PCH_PWRM_CS_SD_CTL1_CS1_CTL_CFG                   (BIT2 | BIT1 | BIT0)       ///< Clock Source 1 Control Configuration
+#define N_PCH_PWRM_CS_SD_CTL1_CS1_CTL_CFG                   0
+#define R_PCH_PWRM_CS_SD_CTL2                               0x3EC             ///< Clock Source Shutdown Control Reg 2
+#define R_PCH_PWRM_HSWPGCR1                                 0x5D0
+#define B_PCH_PWRM_SW_PG_CTRL_LOCK                          BIT31
+#define B_PCH_PWRM_DFX_SW_PG_CTRL                           BIT0
+#define R_PCH_PWRM_600                                      0x600
+#define R_PCH_PWRM_604                                      0x604
+#define R_PCH_PWRM_ST_PG_FDIS_PMC_1                         0x620 ///< Static PG Related Function Disable Register 1
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK              BIT31 ///< Static Function Disable Lock (ST_FDIS_LK)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_CAM_FDIS_PMC            BIT6  ///< Camera Function Disable (PMC Version) (CAM_FDIS_PMC)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_ISH_FDIS_PMC            BIT5  ///< SH Function Disable (PMC Version) (ISH_FDIS_PMC)
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_1_GBE_FDIS_PMC            BIT0  ///< GBE Function Disable (PMC Version) (GBE_FDIS_PMC)
+#define R_PCH_PWRM_ST_PG_FDIS_PMC_2                         0x624 ///< Static Function Disable Control Register 2
+#define V_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_FDIS_PMC       0x7FF ///< Static Function Disable Control Register 2
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_GSPI1_FDIS_PMC BIT10 ///< SerialIo Controller GSPI Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_GSPI0_FDIS_PMC BIT9  ///< SerialIo Controller GSPI Device 0 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART2_FDIS_PMC BIT8  ///< SerialIo Controller UART Device 2 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART1_FDIS_PMC BIT7  ///< SerialIo Controller UART Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_UART0_FDIS_PMC BIT6  ///< SerialIo Controller UART Device 0 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C5_FDIS_PMC  BIT5  ///< SerialIo Controller I2C Device 5 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C4_FDIS_PMC  BIT4  ///< SerialIo Controller I2C Device 4 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C3_FDIS_PMC  BIT3  ///< SerialIo Controller I2C Device 3 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C2_FDIS_PMC  BIT2  ///< SerialIo Controller I2C Device 2 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C1_FDIS_PMC  BIT1  ///< SerialIo Controller I2C Device 1 Function Disable
+#define B_PCH_PWRM_ST_PG_FDIS_PMC_2_SERIALIO_I2C0_FDIS_PMC  BIT0  ///< SerialIo Controller I2C Device 0 Function Disable
+#define R_PCH_PWRM_NST_PG_FDIS_1                            0x628
+#define B_PCH_PWRM_NST_PG_FDIS_1_SCC_FDIS_PMC               BIT25 ///< SCC Function Disable. This is only avaiable in B0 onward.
+#define B_PCH_PWRM_NST_PG_FDIS_1_XDCI_FDIS_PMC              BIT24 ///< XDCI Function Disable. This is only avaiable in B0 onward.
+#define B_PCH_PWRM_NST_PG_FDIS_1_ADSP_FDIS_PMC              BIT23 ///< ADSP Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_SATA_FDIS_PMC              BIT22 ///< SATA Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C3_FDIS_PMC           BIT13 ///< PCIe Controller C Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C2_FDIS_PMC           BIT12 ///< PCIe Controller C Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C1_FDIS_PMC           BIT11 ///< PCIe Controller C Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_C0_FDIS_PMC           BIT10 ///< PCIe Controller C Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B3_FDIS_PMC           BIT9  ///< PCIe Controller B Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B2_FDIS_PMC           BIT8  ///< PCIe Controller B Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B1_FDIS_PMC           BIT7  ///< PCIe Controller B Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_B0_FDIS_PMC           BIT6  ///< PCIe Controller B Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A3_FDIS_PMC           BIT5  ///< PCIe Controller A Port 3 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A2_FDIS_PMC           BIT4  ///< PCIe Controller A Port 2 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A1_FDIS_PMC           BIT3  ///< PCIe Controller A Port 1 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_PCIE_A0_FDIS_PMC           BIT2  ///< PCIe Controller A Port 0 Function Disable
+#define B_PCH_PWRM_NST_PG_FDIS_1_XHCI_FDIS_PMC              BIT0  ///< XHCI Function Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_1                            0x640 ///< Fuse Disable Read 1 Register
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E3_FUSE_DIS           BIT21 ///< PCIe Controller E Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E2_FUSE_DIS           BIT20 ///< PCIe Controller E Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E1_FUSE_DIS           BIT19 ///< PCIe Controller E Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_E0_FUSE_DIS           BIT18 ///< PCIe Controller E Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D3_FUSE_DIS           BIT17 ///< PCIe Controller D Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D2_FUSE_DIS           BIT16 ///< PCIe Controller D Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D1_FUSE_DIS           BIT15 ///< PCIe Controller D Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_D0_FUSE_DIS           BIT14 ///< PCIe Controller D Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C3_FUSE_DIS           BIT13 ///< PCIe Controller C Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C2_FUSE_DIS           BIT12 ///< PCIe Controller C Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C1_FUSE_DIS           BIT11 ///< PCIe Controller C Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_C0_FUSE_DIS           BIT10 ///< PCIe Controller C Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B3_FUSE_DIS           BIT9  ///< PCIe Controller B Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B2_FUSE_DIS           BIT8  ///< PCIe Controller B Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B1_FUSE_DIS           BIT7  ///< PCIe Controller B Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_B0_FUSE_DIS           BIT6  ///< PCIe Controller B Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A3_FUSE_DIS           BIT5  ///< PCIe Controller A Port 3 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A2_FUSE_DIS           BIT4  ///< PCIe Controller A Port 2 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A1_FUSE_DIS           BIT3  ///< PCIe Controller A Port 1 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_PCIE_A0_FUSE_DIS           BIT2  ///< PCIe Controller A Port 0 Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_1_XHCI_FUSE_DIS              BIT0  ///< XHCI Fuse Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_2                            0x644 ///< Fuse Disable Read 2 Register
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPC_SS_DIS                 BIT25 ///< SPC Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPB_SS_DIS                 BIT24 ///< SPB Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SPA_SS_DIS                 BIT23 ///< SPA Fuse Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_PSTH_FUSE_SS_DIS           BIT21 ///< PSTH Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_DMI_FUSE_SS_DIS            BIT20 ///< DMI Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_OTG_FUSE_SS_DIS            BIT19 ///< OTG Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_XHCI_SS_DIS                BIT18 ///< XHCI Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_FIA_FUSE_SS_DIS            BIT17 ///< FIA Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_DSP_FUSE_SS_DIS            BIT16 ///< DSP Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SATA_FUSE_SS_DIS           BIT15 ///< SATA Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ICC_FUSE_SS_DIS            BIT14 ///< ICC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_LPC_FUSE_SS_DIS            BIT13 ///< LPC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_RTC_FUSE_SS_DIS            BIT12 ///< RTC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_P2S_FUSE_SS_DIS            BIT11 ///< P2S Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_TRSB_FUSE_SS_DIS           BIT10 ///< TRSB Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SMB_FUSE_SS_DIS            BIT9  ///< SMB Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ITSS_FUSE_SS_DIS           BIT8  ///< ITSS Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SERIALIO_FUSE_SS_DIS       BIT6  ///< SerialIo Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_SCC_FUSE_SS_DIS            BIT4  ///< SCC Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_P2D_FUSE_SS_DIS            BIT3  ///< P2D Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_CAM_FUSE_SS_DIS            BIT2  ///< Camera Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_ISH_FUSE_SS_DIS            BIT1  ///< ISH Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS            BIT0  ///< GBE Fuse or Soft Strap Disable
+#define R_PCH_PWRM_FUSE_DIS_RD_3                            0x648 ///< Static PG Fuse and Soft Strap Disable Read Register 3
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA3_FUSE_SS_DIS         BIT3  ///< PNCRA3 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA2_FUSE_SS_DIS         BIT2  ///< PNCRA2 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA1_FUSE_SS_DIS         BIT1  ///< PNCRA1 Fuse or Soft Strap Disable
+#define B_PCH_PWRM_FUSE_DIS_RD_3_PNCRA_FUSE_SS_DIS          BIT0  ///< PNCRA Fuse or Soft Strap Disable
+
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsSpi.h b/Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsSpi.h
new file mode 100644
index 0000000000..56831b6afe
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/Register/PchRegsSpi.h
@@ -0,0 +1,304 @@
+/** @file
+  Register names for PCH SPI device.
+
+  Conventions:
+
+  - Prefixes:
+    Definitions beginning with "R_" are registers
+    Definitions beginning with "B_" are bits within registers
+    Definitions beginning with "V_" are meaningful values within the bits
+    Definitions beginning with "S_" are register sizes
+    Definitions beginning with "N_" are the bit position
+  - In general, PCH registers are denoted by "_PCH_" in register names
+  - Registers / bits that are different between PCH generations are denoted by
+    "_PCH_[generation_name]_" in register/bit names.
+  - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+    Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+    e.g., "_PCH_H_", "_PCH_LP_"
+    Registers / bits names without _H_ or _LP_ apply for both H and LP.
+  - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+    at the end of the register/bit names
+  - Registers / bits of new devices introduced in a PCH generation will be just named
+    as "_PCH_" without [generation_name] inserted.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_REGS_SPI_H_
+#define _PCH_REGS_SPI_H_
+
+//
+// SPI Registers (D31:F5)
+//
+
+#define PCI_DEVICE_NUMBER_PCH_SPI           31
+#define PCI_FUNCTION_NUMBER_PCH_SPI         5
+
+#define R_PCH_SPI_BAR0                      0x10
+#define B_PCH_SPI_BAR0_MASK                 0x0FFF
+
+#define R_PCH_SPI_BDE                       0xD8
+#define B_PCH_SPI_BDE_F8                    0x8000
+#define B_PCH_SPI_BDE_F0                    0x4000
+#define B_PCH_SPI_BDE_E8                    0x2000
+#define B_PCH_SPI_BDE_E0                    0x1000
+#define B_PCH_SPI_BDE_D8                    0x0800
+#define B_PCH_SPI_BDE_D0                    0x0400
+#define B_PCH_SPI_BDE_C8                    0x0200
+#define B_PCH_SPI_BDE_C0                    0x0100
+#define B_PCH_SPI_BDE_LEG_F                 0x0080
+#define B_PCH_SPI_BDE_LEG_E                 0x0040
+#define B_PCH_SPI_BDE_70                    0x0008
+#define B_PCH_SPI_BDE_60                    0x0004
+#define B_PCH_SPI_BDE_50                    0x0002
+#define B_PCH_SPI_BDE_40                    0x0001
+
+#define R_PCH_SPI_BC                        0xDC
+#define S_PCH_SPI_BC                        4
+#define N_PCH_SPI_BC_ASE_BWP                11
+#define B_PCH_SPI_BC_ASE_BWP                BIT11
+#define N_PCH_SPI_BC_ASYNC_SS               10
+#define B_PCH_SPI_BC_ASYNC_SS               BIT10
+#define B_PCH_SPI_BC_OSFH                   BIT9            ///< OS Function Hide
+#define N_PCH_SPI_BC_SYNC_SS                8
+#define B_PCH_SPI_BC_SYNC_SS                BIT8
+#define B_PCH_SPI_BC_BILD                   BIT7
+#define B_PCH_SPI_BC_BBS                    BIT6            ///< Boot BIOS strap
+#define N_PCH_SPI_BC_BBS                    6
+#define V_PCH_SPI_BC_BBS_SPI                0               ///< Boot BIOS strapped to SPI
+#define V_PCH_SPI_BC_BBS_LPC                1               ///< Boot BIOS strapped to LPC
+#define B_PCH_SPI_BC_EISS                   BIT5            ///< Enable InSMM.STS
+#define B_PCH_SPI_BC_TSS                    BIT4
+#define B_PCH_SPI_BC_SRC                    (BIT3 | BIT2)
+#define N_PCH_SPI_BC_SRC                    2
+#define V_PCH_SPI_BC_SRC_PREF_EN_CACHE_EN   0x02            ///< Prefetching and Caching enabled
+#define V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_DIS 0x01            ///< No prefetching and no caching
+#define V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_EN  0x00            ///< No prefetching, but caching enabled
+#define B_PCH_SPI_BC_LE                     BIT1            ///< Lock Enable
+#define N_PCH_SPI_BC_BLE                    1
+#define B_PCH_SPI_BC_WPD                    BIT0            ///< Write Protect Disable
+
+//
+// BIOS Flash Program Registers (based on SPI_BAR0)
+//
+#define R_PCH_SPI_BFPR                      0x00                          ///< BIOS Flash Primary Region Register(32bits), which is RO and contains the same value from FREG1
+#define B_PCH_SPI_BFPR_PRL                  0x7FFF0000                    ///< BIOS Flash Primary Region Limit mask
+#define N_PCH_SPI_BFPR_PRL                  16                            ///< BIOS Flash Primary Region Limit bit position
+#define B_PCH_SPI_BFPR_PRB                  0x00007FFF                    ///< BIOS Flash Primary Region Base mask
+#define N_PCH_SPI_BFPR_PRB                  0                             ///< BIOS Flash Primary Region Base bit position
+#define R_PCH_SPI_HSFSC                     0x04                          ///< Hardware Sequencing Flash Status and Control Register(32bits)
+#define B_PCH_SPI_HSFSC_FSMIE               BIT31                         ///< Flash SPI SMI# Enable
+#define B_PCH_SPI_HSFSC_FDBC_MASK           0x3F000000                    ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.
+#define N_PCH_SPI_HSFSC_FDBC                24
+#define B_PCH_SPI_HSFSC_CYCLE_MASK          0x001E0000                    ///< Flash Cycle.
+#define N_PCH_SPI_HSFSC_CYCLE               17
+#define V_PCH_SPI_HSFSC_CYCLE_READ          0                             ///< Flash Cycle Read
+#define V_PCH_SPI_HSFSC_CYCLE_WRITE         2                             ///< Flash Cycle Write
+#define V_PCH_SPI_HSFSC_CYCLE_4K_ERASE      3                             ///< Flash Cycle 4K Block Erase
+#define V_PCH_SPI_HSFSC_CYCLE_64K_ERASE     4                             ///< Flash Cycle 64K Sector Erase
+#define V_PCH_SPI_HSFSC_CYCLE_READ_SFDP     5                             ///< Flash Cycle Read SFDP
+#define V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID 6                             ///< Flash Cycle Read JEDEC ID
+#define V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS  7                             ///< Flash Cycle Write Status
+#define V_PCH_SPI_HSFSC_CYCLE_READ_STATUS   8                             ///< Flash Cycle Read Status
+#define B_PCH_SPI_HSFSC_CYCLE_FGO           BIT16                         ///< Flash Cycle Go.
+#define B_PCH_SPI_HSFSC_FLOCKDN             BIT15                         ///< Flash Configuration Lock-Down
+#define B_PCH_SPI_HSFSC_FDV                 BIT14                         ///< Flash Descriptor Valid, once valid software can use hareware sequencing regs
+#define B_PCH_SPI_HSFSC_FDOPSS              BIT13                         ///< Flash Descriptor Override Pin-Strap Status
+#define B_PCH_SPI_HSFSC_PRR34_LOCKDN        BIT12                         ///< PRR3 PRR4 Lock-Down
+#define B_PCH_SPI_HSFSC_SAF_CE              BIT8                          ///< SAF ctype error
+#define B_PCH_SPI_HSFSC_SAF_MODE_ACTIVE     BIT7                          ///< Indicates flash is attached either directly to the PCH via the SPI bus or EC/BMC
+#define B_PCH_SPI_HSFSC_SAF_LE              BIT6                          ///< SAF link error
+#define B_PCH_SPI_HSFSC_SCIP                BIT5                          ///< SPI cycle in progress
+#define B_PCH_SPI_HSFSC_SAF_DLE             BIT4                          ///< SAF Data length error
+#define B_PCH_SPI_HSFSC_SAF_ERROR           BIT3                          ///< SAF Error
+#define B_PCH_SPI_HSFSC_AEL                 BIT2                          ///< Access Error Log
+#define B_PCH_SPI_HSFSC_FCERR               BIT1                          ///< Flash Cycle Error
+#define B_PCH_SPI_HSFSC_FDONE               BIT0                          ///< Flash Cycle Done
+#define R_PCH_SPI_FADDR                     0x08                          ///< SPI Flash Address
+#define B_PCH_SPI_FADDR_MASK                0x01FFFFFF                    ///< SPI Flash Address Mask (0~24bit)
+#define R_PCH_SPI_DLOCK                     0x0C                          ///< Discrete Lock Bits
+#define B_PCH_SPI_DLOCK_PR0LOCKDN           BIT8                          ///< PR0LOCKDN
+#define R_PCH_SPI_FDATA00                   0x10                          ///< SPI Data 00 (32 bits)
+#define R_PCH_SPI_FDATA01                   0x14                          ///< SPI Data 01
+#define R_PCH_SPI_FDATA02                   0x18                          ///< SPI Data 02
+#define R_PCH_SPI_FDATA03                   0x1C                          ///< SPI Data 03
+#define R_PCH_SPI_FDATA04                   0x20                          ///< SPI Data 04
+#define R_PCH_SPI_FDATA05                   0x24                          ///< SPI Data 05
+#define R_PCH_SPI_FDATA06                   0x28                          ///< SPI Data 06
+#define R_PCH_SPI_FDATA07                   0x2C                          ///< SPI Data 07
+#define R_PCH_SPI_FDATA08                   0x30                          ///< SPI Data 08
+#define R_PCH_SPI_FDATA09                   0x34                          ///< SPI Data 09
+#define R_PCH_SPI_FDATA10                   0x38                          ///< SPI Data 10
+#define R_PCH_SPI_FDATA11                   0x3C                          ///< SPI Data 11
+#define R_PCH_SPI_FDATA12                   0x40                          ///< SPI Data 12
+#define R_PCH_SPI_FDATA13                   0x44                          ///< SPI Data 13
+#define R_PCH_SPI_FDATA14                   0x48                          ///< SPI Data 14
+#define R_PCH_SPI_FDATA15                   0x4C                          ///< SPI Data 15
+#define R_PCH_SPI_FRAP                      0x50                          ///< Flash Region Access Permisions Register
+#define B_PCH_SPI_FRAP_BRWA_MASK            0x0000FF00                    ///< BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define N_PCH_SPI_FRAP_BRWA                 8                             ///< BIOS Region Write Access bit position
+#define B_PCH_SPI_FRAP_BRRA_MASK            0x000000FF                    ///< BIOS Region Read Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define B_PCH_SPI_FRAP_BMRAG_MASK           0x00FF0000                    ///< BIOS Master Read Access Grant
+#define B_PCH_SPI_FRAP_BMWAG_MASK           0xFF000000                    ///< BIOS Master Write Access Grant
+#define R_PCH_SPI_FREG0_FLASHD              0x54                          ///< Flash Region 0(Flash Descriptor)(32bits)
+#define R_PCH_SPI_FREG1_BIOS                0x58                          ///< Flash Region 1(BIOS)(32bits)
+#define R_PCH_SPI_FREG2_ME                  0x5C                          ///< Flash Region 2(ME)(32bits)
+#define R_PCH_SPI_FREG3_GBE                 0x60                          ///< Flash Region 3(GbE)(32bits)
+#define R_PCH_SPI_FREG4_PLATFORM_DATA       0x64                          ///< Flash Region 4(Platform Data)(32bits)
+#define R_PCH_SPI_FREG5_DER                 0x68                          ///< Flash Region 5(Device Expansion Region)(32bits)
+#define S_PCH_SPI_FREGX                     4                             ///< Size of Flash Region register
+#define B_PCH_SPI_FREGX_LIMIT_MASK          0x7FFF0000                    ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh
+#define N_PCH_SPI_FREGX_LIMIT               16                            ///< Region limit bit position
+#define N_PCH_SPI_FREGX_LIMIT_REPR          12                            ///< Region limit bit represents position
+#define B_PCH_SPI_FREGX_BASE_MASK           0x00007FFF                    ///< Flash Region Base, [14:0] represents [26:12]
+#define N_PCH_SPI_FREGX_BASE                0                             ///< Region base bit position
+#define N_PCH_SPI_FREGX_BASE_REPR           12                            ///< Region base bit represents position
+#define R_PCH_SPI_PR0                       0x84                          ///< Protected Region 0 Register
+#define R_PCH_SPI_PR1                       0x88                          ///< Protected Region 1 Register
+#define R_PCH_SPI_PR2                       0x8C                          ///< Protected Region 2 Register
+#define R_PCH_SPI_PR3                       0x90                          ///< Protected Region 3 Register
+#define R_PCH_SPI_PR4                       0x94                          ///< Protected Region 4 Register
+#define S_PCH_SPI_PRX                       4                             ///< Protected Region X Register size
+#define B_PCH_SPI_PRX_WPE                   BIT31                         ///< Write Protection Enable
+#define B_PCH_SPI_PRX_PRL_MASK              0x7FFF0000                    ///< Protected Range Limit Mask, [30:16] here represents upper limit of address [26:12]
+#define N_PCH_SPI_PRX_PRL                   16                            ///< Protected Range Limit bit position
+#define B_PCH_SPI_PRX_RPE                   BIT15                         ///< Read Protection Enable
+#define B_PCH_SPI_PRX_PRB_MASK              0x00007FFF                    ///< Protected Range Base Mask, [14:0] here represents base limit of address [26:12]
+#define N_PCH_SPI_PRX_PRB                   0                             ///< Protected Range Base bit position
+#define R_PCH_SPI_SFRAP                     0xB0                          ///< Secondary Flash Regions Access Permisions Register
+#define R_PCH_SPI_FDOC                      0xB4                          ///< Flash Descriptor Observability Control Register(32 bits)
+#define B_PCH_SPI_FDOC_FDSS_MASK            (BIT14 | BIT13 | BIT12)       ///< Flash Descritor Section Select
+#define V_PCH_SPI_FDOC_FDSS_FSDM            0x0000                        ///< Flash Signature and Descriptor Map
+#define V_PCH_SPI_FDOC_FDSS_COMP            0x1000                        ///< Component
+#define V_PCH_SPI_FDOC_FDSS_REGN            0x2000                        ///< Region
+#define V_PCH_SPI_FDOC_FDSS_MSTR            0x3000                        ///< Master
+#define V_PCH_SPI_FDOC_FDSS_PCHS            0x4000                        ///< PCH soft straps
+#define V_PCH_SPI_FDOC_FDSS_SFDP            0x5000                        ///< SFDP Parameter Table
+#define B_PCH_SPI_FDOC_FDSI_MASK            0x0FFC                        ///< Flash Descriptor Section Index
+#define R_PCH_SPI_FDOD                      0xB8                          ///< Flash Descriptor Observability Data Register(32 bits)
+#define R_PCH_SPI_SFDP0_VSCC0               0xC4                          ///< Vendor Specific Component Capabilities Register(32 bits)
+#define B_PCH_SPI_SFDPX_VSCCX_CPPTV         BIT31                         ///< Component Property Parameter Table Valid
+#define B_PCH_SPI_SFDP0_VSCC0_VCL           BIT30                         ///< Vendor Component Lock
+#define B_PCH_SPI_SFDPX_VSCCX_EO_64K        BIT29                         ///< 64k Erase valid (EO_64k_valid)
+#define B_PCH_SPI_SFDPX_VSCCX_EO_4K         BIT28                         ///< 4k Erase valid (EO_4k_valid)
+#define B_PCH_SPI_SFDPX_VSCCX_RPMC          BIT27                         ///< RPMC Supported
+#define B_PCH_SPI_SFDPX_VSCCX_DPD           BIT26                         ///< Deep Powerdown Supported
+#define B_PCH_SPI_SFDPX_VSCCX_SUSRES        BIT25                         ///< Suspend/Resume Supported
+#define B_PCH_SPI_SFDPX_VSCCX_SOFTRES       BIT24                         ///< Soft Reset Supported
+#define B_PCH_SPI_SFDPX_VSCCX_64k_EO_MASK   0x00FF0000                    ///< 64k Erase Opcode (EO_64k)
+#define B_PCH_SPI_SFDPX_VSCCX_4k_EO_MASK    0x0000FF00                    ///< 4k Erase Opcode (EO_4k)
+#define B_PCH_SPI_SFDPX_VSCCX_QER           (BIT7 | BIT6 | BIT5)          ///< Quad Enable Requirements
+#define B_PCH_SPI_SFDPX_VSCCX_WEWS          BIT4                          ///< Write Enable on Write Status
+#define B_PCH_SPI_SFDPX_VSCCX_WSR           BIT3                          ///< Write Status Required
+#define B_PCH_SPI_SFDPX_VSCCX_WG_64B        BIT2                          ///< Write Granularity, 0: 1 Byte; 1: 64 Bytes
+#define R_PCH_SPI_SFDP1_VSCC1               0xC8                          ///< Vendor Specific Component Capabilities Register(32 bits)
+#define R_PCH_SPI_PINTX                     0xCC                          ///< Parameter Table Index
+#define N_PCH_SPI_PINTX_SPT                 14
+#define V_PCH_SPI_PINTX_SPT_CPT0            0x0                           ///< Component 0 Property Parameter Table
+#define V_PCH_SPI_PINTX_SPT_CPT1            0x1                           ///< Component 1 Property Parameter Table
+#define N_PCH_SPI_PINTX_HORD                12
+#define V_PCH_SPI_PINTX_HORD_SFDP           0x0                           ///< SFDP Header
+#define V_PCH_SPI_PINTX_HORD_PT             0x1                           ///< Parameter Table Header
+#define V_PCH_SPI_PINTX_HORD_DATA           0x2                           ///< Data
+#define R_PCH_SPI_PTDATA                    0xD0                          ///< Parameter Table Data
+#define R_PCH_SPI_SBRS                      0xD4                          ///< SPI Bus Requester Status
+#define R_PCH_SPI_SSML                      0xF0                          ///< Set Strap Msg Lock
+#define B_PCH_SPI_SSML_SSL                  BIT0                          ///< Set_Strap Lock
+#define R_PCH_SPI_SSMC                      0xF4                          ///< Set Strap Msg Control
+#define B_PCH_SPI_SSMC_SSMS                 BIT0                          ///< Set_Strap Mux Select
+#define R_PCH_SPI_SSMD                      0xF8                          ///< Set Strap Msg Data
+//
+// @todo Follow up with EDS owner if it should be 3FFF or FFFF.
+//
+#define B_PCH_SPI_SRD_SSD                   0x0000FFFF                    ///< Set_Strap Data
+//
+// Flash Descriptor Base Address Region (FDBAR) from Flash Region 0
+//
+#define R_PCH_SPI_FDBAR_FLVALSIG            0x00                          ///< Flash Valid Signature
+#define V_PCH_SPI_FDBAR_FLVALSIG            0x0FF0A55A
+#define R_PCH_SPI_FDBAR_FLASH_MAP0          0x04
+#define B_PCH_SPI_FDBAR_FCBA                0x000000FF                    ///< Flash Component Base Address
+#define B_PCH_SPI_FDBAR_NC                  0x00000300                    ///< Number Of Components
+#define N_PCH_SPI_FDBAR_NC                  8                             ///< Number Of Components
+#define V_PCH_SPI_FDBAR_NC_1                0x00000000
+#define V_PCH_SPI_FDBAR_NC_2                0x00000100
+#define B_PCH_SPI_FDBAR_FRBA                0x00FF0000                    ///< Flash Region Base Address
+#define B_PCH_SPI_FDBAR_NR                  0x07000000                    ///< Number Of Regions
+#define R_PCH_SPI_FDBAR_FLASH_MAP1          0x08
+#define B_PCH_SPI_FDBAR_FMBA                0x000000FF                    ///< Flash Master Base Address
+#define B_PCH_SPI_FDBAR_NM                  0x00000700                    ///< Number Of Masters
+#define B_PCH_SPI_FDBAR_FPSBA               0x00FF0000                    ///< PCH Strap Base Address, [23:16] represents [11:4]
+#define N_PCH_SPI_FDBAR_FPSBA               16                            ///< PCH Strap base Address bit position
+#define N_PCH_SPI_FDBAR_FPSBA_REPR          4                             ///< PCH Strap base Address bit represents position
+#define B_PCH_SPI_FDBAR_PCHSL               0xFF000000                    ///< PCH Strap Length, [31:24] represents number of Dwords
+#define N_PCH_SPI_FDBAR_PCHSL               24                            ///< PCH Strap Length bit position
+#define R_PCH_SPI_FDBAR_FLASH_MAP2          0x0C
+#define B_PCH_SPI_FDBAR_FCPUSBA             0x000000FF                    ///< CPU Strap Base Address, [7:0] represents [11:4]
+#define N_PCH_SPI_FDBAR_FCPUSBA             0                             ///< CPU Strap Base Address bit position
+#define N_PCH_SPI_FDBAR_FCPUSBA_REPR        4                             ///< CPU Strap Base Address bit represents position
+#define B_PCH_SPI_FDBAR_CPUSL               0x0000FF00                    ///< CPU Strap Length, [15:8] represents number of Dwords
+#define N_PCH_SPI_FDBAR_CPUSL               8                             ///< CPU Strap Length bit position
+//
+// Flash Component Base Address (FCBA) from Flash Region 0
+//
+#define R_PCH_SPI_FCBA_FLCOMP               0x00                          ///< Flash Components Register
+#define B_PCH_SPI_FLCOMP_RIDS_FREQ          (BIT29 | BIT28 | BIT27)       ///< Read ID and Read Status Clock Frequency
+#define B_PCH_SPI_FLCOMP_WE_FREQ            (BIT26 | BIT25 | BIT24)       ///< Write and Erase Clock Frequency
+#define B_PCH_SPI_FLCOMP_FRCF_FREQ          (BIT23 | BIT22 | BIT21)       ///< Fast Read Clock Frequency
+#define B_PCH_SPI_FLCOMP_FR_SUP             BIT20                         ///< Fast Read Support.
+#define B_PCH_SPI_FLCOMP_RC_FREQ            (BIT19 | BIT18 | BIT17)       ///< Read Clock Frequency.
+#define V_PCH_SPI_FLCOMP_FREQ_48MHZ         0x02
+#define V_PCH_SPI_FLCOMP_FREQ_30MHZ         0x04
+#define V_PCH_SPI_FLCOMP_FREQ_17MHZ         0x06
+#define B_PCH_SPI_FLCOMP_COMP1_MASK         0xF0                          ///< Flash Component 1 Size MASK
+#define N_PCH_SPI_FLCOMP_COMP1              4                             ///< Flash Component 1 Size bit position
+#define B_PCH_SPI_FLCOMP_COMP0_MASK         0x0F                          ///< Flash Component 0 Size MASK
+#define V_PCH_SPI_FLCOMP_COMP_512KB         0x80000
+//
+// Descriptor Upper Map Section from Flash Region 0
+//
+#define R_PCH_SPI_FLASH_UMAP1               0xEFC                         ///< Flash Upper Map 1
+#define B_PCH_SPI_FLASH_UMAP1_VTBA          0x000000FF                    ///< VSCC Table Base Address
+#define B_PCH_SPI_FLASH_UMAP1_VTL           0x0000FF00                    ///< VSCC Table Length
+
+#define R_PCH_SPI_VTBA_JID0                 0x00                          ///< JEDEC-ID 0 Register
+#define S_PCH_SPI_VTBA_JID0                 0x04
+#define B_PCH_SPI_VTBA_JID0_VID             0x000000FF
+#define B_PCH_SPI_VTBA_JID0_DID0            0x0000FF00
+#define B_PCH_SPI_VTBA_JID0_DID1            0x00FF0000
+#define N_PCH_SPI_VTBA_JID0_DID0            0x08
+#define N_PCH_SPI_VTBA_JID0_DID1            0x10
+#define R_PCH_SPI_VTBA_VSCC0                0x04
+#define S_PCH_SPI_VTBA_VSCC0                0x04
+
+
+//
+// SPI Private Configuration Space Registers
+//
+#define R_PCH_PCR_SPI_CLK_CTL               0xC004
+#define R_PCH_PCR_SPI_PWR_CTL               0xC008
+#define R_PCH_PCR_SPI_ESPI_SOFTSTRAPS       0xC210
+#define B_PCH_PCR_SPI_ESPI_SOFTSTRAPS_SLAVE BIT12
+
+//
+// MMP0
+//
+#define R_PCH_SPI_STRP_MMP0                 0xC4    ///< MMP0 Soft strap offset
+#define B_PCH_SPI_STRP_MMP0                 0x10    ///< MMP0 Soft strap bit
+
+
+#define R_PCH_SPI_STRP_SFDP                 0xF0    ///< PCH Soft Strap SFDP
+#define B_PCH_SPI_STRP_SFDP_QIORE           BIT3    ///< Quad IO Read Enable
+#define B_PCH_SPI_STRP_SFDP_QORE            BIT2    ///< Quad Output Read Enable
+#define B_PCH_SPI_STRP_SFDP_DIORE           BIT1    ///< Dual IO Read Enable
+#define B_PCH_SPI_STRP_SFDP_DORE            BIT0    ///< Dual Output Read Enable
+
+//
+// Descriptor Record 0
+//
+#define R_PCH_SPI_STRP_DSCR_0               0x00    ///< PCH Soft Strap 0
+#define B_PCH_SPI_STRP_DSCR_0_PTT_SUPP      BIT22   ///< PTT Supported
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Include/Register/X58Ich10.h b/Silicon/Intel/SimicsIch10Pkg/Include/Register/X58Ich10.h
new file mode 100644
index 0000000000..eac46955e0
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Include/Register/X58Ich10.h
@@ -0,0 +1,114 @@
+/** @file
+  Various register numbers and value bits based on the following publications:
+  - Intel(R) datasheet 319973-003
+  - Intel(R) datasheet 319974-017US
+
+  Copyright (C) 2015, Red Hat, Inc.
+  Copyright (c) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __X58_ICH10_H__
+#define __X58_ICH10_H__
+
+#include <Library/PciLib.h>
+#include <IndustryStandard/Pci22.h>
+
+//
+// Simics Host Bridge DID Address
+//
+#define SIMICS_HOSTBRIDGE_DID \
+  PCI_LIB_ADDRESS (0, 0, 0, PCI_DEVICE_ID_OFFSET)
+
+//
+// Host Bridge Device ID (DID) value for ICH10
+//
+#define INTEL_ICH10_DEVICE_ID 0x3400
+
+//
+// B/D/F/Type: 0/0/0/PCI
+//
+#define DRAMC_REGISTER_Q35(Offset) PCI_LIB_ADDRESS (0, 0, 0, (Offset))
+#define DRAMC_REGISTER_X58(Offset) PCI_LIB_ADDRESS (0, 20, 0, (Offset))
+#define MCH_GGC                 0x52
+#define MCH_GGC_IVD             BIT1
+
+#define MCH_PCIEXBAR_LOW        0x10C
+#define MCH_PCIEXBAR_LID        0x10E
+#define MCH_PCIEXBAR_SHIFT      16
+#define MCH_PCIEXBAR_LOWMASK    0x0FFFFFFF
+#define MCH_PCIEXBAR_BUS_FF     0
+#define MCH_PCIEXBAR_EN         BIT0
+
+#define MCH_PCIEXBAR_HIGH       0x64
+#define MCH_PCIEXBAR_HIGHMASK   0xFFFFFFF0
+
+#define MCH_SMRAM             0x9D
+#define MCH_SMRAM_D_LCK         BIT4
+#define MCH_SMRAM_G_SMRAME      BIT3
+
+#define MCH_ESMRAMC           0x9E
+#define MCH_ESMRAMC_H_SMRAME    BIT7
+#define MCH_ESMRAMC_E_SMERR     BIT6
+#define MCH_ESMRAMC_SM_CACHE    BIT5
+#define MCH_ESMRAMC_SM_L1       BIT4
+#define MCH_ESMRAMC_SM_L2       BIT3
+#define MCH_ESMRAMC_TSEG_8MB    BIT3
+#define MCH_ESMRAMC_TSEG_2MB    BIT2
+#define MCH_ESMRAMC_TSEG_1MB    BIT1
+#define MCH_ESMRAMC_TSEG_MASK   (BIT3 | BIT2 | BIT1)
+#define MCH_ESMRAMC_T_EN        BIT0
+
+#define MCH_GBSM              0xA4
+#define MCH_GBSM_MB_SHIFT       20
+
+#define MCH_BGSM              0xA8
+#define MCH_BGSM_MB_SHIFT       20
+
+#define MCH_TSEGMB            0xA8
+#define MCH_TSEGMB_MB_SHIFT     20
+
+#define MCH_TOLUD             0xD0
+
+//
+// B/D/F/Type: 0/0x1f/0/PCI
+//
+#define POWER_MGMT_REGISTER_ICH10(Offset) \
+  PCI_LIB_ADDRESS (0, 0x1f, 0, (Offset))
+
+#define ICH10_PMBASE               0x40
+#define ICH10_PMBASE_MASK            (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | \
+                                     BIT10 | BIT9  | BIT8  | BIT7)
+
+#define ICH10_ACPI_CNTL            0x44
+#define ICH10_ACPI_CNTL_ACPI_EN      BIT7
+
+#define ICH10_GEN_PMCON_1          0xA0
+#define ICH10_GEN_PMCON_1_SMI_LOCK   BIT4
+
+#define ICH10_RCBA                 0xF0
+#define ICH10_RCBA_EN                BIT0
+
+#define ICH10_PMBASE_IO            0x400
+//
+// IO ports
+//
+#define ICH10_APM_CNT 0xB2
+#define ICH10_APM_STS 0xB3
+
+//
+// IO ports relative to PMBASE
+//
+#define ICH10_PMBASE_OFS_SMI_EN   0x30
+#define ICH10_SMI_EN_APMC_EN      BIT5
+#define ICH10_SMI_EN_GBL_SMI_EN   BIT0
+#define ICH10_SMI_EN_EOS          BIT1  // End of SMI
+
+#define ICH10_PMBASE_OFS_SMI_STS  0x34
+#define ICH10_SMI_STS_APM         BIT5  // APM Status
+
+#define ICH10_ROOT_COMPLEX_BASE 0xFED1C000
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/IncludePrivate/Library/PchSpiCommonLib.h b/Silicon/Intel/SimicsIch10Pkg/IncludePrivate/Library/PchSpiCommonLib.h
new file mode 100644
index 0000000000..cf60f1fd58
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IncludePrivate/Library/PchSpiCommonLib.h
@@ -0,0 +1,396 @@
+/** @file
+  Header file for the PCH SPI Common Driver.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SPI_COMMON_LIB_H_
+#define _PCH_SPI_COMMON_LIB_H_
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+//  Wait Time = 6 seconds = 6000000 microseconds
+//  Wait Period = 10 microseconds
+//
+#define SPI_WAIT_TIME   6000000     ///< Wait Time = 6 seconds = 6000000 microseconds
+#define SPI_WAIT_PERIOD 10          ///< Wait Period = 10 microseconds
+
+///
+/// Flash cycle Type
+///
+typedef enum {
+  FlashCycleRead,
+  FlashCycleWrite,
+  FlashCycleErase,
+  FlashCycleReadSfdp,
+  FlashCycleReadJedecId,
+  FlashCycleWriteStatus,
+  FlashCycleReadStatus,
+  FlashCycleMax
+} FLASH_CYCLE_TYPE;
+
+///
+/// Flash Component Number
+///
+typedef enum {
+  FlashComponent0,
+  FlashComponent1,
+  FlashComponentMax
+} FLASH_COMPONENT_NUM;
+
+///
+/// Private data structure definitions for the driver
+///
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+typedef struct {
+  UINT32                Signature;
+  EFI_HANDLE            Handle;
+  EFI_SPI_PROTOCOL      SpiProtocol;
+  UINT16                PchAcpiBase;
+  UINTN                 PchSpiBase;
+  UINT16                ReadPermission;
+  UINT16                WritePermission;
+  UINT32                SfdpVscc0Value;
+  UINT32                SfdpVscc1Value;
+  UINT16                PchStrapBaseAddr;
+  UINT16                PchStrapSize;
+  UINT16                CpuStrapBaseAddr;
+  UINT16                CpuStrapSize;
+  UINT8                 NumberOfComponents;
+  UINT32                Component1StartAddr;
+  UINT32                TotalFlashSize;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a)  CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+
+/**
+  Initialize an SPI protocol instance.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval EFI_SUCCESS             The protocol instance was properly initialized
+  @exception EFI_UNSUPPORTED      The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+  IN     SPI_INSTANCE       *SpiInstance
+  );
+
+/**
+  This function is a hook for Spi to disable BIOS Write Protect
+
+  @retval EFI_SUCCESS             The protocol instance was properly initialized
+  @retval EFI_ACCESS_DENIED       The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+  VOID
+  );
+
+/**
+  This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+  VOID
+  );
+
+/**
+  Acquire pch spi mmio address.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval PchSpiBar0              return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+  IN  SPI_INSTANCE                *SpiInstance
+  );
+
+/**
+  Release pch spi mmio address.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+  IN  SPI_INSTANCE                *SpiInstance
+  );
+
+/**
+  Read data from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[out] Buffer              The Pointer to caller-allocated buffer containing the dada received.
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *Buffer
+  );
+
+/**
+  Write data to the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[in] Buffer               Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *Buffer
+  );
+
+/**
+  Erase some area on the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount
+  );
+
+/**
+  Read SFDP data from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] Address              The starting byte address for SFDP data read.
+  @param[in] ByteCount            Number of bytes in SFDP data portion of the SPI cycle
+  @param[out] SfdpData            The Pointer to caller-allocated buffer containing the SFDP data received
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *SfdpData
+  );
+
+/**
+  Read Jedec Id from the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] ByteCount            Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+  @param[out] JedecId             The Pointer to caller-allocated buffer containing JEDEC ID received
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *JedecId
+  );
+
+/**
+  Write the status register in the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+  @param[in] StatusValue          The Pointer to caller-allocated buffer containing the value of Status register writing
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *StatusValue
+  );
+
+/**
+  Read status register in the flash part.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+  @param[out] StatusValue         The Pointer to caller-allocated buffer containing the value of Status register received.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *StatusValue
+  );
+
+/**
+  Get the SPI region base and size, based on the enum type
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] FlashRegionType      The Flash Region type for for the base address which is listed in the Descriptor.
+  @param[out] BaseAddress         The Flash Linear Address for the Region 'n' Base
+  @param[out] RegionSize          The size for the Region 'n'
+
+  @retval EFI_SUCCESS             Read success
+  @retval EFI_INVALID_PARAMETER   Invalid region type given
+  @retval EFI_DEVICE_ERROR        The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  OUT    UINT32             *BaseAddress,
+  OUT    UINT32             *RegionSize
+  );
+
+/**
+  Read PCH Soft Strap Values
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SoftStrapAddr        PCH Soft Strap address offset from FPSBA.
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+                                  If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    VOID               *SoftStrapValue
+  );
+
+/**
+  Read CPU Soft Strap Values
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SoftStrapAddr        CPU Soft Strap address offset from FCPUSBA.
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle.
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+                                  If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    VOID               *SoftStrapValue
+  );
+
+/**
+  This function sends the programmed SPI command to the slave device.
+
+  @param[in] This                 Pointer to the PCH_SPI_PROTOCOL instance.
+  @param[in] SpiRegionType        The SPI Region type for flash cycle which is listed in the Descriptor
+  @param[in] FlashCycleType       The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.
+  @param[in,out] Buffer           Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+  @retval EFI_SUCCESS             SPI command completes successfully.
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     FLASH_REGION_TYPE  FlashRegionType,
+  IN     FLASH_CYCLE_TYPE   FlashCycleType,
+  IN     UINT32             Address,
+  IN     UINT32             ByteCount,
+  IN OUT UINT8              *Buffer
+  );
+
+/**
+  Wait execution cycle to complete on the SPI interface.
+
+  @param[in] This                 The SPI protocol instance
+  @param[in] PchSpiBar0           Spi MMIO base address
+  @param[in] ErrorCheck           TRUE if the SpiCycle needs to do the error check
+
+  @retval TRUE                    SPI cycle completed on the interface.
+  @retval FALSE                   Time out while waiting the SPI cycle to complete.
+                                  It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINTN              PchSpiBar0,
+  IN     BOOLEAN            ErrorCheck
+  );
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.inf b/Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100644
index 0000000000..7b50ee8867
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,34 @@
+## @file
+#  Library instance for ResetSystem library class for OVMF
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ResetSystemLib
+  FILE_GUID                      = 66564872-21d4-4d2a-a68b-1e844f980820
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ResetSystemLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  ResetSystemLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  DebugLib
+  IoLib
+  TimerLib
diff --git a/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
new file mode 100644
index 0000000000..23b334a080
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
@@ -0,0 +1,50 @@
+## @file
+# SMM Library instance of Spi Flash Common Library Class
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = SmmSpiFlashCommonLib
+  FILE_GUID                      = 9632D96E-E849-4217-9217-DC500B8AAE47
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = SpiFlashCommonLib|DXE_SMM_DRIVER
+  CONSTRUCTOR                    = SmmSpiFlashCommonLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+  PciLib
+  IoLib
+  MemoryAllocationLib
+  BaseLib
+  UefiLib
+  SmmServicesTableLib
+  BaseMemoryLib
+  DebugLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[Pcd]
+  gEfiPchTokenSpaceGuid.PcdFlashAreaBaseAddress  ## CONSUMES
+  gEfiPchTokenSpaceGuid.PcdFlashAreaSize         ## CONSUMES
+
+[Sources]
+  SpiFlashCommonSmmLib.c
+  SpiFlashCommon.c
+
+[Protocols]
+  gEfiSmmSpiProtocolGuid                        ## CONSUMES
+
+[Depex.X64.DXE_SMM_DRIVER]
+  gEfiSmmSpiProtocolGuid
diff --git a/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
new file mode 100644
index 0000000000..df1da274a6
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
@@ -0,0 +1,31 @@
+## @file
+#  Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BasePchSpiCommonLib
+  FILE_GUID                      = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PchSpiCommonLib
+
+[Sources]
+  SpiCommon.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+
+[Pcd]
+  gEfiPchTokenSpaceGuid.PcdFlashAreaBaseAddress  ## CONSUMES
+  gEfiPchTokenSpaceGuid.PcdFlashAreaSize         ## CONSUMES
diff --git a/Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.inf b/Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.inf
new file mode 100644
index 0000000000..d8bc156dca
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/SmmControl/RuntimeDxe/SmmControl2Dxe.inf
@@ -0,0 +1,61 @@
+## @file
+# A DXE_RUNTIME_DRIVER providing synchronous SMI activations via the
+# EFI_SMM_CONTROL2_PROTOCOL.
+#
+# We expect the PEI phase to have covered the following:
+# - ensure that the underlying QEMU machine type be X58
+#   (responsible: OvmfPkg/SmmAccess/SmmAccessPei.inf)
+# - ensure that the ACPI PM IO space be configured
+#   (responsible: OvmfPkg/PlatformPei/PlatformPei.inf)
+#
+# Our own entry point is responsible for confirming the SMI feature and for
+# configuring it.
+#
+# Copyright (C) 2013, 2015, Red Hat, Inc.
+# Copyright (C) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmmControl2Dxe
+  FILE_GUID                      = 1206F7CA-A475-4624-A83E-E6FC9BB38E49
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010400
+  ENTRY_POINT                    = SmmControl2DxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SmmControl2Dxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SimicsX58SktPkg/SktPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  PcdLib
+  PciLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiS3SaveStateProtocolGuid   ## SOMETIMES_CONSUMES
+  gEfiSmmControl2ProtocolGuid   ## PRODUCES
+
+[FeaturePcd]
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[Depex]
+  TRUE
diff --git a/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h b/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h
new file mode 100644
index 0000000000..6ada9b121d
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpi.h
@@ -0,0 +1,23 @@
+/** @file
+  Header file for the PCH SPI SMM Driver.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SPI_H_
+#define _PCH_SPI_H_
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <PchAccess.h>
+#include <Protocol/Spi.h>
+#include <IncludePrivate/Library/PchSpiCommonLib.h>
+
+#endif
diff --git a/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf b/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf
new file mode 100644
index 0000000000..7b60d36c5b
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/Spi/Smm/PchSpiSmm.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                 = 0x00010017
+  BASE_NAME                   = PchSpiSmm
+  FILE_GUID                   = 27F4917B-A707-4aad-9676-26DF168CBF0D
+  VERSION_STRING              = 1.0
+  MODULE_TYPE                 = DXE_SMM_DRIVER
+  PI_SPECIFICATION_VERSION    = 1.10
+  ENTRY_POINT                 = InstallPchSpi
+
+
+  [LibraryClasses]
+  DebugLib
+  IoLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  BaseLib
+  SmmServicesTableLib
+  PchSpiCommonLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[Sources]
+  PchSpi.h
+  PchSpi.c
+
+
+[Protocols]
+  gEfiSmmSpiProtocolGuid      # PRODUCES   #SERVER_BIOS
+
+
+[Depex]
+  gEfiSmmBase2ProtocolGuid    #This is for SmmServicesTableLib
+  AND gEfiSmmCpuProtocolGuid  # This is for CpuSmmDisableBiosWriteProtect()
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 2/7] SimicsIch10Pkg: Add Ich Pkg for SimicsIch10 David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add modules Include, Library, SimicsDxe, SimicsPei, Policy, SmbiosPlatformDxe
and SecCore for Simics Quick Start Platform support

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 .../SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c   |  647 ++++++++
 .../Library/LoadLinuxLib/Linux.c                   |  662 +++++++++
 .../Library/LoadLinuxLib/LinuxGdt.c                |  175 +++
 .../Library/NvVarsFileLib/FsAccess.c               |  507 +++++++
 .../Library/NvVarsFileLib/NvVarsFileLib.c          |   77 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    |  419 ++++++
 .../SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c |  100 ++
 .../Library/PeiReportFvLib/PeiReportFvLib.c        |  119 ++
 .../Library/PlatformBootManagerLib/BdsPlatform.c   | 1553 ++++++++++++++++++++
 .../Library/PlatformBootManagerLib/PlatformData.c  |   35 +
 .../SerializeVariablesLib/SerializeVariablesLib.c  |  869 +++++++++++
 .../SiliconPolicyInitLib/SiliconPolicyInitLib.c    |  108 ++
 .../SiliconPolicyUpdateLib.c                       |   70 +
 .../Intel/SimicsOpenBoardPkg/SecCore/SecMain.c     |  956 ++++++++++++
 .../Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c  |  865 +++++++++++
 .../SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c  |  124 ++
 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c |   57 +
 .../SimicsOpenBoardPkg/SimicsPei/FeatureControl.c  |  115 ++
 .../Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c |  568 +++++++
 .../Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c  |  630 ++++++++
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.c          |  148 ++
 .../Include/Guid/SimicsBoardConfig.h               |   18 +
 .../Include/IndustryStandard/I440FxPiix4.h         |   50 +
 .../Include/IndustryStandard/LinuxBzImage.h        |  159 ++
 .../Include/Library/LoadLinuxLib.h                 |  205 +++
 .../Include/Library/SerializeVariablesLib.h        |  224 +++
 .../SimicsOpenBoardPkg/Include/SimicsPlatforms.h   |   55 +
 .../Library/DxeLogoLib/DxeLogoLib.inf              |   55 +
 .../Library/DxeLogoLib/OemBadging.h                |   83 ++
 .../Library/LoadLinuxLib/DxeLoadLinuxLib.inf       |   42 +
 .../Library/LoadLinuxLib/Ia32/JumpToKernel.nasm    |   41 +
 .../Library/LoadLinuxLib/LoadLinuxLib.h            |   52 +
 .../Library/LoadLinuxLib/X64/JumpToKernel.nasm     |   85 ++
 .../Library/NvVarsFileLib/NvVarsFileLib.h          |   55 +
 .../Library/NvVarsFileLib/NvVarsFileLib.inf        |   53 +
 .../Library/PciHostBridgeLib/PciHostBridge.h       |   68 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |   51 +
 .../Library/PeiReportFvLib/PeiReportFvLib.inf      |   56 +
 .../Library/PlatformBootManagerLib/BdsPlatform.h   |  172 +++
 .../PlatformBootManagerLib.inf                     |   72 +
 .../SerializeVariablesLib/SerializeVariablesLib.h  |   33 +
 .../SerializeVariablesLib.inf                      |   36 +
 .../SiliconPolicyInitLib/SiliconPolicyInitLib.inf  |   38 +
 .../SiliconPolicyUpdateLib.inf                     |   35 +
 .../SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm  |   45 +
 .../Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf   |   73 +
 .../SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm   |   45 +
 .../Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h  |   38 +
 .../SimicsOpenBoardPkg/SimicsDxe/Platform.uni      |   31 +
 .../SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h  |   52 +
 .../SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr |   67 +
 .../SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf     |   65 +
 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h |   50 +
 .../Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h  |   88 ++
 .../SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf     |  104 ++
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.h          |   38 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf        |   51 +
 57 files changed, 11289 insertions(+)
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf

diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
new file mode 100644
index 0000000000..48a718a90d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
@@ -0,0 +1,647 @@
+/** @file
+  BDS Lib functions which contain all the code to connect console device
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+#include <Protocol/SimpleTextOut.h>
+#include <OemBadging.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UgaDraw.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#include <IndustryStandard/Bmp.h>
+#include <Protocol/BootLogo.h>
+
+/**
+  Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+  is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+  buffer is passed in it will be used if it is big enough.
+
+  @param  BmpImage      Pointer to BMP file
+  @param  BmpImageSize  Number of bytes in BmpImage
+  @param  GopBlt        Buffer containing GOP version of BmpImage.
+  @param  GopBltSize    Size of GopBlt in bytes.
+  @param  PixelHeight   Height of GopBlt/BmpImage in pixels
+  @param  PixelWidth    Width of GopBlt/BmpImage in pixels
+
+  @retval EFI_SUCCESS           GopBlt and GopBltSize are returned.
+  @retval EFI_UNSUPPORTED       BmpImage is not a valid *.BMP image
+  @retval EFI_BUFFER_TOO_SMALL  The passed in GopBlt buffer is not big enough.
+                                GopBltSize will contain the required size.
+  @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate.
+
+**/
+EFI_STATUS
+ConvertBmpToGopBlt (
+  IN     VOID      *BmpImage,
+  IN     UINTN     BmpImageSize,
+  IN OUT VOID      **GopBlt,
+  IN OUT UINTN     *GopBltSize,
+     OUT UINTN     *PixelHeight,
+     OUT UINTN     *PixelWidth
+  )
+{
+  UINT8                         *Image;
+  UINT8                         *ImageHeader;
+  BMP_IMAGE_HEADER              *BmpHeader;
+  BMP_COLOR_MAP                 *BmpColorMap;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+  UINT64                        BltBufferSize;
+  UINTN                         Index;
+  UINTN                         Height;
+  UINTN                         Width;
+  UINTN                         ImageIndex;
+  UINT32                        DataSizePerLine;
+  BOOLEAN                       IsAllocated;
+  UINT32                        ColorMapNum;
+
+  if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+  if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Doesn't support compress.
+  //
+  if (BmpHeader->CompressionType != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Only support BITMAPINFOHEADER format.
+  // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
+  //
+  if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // The data size in each line must be 4 byte alignment.
+  //
+  DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
+  BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
+  if (BltBufferSize > (UINT32) ~0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((BmpHeader->Size != BmpImageSize) ||
+      (BmpHeader->Size < BmpHeader->ImageOffset) ||
+      (BmpHeader->Size - BmpHeader->ImageOffset !=  BmpHeader->PixelHeight * DataSizePerLine)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Calculate Color Map offset in the image.
+  //
+  Image       = BmpImage;
+  BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+  if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
+    switch (BmpHeader->BitPerPixel) {
+      case 1:
+        ColorMapNum = 2;
+        break;
+      case 4:
+        ColorMapNum = 16;
+        break;
+      case 8:
+        ColorMapNum = 256;
+        break;
+      default:
+        ColorMapNum = 0;
+        break;
+      }
+    //
+    // BMP file may has padding data between the bmp header section and the bmp data section.
+    //
+    if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Calculate graphics image data address in the image
+  //
+  Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+  ImageHeader   = Image;
+
+  //
+  // Calculate the BltBuffer needed size.
+  //
+  BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+  //
+  // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+  //
+  if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+    return EFI_UNSUPPORTED;
+  }
+  BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+  IsAllocated   = FALSE;
+  if (*GopBlt == NULL) {
+    //
+    // GopBlt is not allocated by caller.
+    //
+    *GopBltSize = (UINTN) BltBufferSize;
+    *GopBlt     = AllocatePool (*GopBltSize);
+    IsAllocated = TRUE;
+    if (*GopBlt == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  } else {
+    //
+    // GopBlt has been allocated by caller.
+    //
+    if (*GopBltSize < (UINTN) BltBufferSize) {
+      *GopBltSize = (UINTN) BltBufferSize;
+      return EFI_BUFFER_TOO_SMALL;
+    }
+  }
+
+  *PixelWidth   = BmpHeader->PixelWidth;
+  *PixelHeight  = BmpHeader->PixelHeight;
+
+  //
+  // Convert image from BMP to Blt buffer format
+  //
+  BltBuffer = *GopBlt;
+  for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+    Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+    for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+      switch (BmpHeader->BitPerPixel) {
+      case 1:
+        //
+        // Convert 1-bit (2 colors) BMP to 24-bit color
+        //
+        for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+          Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+          Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+          Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+          Blt++;
+          Width++;
+        }
+
+        Blt--;
+        Width--;
+        break;
+
+      case 4:
+        //
+        // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+        //
+        Index       = (*Image) >> 4;
+        Blt->Red    = BmpColorMap[Index].Red;
+        Blt->Green  = BmpColorMap[Index].Green;
+        Blt->Blue   = BmpColorMap[Index].Blue;
+        if (Width < (BmpHeader->PixelWidth - 1)) {
+          Blt++;
+          Width++;
+          Index       = (*Image) & 0x0f;
+          Blt->Red    = BmpColorMap[Index].Red;
+          Blt->Green  = BmpColorMap[Index].Green;
+          Blt->Blue   = BmpColorMap[Index].Blue;
+        }
+        break;
+
+      case 8:
+        //
+        // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+        //
+        Blt->Red    = BmpColorMap[*Image].Red;
+        Blt->Green  = BmpColorMap[*Image].Green;
+        Blt->Blue   = BmpColorMap[*Image].Blue;
+        break;
+
+      case 24:
+        //
+        // It is 24-bit BMP.
+        //
+        Blt->Blue   = *Image++;
+        Blt->Green  = *Image++;
+        Blt->Red    = *Image;
+        break;
+
+      default:
+        //
+        // Other bit format BMP is not supported.
+        //
+        if (IsAllocated) {
+          FreePool (*GopBlt);
+          *GopBlt = NULL;
+        }
+        return EFI_UNSUPPORTED;
+        break;
+      };
+
+    }
+
+    ImageIndex = (UINTN) (Image - ImageHeader);
+    if ((ImageIndex % 4) != 0) {
+      //
+      // Bmp Image starts each row on a 32-bit boundary!
+      //
+      Image = Image + (4 - (ImageIndex % 4));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Use SystemTable Conout to stop video based Simple Text Out consoles from going
+  to the video device. Put up LogoFile on every video device that is a console.
+
+  @param[in]  LogoFile   File name of logo to display on the center of the screen.
+
+  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and logo displayed.
+  @retval EFI_UNSUPPORTED Logo not found
+
+**/
+EFI_STATUS
+EFIAPI
+EnableBootLogo (
+  IN  EFI_GUID  *LogoFile
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_OEM_BADGING_PROTOCOL      *Badging;
+  UINT32                        SizeOfX;
+  UINT32                        SizeOfY;
+  INTN                          DestX;
+  INTN                          DestY;
+  UINT8                         *ImageData;
+  UINTN                         ImageSize;
+  UINTN                         BltSize;
+  UINT32                        Instance;
+  EFI_BADGING_FORMAT            Format;
+  EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
+  UINTN                         CoordinateX;
+  UINTN                         CoordinateY;
+  UINTN                         Height;
+  UINTN                         Width;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+  EFI_UGA_DRAW_PROTOCOL         *UgaDraw;
+  UINT32                        ColorDepth;
+  UINT32                        RefreshRate;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
+  EFI_BOOT_LOGO_PROTOCOL        *BootLogo;
+  UINTN                         NumberOfLogos;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
+  UINTN                         LogoDestX;
+  UINTN                         LogoDestY;
+  UINTN                         LogoHeight;
+  UINTN                         LogoWidth;
+  UINTN                         NewDestX;
+  UINTN                         NewDestY;
+  UINTN                         NewHeight;
+  UINTN                         NewWidth;
+  UINT64                        BufferSize;
+
+  UgaDraw = NULL;
+  //
+  // Try to open GOP first
+  //
+  Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
+  if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
+    GraphicsOutput = NULL;
+    //
+    // Open GOP failed, try to open UGA
+    //
+    Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
+  }
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Try to open Boot Logo Protocol.
+  //
+  BootLogo = NULL;
+  gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
+
+  //
+  // Erase Cursor from screen
+  //
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+  Badging = NULL;
+  Status  = gBS->LocateProtocol (&gEfiOemBadgingProtocolGuid, NULL, (VOID **) &Badging);
+
+  if (GraphicsOutput != NULL) {
+    SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+    SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+
+  } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+    Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
+    if (EFI_ERROR (Status)) {
+      return EFI_UNSUPPORTED;
+    }
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  Blt = NULL;
+  NumberOfLogos = 0;
+  LogoDestX = 0;
+  LogoDestY = 0;
+  LogoHeight = 0;
+  LogoWidth = 0;
+  NewDestX = 0;
+  NewDestY = 0;
+  NewHeight = 0;
+  NewWidth = 0;
+  Instance = 0;
+  while (1) {
+    ImageData = NULL;
+    ImageSize = 0;
+
+    if (Badging != NULL) {
+      //
+      // Get image from OEMBadging protocol.
+      //
+      Status = Badging->GetImage (
+                          Badging,
+                          &Instance,
+                          &Format,
+                          &ImageData,
+                          &ImageSize,
+                          &Attribute,
+                          &CoordinateX,
+                          &CoordinateY
+                          );
+      if (EFI_ERROR (Status)) {
+        goto Done;
+      }
+
+    } else {
+      //
+      // Get the specified image from FV.
+      //
+      Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
+      if (EFI_ERROR (Status)) {
+        return EFI_UNSUPPORTED;
+      }
+
+      CoordinateX = 0;
+      CoordinateY = 0;
+      Attribute   = EfiBadgingDisplayAttributeCenter;
+    }
+
+    if (Blt != NULL) {
+      FreePool (Blt);
+    }
+
+    //
+    // Try BMP decoder
+    //
+    Blt = NULL;
+    Status = ConvertBmpToGopBlt (
+              ImageData,
+              ImageSize,
+              (VOID **) &Blt,
+              &BltSize,
+              &Height,
+              &Width
+              );
+
+    if (EFI_ERROR (Status)) {
+      FreePool (ImageData);
+
+      if (Badging == NULL) {
+        return Status;
+      } else {
+        continue;
+      }
+    }
+
+    //
+    // Calculate the display position according to Attribute.
+    //
+    switch (Attribute) {
+    case EfiBadgingDisplayAttributeLeftTop:
+      DestX = CoordinateX;
+      DestY = CoordinateY;
+      break;
+
+    case EfiBadgingDisplayAttributeCenterTop:
+      DestX = (SizeOfX - Width) / 2;
+      DestY = CoordinateY;
+      break;
+
+    case EfiBadgingDisplayAttributeRightTop:
+      DestX = (SizeOfX - Width - CoordinateX);
+      DestY = CoordinateY;;
+      break;
+
+    case EfiBadgingDisplayAttributeCenterRight:
+      DestX = (SizeOfX - Width - CoordinateX);
+      DestY = (SizeOfY - Height) / 2;
+      break;
+
+    case EfiBadgingDisplayAttributeRightBottom:
+      DestX = (SizeOfX - Width - CoordinateX);
+      DestY = (SizeOfY - Height - CoordinateY);
+      break;
+
+    case EfiBadgingDisplayAttributeCenterBottom:
+      DestX = (SizeOfX - Width) / 2;
+      DestY = (SizeOfY - Height - CoordinateY);
+      break;
+
+    case EfiBadgingDisplayAttributeLeftBottom:
+      DestX = CoordinateX;
+      DestY = (SizeOfY - Height - CoordinateY);
+      break;
+
+    case EfiBadgingDisplayAttributeCenterLeft:
+      DestX = CoordinateX;
+      DestY = (SizeOfY - Height) / 2;
+      break;
+
+    case EfiBadgingDisplayAttributeCenter:
+      DestX = (SizeOfX - Width) / 2;
+      DestY = (SizeOfY - Height) / 2;
+      break;
+
+    default:
+      DestX = CoordinateX;
+      DestY = CoordinateY;
+      break;
+    }
+
+    if ((DestX >= 0) && (DestY >= 0)) {
+      if (GraphicsOutput != NULL) {
+        Status = GraphicsOutput->Blt (
+                            GraphicsOutput,
+                            Blt,
+                            EfiBltBufferToVideo,
+                            0,
+                            0,
+                            (UINTN) DestX,
+                            (UINTN) DestY,
+                            Width,
+                            Height,
+                            Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+                            );
+      } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+        Status = UgaDraw->Blt (
+                            UgaDraw,
+                            (EFI_UGA_PIXEL *) Blt,
+                            EfiUgaBltBufferToVideo,
+                            0,
+                            0,
+                            (UINTN) DestX,
+                            (UINTN) DestY,
+                            Width,
+                            Height,
+                            Width * sizeof (EFI_UGA_PIXEL)
+                            );
+      } else {
+        Status = EFI_UNSUPPORTED;
+      }
+
+      //
+      // Report displayed Logo information.
+      //
+      if (!EFI_ERROR (Status)) {
+        NumberOfLogos++;
+
+        if (LogoWidth == 0) {
+          //
+          // The first Logo.
+          //
+          LogoDestX = (UINTN) DestX;
+          LogoDestY = (UINTN) DestY;
+          LogoWidth = Width;
+          LogoHeight = Height;
+        } else {
+          //
+          // Merge new logo with old one.
+          //
+          NewDestX = MIN ((UINTN) DestX, LogoDestX);
+          NewDestY = MIN ((UINTN) DestY, LogoDestY);
+          NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;
+          NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;
+
+          LogoDestX = NewDestX;
+          LogoDestY = NewDestY;
+          LogoWidth = NewWidth;
+          LogoHeight = NewHeight;
+        }
+      }
+    }
+
+    FreePool (ImageData);
+
+    if (Badging == NULL) {
+      break;
+    }
+  }
+
+Done:
+  if (BootLogo == NULL || NumberOfLogos == 0) {
+    //
+    // No logo displayed.
+    //
+    if (Blt != NULL) {
+      FreePool (Blt);
+    }
+
+    return Status;
+  }
+
+  //
+  // Advertise displayed Logo information.
+  //
+  if (NumberOfLogos == 1) {
+    //
+    // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
+    //
+    LogoBlt = Blt;
+    Status = EFI_SUCCESS;
+  } else {
+    //
+    // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
+    //
+    if (Blt != NULL) {
+      FreePool (Blt);
+    }
+
+    //
+    // Ensure the LogoHeight * LogoWidth doesn't overflow
+    //
+    if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {
+      return EFI_UNSUPPORTED;
+    }
+    BufferSize = MultU64x64 (LogoWidth, LogoHeight);
+
+    //
+    // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+    //
+    if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+      return EFI_UNSUPPORTED;
+    }
+
+    LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+    if (LogoBlt == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    if (GraphicsOutput != NULL) {
+      Status = GraphicsOutput->Blt (
+                          GraphicsOutput,
+                          LogoBlt,
+                          EfiBltVideoToBltBuffer,
+                          LogoDestX,
+                          LogoDestY,
+                          0,
+                          0,
+                          LogoWidth,
+                          LogoHeight,
+                          LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+                          );
+    } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+      Status = UgaDraw->Blt (
+                          UgaDraw,
+                          (EFI_UGA_PIXEL *) LogoBlt,
+                          EfiUgaVideoToBltBuffer,
+                          LogoDestX,
+                          LogoDestY,
+                          0,
+                          0,
+                          LogoWidth,
+                          LogoHeight,
+                          LogoWidth * sizeof (EFI_UGA_PIXEL)
+                          );
+    } else {
+      Status = EFI_UNSUPPORTED;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);
+  }
+  FreePool (LogoBlt);
+
+  return Status;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
new file mode 100644
index 0000000000..631bb7ee69
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
@@ -0,0 +1,662 @@
+/** @file
+  Copyright (c) 2011 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "LoadLinuxLib.h"
+
+
+/**
+  A simple check of the kernel setup image
+
+  An assumption is made that the size of the data is at least the
+  size of struct boot_params.
+
+  @param[in]    KernelSetup - The kernel setup image
+
+  @retval    EFI_SUCCESS - The kernel setup looks valid and supported
+  @retval    EFI_INVALID_PARAMETER - KernelSetup was NULL
+  @retval    EFI_UNSUPPORTED - The kernel setup is not valid or supported
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BasicKernelSetupCheck (
+  IN VOID        *KernelSetup
+  )
+{
+  return LoadLinuxCheckKernelSetup(KernelSetup, sizeof (struct boot_params));
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxCheckKernelSetup (
+  IN VOID        *KernelSetup,
+  IN UINTN       KernelSetupSize
+  )
+{
+  struct boot_params        *Bp;
+
+  if (KernelSetup == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (KernelSetupSize < sizeof (*Bp)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  if ((Bp->hdr.signature != 0xAA55) || // Check boot sector signature
+      (Bp->hdr.header != SETUP_HDR) ||
+      (Bp->hdr.version < 0x205) || // We only support relocatable kernels
+      (!Bp->hdr.relocatable_kernel)
+     ) {
+    return EFI_UNSUPPORTED;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+
+UINTN
+EFIAPI
+LoadLinuxGetKernelSize (
+  IN VOID        *KernelSetup,
+  IN UINTN       KernelSize
+  )
+{
+  struct boot_params        *Bp;
+
+  if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+    return 0;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  if (Bp->hdr.version > 0x20a) {
+    return Bp->hdr.init_size;
+  } else {
+    //
+    // Add extra size for kernel decompression
+    //
+    return 3 * KernelSize;
+  }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelSetupPages (
+  IN UINTN                  Pages
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      Address;
+
+  Address = BASE_1GB;
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiLoaderData,
+                  Pages,
+                  &Address
+                  );
+  if (!EFI_ERROR (Status)) {
+    return (VOID*)(UINTN) Address;
+  } else {
+    return NULL;
+  }
+}
+
+EFI_STATUS
+EFIAPI
+LoadLinuxInitializeKernelSetup (
+  IN VOID        *KernelSetup
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     SetupEnd;
+  struct boot_params        *Bp;
+
+  Status = BasicKernelSetupCheck (KernelSetup);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  SetupEnd = 0x202 + (Bp->hdr.jump & 0xff);
+
+  //
+  // Clear all but the setup_header
+  //
+  ZeroMem (KernelSetup, 0x1f1);
+  ZeroMem (((UINT8 *)KernelSetup) + SetupEnd, 4096 - SetupEnd);
+  DEBUG ((EFI_D_INFO, "Cleared kernel setup 0-0x1f1, 0x%Lx-0x1000\n",
+    (UINT64)SetupEnd));
+
+  return EFI_SUCCESS;
+}
+
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelPages (
+  IN VOID                   *KernelSetup,
+  IN UINTN                  Pages
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      KernelAddress;
+  UINT32                    Loop;
+  struct boot_params        *Bp;
+
+  if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+    return NULL;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  for (Loop = 1; Loop < 512; Loop++) {
+    KernelAddress = MultU64x32 (
+                      2 * Bp->hdr.kernel_alignment,
+                      Loop
+                      );
+    Status = gBS->AllocatePages (
+                    AllocateAddress,
+                    EfiLoaderData,
+                    Pages,
+                    &KernelAddress
+                    );
+    if (!EFI_ERROR (Status)) {
+      return (VOID*)(UINTN) KernelAddress;
+    }
+  }
+
+  return NULL;
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateCommandLinePages (
+  IN UINTN                  Pages
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      Address;
+
+  Address = 0xa0000;
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiLoaderData,
+                  Pages,
+                  &Address
+                  );
+  if (!EFI_ERROR (Status)) {
+    return (VOID*)(UINTN) Address;
+  } else {
+    return NULL;
+  }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateInitrdPages (
+  IN VOID                   *KernelSetup,
+  IN UINTN                  Pages
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      Address;
+
+  struct boot_params        *Bp;
+
+  if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+    return NULL;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Bp->hdr.ramdisk_max;
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiLoaderData,
+                  Pages,
+                  &Address
+                  );
+  if (!EFI_ERROR (Status)) {
+    return (VOID*)(UINTN) Address;
+  } else {
+    return NULL;
+  }
+}
+
+
+STATIC
+VOID
+SetupLinuxMemmap (
+  IN OUT struct boot_params        *Bp
+  )
+{
+  EFI_STATUS                           Status;
+  UINT8                                TmpMemoryMap[1];
+  UINTN                                MapKey;
+  UINTN                                DescriptorSize;
+  UINT32                               DescriptorVersion;
+  UINTN                                MemoryMapSize;
+  EFI_MEMORY_DESCRIPTOR                *MemoryMap;
+  EFI_MEMORY_DESCRIPTOR                *MemoryMapPtr;
+  UINTN                                Index;
+  struct efi_info                      *Efi;
+  struct e820_entry                    *LastE820;
+  struct e820_entry                    *E820;
+  UINTN                                E820EntryCount;
+  EFI_PHYSICAL_ADDRESS                 LastEndAddr;
+
+  //
+  // Get System MemoryMapSize
+  //
+  MemoryMapSize = sizeof (TmpMemoryMap);
+  Status = gBS->GetMemoryMap (
+                  &MemoryMapSize,
+                  (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,
+                  &MapKey,
+                  &DescriptorSize,
+                  &DescriptorVersion
+                  );
+  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+  //
+  // Enlarge space here, because we will allocate pool now.
+  //
+  MemoryMapSize += EFI_PAGE_SIZE;
+  Status = gBS->AllocatePool (
+                  EfiLoaderData,
+                  MemoryMapSize,
+                  (VOID **) &MemoryMap
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Get System MemoryMap
+  //
+  Status = gBS->GetMemoryMap (
+                  &MemoryMapSize,
+                  MemoryMap,
+                  &MapKey,
+                  &DescriptorSize,
+                  &DescriptorVersion
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  LastE820 = NULL;
+  E820 = &Bp->e820_map[0];
+  E820EntryCount = 0;
+  LastEndAddr = 0;
+  MemoryMapPtr = MemoryMap;
+  for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {
+    UINTN E820Type = 0;
+
+    if (MemoryMap->NumberOfPages == 0) {
+      continue;
+    }
+
+    switch(MemoryMap->Type) {
+    case EfiReservedMemoryType:
+    case EfiRuntimeServicesCode:
+    case EfiRuntimeServicesData:
+    case EfiMemoryMappedIO:
+    case EfiMemoryMappedIOPortSpace:
+    case EfiPalCode:
+      E820Type = E820_RESERVED;
+      break;
+
+    case EfiUnusableMemory:
+      E820Type = E820_UNUSABLE;
+      break;
+
+    case EfiACPIReclaimMemory:
+      E820Type = E820_ACPI;
+      break;
+
+    case EfiLoaderCode:
+    case EfiLoaderData:
+    case EfiBootServicesCode:
+    case EfiBootServicesData:
+    case EfiConventionalMemory:
+      E820Type = E820_RAM;
+      break;
+
+    case EfiACPIMemoryNVS:
+      E820Type = E820_NVS;
+      break;
+
+    default:
+      DEBUG ((
+        EFI_D_ERROR,
+        "Invalid EFI memory descriptor type (0x%x)!\n",
+        MemoryMap->Type
+        ));
+      continue;
+    }
+
+    if ((LastE820 != NULL) &&
+        (LastE820->type == (UINT32) E820Type) &&
+        (MemoryMap->PhysicalStart == LastEndAddr)) {
+      LastE820->size += EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
+      LastEndAddr += EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
+    } else {
+      if (E820EntryCount >= (sizeof (Bp->e820_map) / sizeof (Bp->e820_map[0]))) {
+        break;
+      }
+      E820->type = (UINT32) E820Type;
+      E820->addr = MemoryMap->PhysicalStart;
+      E820->size = EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
+      LastE820 = E820;
+      LastEndAddr = E820->addr + E820->size;
+      E820++;
+      E820EntryCount++;
+    }
+
+    //
+    // Get next item
+    //
+    MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);
+  }
+  Bp->e820_entries = (UINT8) E820EntryCount;
+
+  Efi = &Bp->efi_info;
+  Efi->efi_systab = (UINT32)(UINTN) gST;
+  Efi->efi_memdesc_size = (UINT32) DescriptorSize;
+  Efi->efi_memdesc_version = DescriptorVersion;
+  Efi->efi_memmap = (UINT32)(UINTN) MemoryMapPtr;
+  Efi->efi_memmap_size = (UINT32) MemoryMapSize;
+#ifdef MDE_CPU_IA32
+  Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '3', '2');
+#else
+  Efi->efi_systab_hi = (UINT32) (((UINT64)(UINTN) gST) >> 32);
+  Efi->efi_memmap_hi = (UINT32) (((UINT64)(UINTN) MemoryMapPtr) >> 32);
+  Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '6', '4');
+#endif
+
+  gBS->ExitBootServices (gImageHandle, MapKey);
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxSetCommandLine (
+  IN OUT VOID    *KernelSetup,
+  IN CHAR8       *CommandLine
+  )
+{
+  EFI_STATUS             Status;
+  struct boot_params     *Bp;
+
+  Status = BasicKernelSetupCheck (KernelSetup);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  Bp->hdr.cmd_line_ptr = (UINT32)(UINTN) CommandLine;
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxSetInitrd (
+  IN OUT VOID    *KernelSetup,
+  IN VOID        *Initrd,
+  IN UINTN       InitrdSize
+  )
+{
+  EFI_STATUS             Status;
+  struct boot_params     *Bp;
+
+  Status = BasicKernelSetupCheck (KernelSetup);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Bp = (struct boot_params*) KernelSetup;
+
+  Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;
+  Bp->hdr.ramdisk_len = (UINT32) InitrdSize;
+
+  return EFI_SUCCESS;
+}
+
+
+STATIC VOID
+FindBits (
+  unsigned long Mask,
+  UINT8 *Pos,
+  UINT8 *Size
+  )
+{
+  UINT8 First, Len;
+
+  First = 0;
+  Len = 0;
+
+  if (Mask) {
+    while (!(Mask & 0x1)) {
+      Mask = Mask >> 1;
+      First++;
+    }
+
+    while (Mask & 0x1) {
+      Mask = Mask >> 1;
+      Len++;
+    }
+  }
+  *Pos = First;
+  *Size = Len;
+}
+
+
+STATIC
+EFI_STATUS
+SetupGraphicsFromGop (
+  struct screen_info           *Si,
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
+  )
+{
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+  EFI_STATUS                           Status;
+  UINTN                                Size;
+
+  Status = Gop->QueryMode(Gop, Gop->Mode->Mode, &Size, &Info);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  /* We found a GOP */
+
+  /* EFI framebuffer */
+  Si->orig_video_isVGA = 0x70;
+
+  Si->orig_x = 0;
+  Si->orig_y = 0;
+  Si->orig_video_page = 0;
+  Si->orig_video_mode = 0;
+  Si->orig_video_cols = 0;
+  Si->orig_video_lines = 0;
+  Si->orig_video_ega_bx = 0;
+  Si->orig_video_points = 0;
+
+  Si->lfb_base = (UINT32) Gop->Mode->FrameBufferBase;
+  Si->lfb_size = (UINT32) Gop->Mode->FrameBufferSize;
+  Si->lfb_width = (UINT16) Info->HorizontalResolution;
+  Si->lfb_height = (UINT16) Info->VerticalResolution;
+  Si->pages = 1;
+  Si->vesapm_seg = 0;
+  Si->vesapm_off = 0;
+
+  if (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
+    Si->lfb_depth = 32;
+    Si->red_size = 8;
+    Si->red_pos = 0;
+    Si->green_size = 8;
+    Si->green_pos = 8;
+    Si->blue_size = 8;
+    Si->blue_pos = 16;
+    Si->rsvd_size = 8;
+    Si->rsvd_pos = 24;
+    Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
+
+  } else if (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
+    Si->lfb_depth = 32;
+    Si->red_size = 8;
+    Si->red_pos = 16;
+    Si->green_size = 8;
+    Si->green_pos = 8;
+    Si->blue_size = 8;
+    Si->blue_pos = 0;
+    Si->rsvd_size = 8;
+    Si->rsvd_pos = 24;
+    Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
+  } else if (Info->PixelFormat == PixelBitMask) {
+    FindBits(Info->PixelInformation.RedMask,
+        &Si->red_pos, &Si->red_size);
+    FindBits(Info->PixelInformation.GreenMask,
+        &Si->green_pos, &Si->green_size);
+    FindBits(Info->PixelInformation.BlueMask,
+        &Si->blue_pos, &Si->blue_size);
+    FindBits(Info->PixelInformation.ReservedMask,
+        &Si->rsvd_pos, &Si->rsvd_size);
+    Si->lfb_depth = Si->red_size + Si->green_size +
+      Si->blue_size + Si->rsvd_size;
+    Si->lfb_linelength = (UINT16) ((Info->PixelsPerScanLine * Si->lfb_depth) / 8);
+  } else {
+    Si->lfb_depth = 4;
+    Si->red_size = 0;
+    Si->red_pos = 0;
+    Si->green_size = 0;
+    Si->green_pos = 0;
+    Si->blue_size = 0;
+    Si->blue_pos = 0;
+    Si->rsvd_size = 0;
+    Si->rsvd_pos = 0;
+    Si->lfb_linelength = Si->lfb_width / 2;
+  }
+
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+SetupGraphics (
+  IN OUT struct boot_params *Bp
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_HANDLE                      *HandleBuffer;
+  UINTN                           HandleCount;
+  UINTN                           Index;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL    *Gop;
+
+  ZeroMem ((VOID*)&Bp->screen_info, sizeof(Bp->screen_info));
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    for (Index = 0; Index < HandleCount; Index++) {
+      Status = gBS->HandleProtocol (
+                      HandleBuffer[Index],
+                      &gEfiGraphicsOutputProtocolGuid,
+                      (VOID*) &Gop
+                      );
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      Status = SetupGraphicsFromGop (&Bp->screen_info, Gop);
+      if (!EFI_ERROR (Status)) {
+        FreePool (HandleBuffer);
+        return EFI_SUCCESS;
+      }
+    }
+
+    FreePool (HandleBuffer);
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
+STATIC
+EFI_STATUS
+SetupLinuxBootParams (
+  IN OUT struct boot_params *Bp
+  )
+{
+  SetupGraphics (Bp);
+
+  SetupLinuxMemmap (Bp);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinux (
+  IN VOID      *Kernel,
+  IN OUT VOID  *KernelSetup
+  )
+{
+  EFI_STATUS             Status;
+  struct boot_params  *Bp;
+
+  Status = BasicKernelSetupCheck (KernelSetup);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Bp = (struct boot_params *) KernelSetup;
+
+  if (Bp->hdr.version < 0x205 || !Bp->hdr.relocatable_kernel) {
+    //
+    // We only support relocatable kernels
+    //
+    return EFI_UNSUPPORTED;
+  }
+
+  InitLinuxDescriptorTables ();
+
+  Bp->hdr.code32_start = (UINT32)(UINTN) Kernel;
+  if (Bp->hdr.version >= 0x20c && Bp->hdr.handover_offset &&
+      (Bp->hdr.xloadflags & (sizeof (UINTN) == 4 ? BIT2 : BIT3))) {
+    DEBUG ((EFI_D_INFO, "Jumping to kernel EFI handover point at ofs %x\n", Bp->hdr.handover_offset));
+
+    DisableInterrupts ();
+    JumpToUefiKernel ((VOID*) gImageHandle, (VOID*) gST, KernelSetup, Kernel);
+  }
+
+  //
+  // Old kernels without EFI handover protocol
+  //
+  SetupLinuxBootParams (KernelSetup);
+
+  DEBUG ((EFI_D_INFO, "Jumping to kernel\n"));
+  DisableInterrupts ();
+  SetLinuxDescriptorTables ();
+  JumpToKernel (Kernel, (VOID*) KernelSetup);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
new file mode 100644
index 0000000000..fda185e3d7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
@@ -0,0 +1,175 @@
+/** @file
+  Initialize GDT for Linux.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "LoadLinuxLib.h"
+
+
+//
+// Local structure definitions
+//
+
+#pragma pack (1)
+
+//
+// Global Descriptor Entry structures
+//
+
+typedef struct _GDT_ENTRY {
+  UINT16 Limit15_0;
+  UINT16 Base15_0;
+  UINT8  Base23_16;
+  UINT8  Type;
+  UINT8  Limit19_16_and_flags;
+  UINT8  Base31_24;
+} GDT_ENTRY;
+
+typedef
+struct _GDT_ENTRIES {
+  GDT_ENTRY Null;
+  GDT_ENTRY Null2;
+  GDT_ENTRY Linear;
+  GDT_ENTRY LinearCode;
+  GDT_ENTRY TaskSegment;
+  GDT_ENTRY Spare4;
+  GDT_ENTRY Spare5;
+} GDT_ENTRIES;
+
+#pragma pack ()
+
+STATIC GDT_ENTRIES *mGdt = NULL;
+
+//
+// Global descriptor table (GDT) Template
+//
+STATIC GDT_ENTRIES GdtTemplate = {
+  //
+  // Null
+  //
+  {
+    0x0,            // limit 15:0
+    0x0,            // base 15:0
+    0x0,            // base 23:16
+    0x0,            // type
+    0x0,            // limit 19:16, flags
+    0x0,            // base 31:24
+  },
+  //
+  // Null2
+  //
+  {
+    0x0,            // limit 15:0
+    0x0,            // base 15:0
+    0x0,            // base 23:16
+    0x0,            // type
+    0x0,            // limit 19:16, flags
+    0x0,            // base 31:24
+  },
+  //
+  // Linear
+  //
+  {
+    0x0FFFF,        // limit 0xFFFFF
+    0x0,            // base 0
+    0x0,
+    0x09A,          // present, ring 0, data, expand-up, writable
+    0x0CF,          // page-granular, 32-bit
+    0x0,
+  },
+  //
+  // LinearCode
+  //
+  {
+    0x0FFFF,        // limit 0xFFFFF
+    0x0,            // base 0
+    0x0,
+    0x092,          // present, ring 0, data, expand-up, writable
+    0x0CF,          // page-granular, 32-bit
+    0x0,
+  },
+  //
+  // TaskSegment
+  //
+  {
+    0x0,            // limit 0
+    0x0,            // base 0
+    0x0,
+    0x089,          // ?
+    0x080,          // ?
+    0x0,
+  },
+  //
+  // Spare4
+  //
+  {
+    0x0,            // limit 0
+    0x0,            // base 0
+    0x0,
+    0x0,            // present, ring 0, data, expand-up, writable
+    0x0,            // page-granular, 32-bit
+    0x0,
+  },
+  //
+  // Spare5
+  //
+  {
+    0x0,            // limit 0
+    0x0,            // base 0
+    0x0,
+    0x0,            // present, ring 0, data, expand-up, writable
+    0x0,            // page-granular, 32-bit
+    0x0,
+  },
+};
+
+/**
+  Initialize Global Descriptor Table.
+
+**/
+VOID
+InitLinuxDescriptorTables (
+  VOID
+  )
+{
+  //
+  // Allocate Runtime Data for the GDT
+  //
+  mGdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+  ASSERT (mGdt != NULL);
+  mGdt = ALIGN_POINTER (mGdt, 8);
+
+  //
+  // Initialize all GDT entries
+  //
+  CopyMem (mGdt, &GdtTemplate, sizeof (GdtTemplate));
+
+}
+
+/**
+  Initialize Global Descriptor Table.
+
+**/
+VOID
+SetLinuxDescriptorTables (
+  VOID
+  )
+{
+  IA32_DESCRIPTOR GdtPtr;
+  IA32_DESCRIPTOR IdtPtr;
+
+  //
+  // Write GDT register
+  //
+  GdtPtr.Base = (UINT32)(UINTN)(VOID*) mGdt;
+  GdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
+  AsmWriteGdtr (&GdtPtr);
+
+  IdtPtr.Base = (UINT32) 0;
+  IdtPtr.Limit = (UINT16) 0;
+  AsmWriteIdtr (&IdtPtr);
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
new file mode 100644
index 0000000000..3d98291410
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
@@ -0,0 +1,507 @@
+/** @file
+  File System Access for NvVarsFileLib
+
+  Copyright (c) 2004 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "NvVarsFileLib.h"
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+
+/**
+  Open the NvVars file for reading or writing
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+  @param[in]  ReadingFile - TRUE: open the file for reading.  FALSE: writing
+  @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
+                           with the opened NvVars file.
+
+  @return     EFI_SUCCESS if the file was opened
+
+**/
+EFI_STATUS
+GetNvVarsFile (
+  IN  EFI_HANDLE            FsHandle,
+  IN  BOOLEAN               ReadingFile,
+  OUT EFI_FILE_HANDLE       *NvVarsFile
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL       *Fs;
+  EFI_FILE_HANDLE                       Root;
+
+  //
+  // Get the FileSystem protocol on that handle
+  //
+  Status = gBS->HandleProtocol (
+                  FsHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID **)&Fs
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Get the volume (the root directory)
+  //
+  Status = Fs->OpenVolume (Fs, &Root);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Attempt to open the NvVars file in the root directory
+  //
+  Status = Root->Open (
+                   Root,
+                   NvVarsFile,
+                   L"NvVars",
+                   ReadingFile ?
+                     EFI_FILE_MODE_READ :
+                     (
+                       EFI_FILE_MODE_CREATE |
+                       EFI_FILE_MODE_READ |
+                       EFI_FILE_MODE_WRITE
+                     ),
+                   0
+                   );
+
+  return Status;
+}
+
+
+/**
+  Open the NvVars file for reading or writing
+
+  @param[in]  File - The file to inspect
+  @param[out] Exists - Returns whether the file exists
+  @param[out] Size - Returns the size of the file
+                     (0 if the file does not exist)
+
+**/
+VOID
+NvVarsFileReadCheckup (
+  IN  EFI_FILE_HANDLE        File,
+  OUT BOOLEAN                *Exists,
+  OUT UINTN                  *Size
+  )
+{
+  EFI_FILE_INFO               *FileInfo;
+
+  *Exists = FALSE;
+  *Size = 0;
+
+  FileInfo = FileHandleGetInfo (File);
+  if (FileInfo == NULL) {
+    return;
+  }
+
+  if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
+    FreePool (FileInfo);
+    return;
+  }
+
+  *Exists = TRUE;
+  *Size = (UINTN) FileInfo->FileSize;
+
+  FreePool (FileInfo);
+}
+
+
+/**
+  Open the NvVars file for reading or writing
+
+  @param[in]  File - The file to inspect
+  @param[out] Exists - Returns whether the file exists
+  @param[out] Size - Returns the size of the file
+                     (0 if the file does not exist)
+
+**/
+EFI_STATUS
+FileHandleEmpty (
+  IN  EFI_FILE_HANDLE        File
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_FILE_INFO               *FileInfo;
+
+  //
+  // Retrieve the FileInfo structure
+  //
+  FileInfo = FileHandleGetInfo (File);
+  if (FileInfo == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If the path is a directory, then return an error
+  //
+  if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
+    FreePool (FileInfo);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If the file size is already 0, then it is empty, so
+  // we can return success.
+  //
+  if (FileInfo->FileSize == 0) {
+    FreePool (FileInfo);
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Set the file size to 0.
+  //
+  FileInfo->FileSize = 0;
+  Status = FileHandleSetInfo (File, FileInfo);
+
+  FreePool (FileInfo);
+
+  return Status;
+}
+
+
+/**
+  Reads a file to a newly allocated buffer
+
+  @param[in]  File - The file to read
+  @param[in]  ReadSize - The size of data to read from the file
+
+  @return     Pointer to buffer allocated to hold the file
+              contents.  NULL if an error occurred.
+
+**/
+VOID*
+FileHandleReadToNewBuffer (
+  IN EFI_FILE_HANDLE            FileHandle,
+  IN UINTN                      ReadSize
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       ActualReadSize;
+  VOID                        *FileContents;
+
+  ActualReadSize = ReadSize;
+  FileContents = AllocatePool (ReadSize);
+  if (FileContents != NULL) {
+    Status = FileHandleRead (
+               FileHandle,
+               &ReadSize,
+               FileContents
+               );
+    if (EFI_ERROR (Status) || (ActualReadSize != ReadSize)) {
+      FreePool (FileContents);
+      return NULL;
+    }
+  }
+
+  return FileContents;
+}
+
+
+/**
+  Reads the contents of the NvVars file on the file system
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+  @return     EFI_STATUS based on the success or failure of the file read
+
+**/
+EFI_STATUS
+ReadNvVarsFile (
+  IN  EFI_HANDLE            FsHandle
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_FILE_HANDLE             File;
+  UINTN                       FileSize;
+  BOOLEAN                     FileExists;
+  VOID                        *FileContents;
+  EFI_HANDLE                  SerializedVariables;
+
+  Status = GetNvVarsFile (FsHandle, TRUE, &File);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "FsAccess.c: Could not open NV Variables file on this file system\n"));
+    return Status;
+  }
+
+  NvVarsFileReadCheckup (File, &FileExists, &FileSize);
+  if (FileSize == 0) {
+    FileHandleClose (File);
+    return EFI_UNSUPPORTED;
+  }
+
+  FileContents = FileHandleReadToNewBuffer (File, FileSize);
+  if (FileContents == NULL) {
+    FileHandleClose (File);
+    return EFI_UNSUPPORTED;
+  }
+
+  DEBUG ((
+    EFI_D_INFO,
+    "FsAccess.c: Read %Lu bytes from NV Variables file\n",
+    (UINT64)FileSize
+    ));
+
+  Status = SerializeVariablesNewInstanceFromBuffer (
+             &SerializedVariables,
+             FileContents,
+             FileSize
+             );
+  if (!RETURN_ERROR (Status)) {
+    Status = SerializeVariablesSetSerializedVariables (SerializedVariables);
+  }
+
+  FreePool (FileContents);
+  FileHandleClose (File);
+
+  return Status;
+}
+
+
+/**
+  Writes a variable to indicate that the NV variables
+  have been loaded from the file system.
+
+**/
+STATIC
+VOID
+SetNvVarsVariable (
+  VOID
+  )
+{
+  BOOLEAN                        VarData;
+  UINTN                          Size;
+
+  //
+  // Write a variable to indicate we've already loaded the
+  // variable data.  If it is found, we skip the loading on
+  // subsequent attempts.
+  //
+  Size = sizeof (VarData);
+  VarData = TRUE;
+  gRT->SetVariable (
+         L"NvVars",
+         &gEfiSimpleFileSystemProtocolGuid,
+         EFI_VARIABLE_NON_VOLATILE |
+           EFI_VARIABLE_BOOTSERVICE_ACCESS |
+           EFI_VARIABLE_RUNTIME_ACCESS,
+         Size,
+         (VOID*) &VarData
+         );
+}
+
+
+/**
+  Loads the non-volatile variables from the NvVars file on the
+  given file system.
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+  @return     EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+LoadNvVarsFromFs (
+  EFI_HANDLE                            FsHandle
+  )
+{
+  EFI_STATUS                     Status;
+  BOOLEAN                        VarData;
+  UINTN                          Size;
+
+  DEBUG ((EFI_D_INFO, "FsAccess.c: LoadNvVarsFromFs\n"));
+
+  //
+  // We write a variable to indicate we've already loaded the
+  // variable data.  If it is found, we skip the loading.
+  //
+  // This is relevant if the non-volatile variable have been
+  // able to survive a reboot operation.  In that case, we don't
+  // want to re-load the file as it would overwrite newer changes
+  // made to the variables.
+  //
+  Size = sizeof (VarData);
+  VarData = TRUE;
+  Status = gRT->GetVariable (
+                  L"NvVars",
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  NULL,
+                  &Size,
+                  (VOID*) &VarData
+                  );
+  if (Status == EFI_SUCCESS) {
+    DEBUG ((EFI_D_INFO, "NV Variables were already loaded\n"));
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Attempt to restore the variables from the NvVars file.
+  //
+  Status = ReadNvVarsFile (FsHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "Error while restoring NV variable data\n"));
+    return Status;
+  }
+
+  //
+  // Write a variable to indicate we've already loaded the
+  // variable data.  If it is found, we skip the loading on
+  // subsequent attempts.
+  //
+  SetNvVarsVariable();
+
+  DEBUG ((
+    EFI_D_INFO,
+    "FsAccess.c: Read NV Variables file (size=%Lu)\n",
+    (UINT64)Size
+    ));
+
+  return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackAddAllNvVariables (
+  IN  VOID                         *Context,
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid,
+  IN  UINT32                       Attributes,
+  IN  UINTN                        DataSize,
+  IN  VOID                         *Data
+  )
+{
+  EFI_HANDLE  Instance;
+
+  Instance = (EFI_HANDLE) Context;
+
+  //
+  // Only save non-volatile variables
+  //
+  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+    return RETURN_SUCCESS;
+  }
+
+  return SerializeVariablesAddVariable (
+           Instance,
+           VariableName,
+           VendorGuid,
+           Attributes,
+           DataSize,
+           Data
+           );
+}
+
+
+/**
+  Saves the non-volatile variables into the NvVars file on the
+  given file system.
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+  @return     EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+SaveNvVarsToFs (
+  EFI_HANDLE                            FsHandle
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_FILE_HANDLE             File;
+  UINTN                       WriteSize;
+  UINTN                       VariableDataSize;
+  VOID                        *VariableData;
+  EFI_HANDLE                  SerializedVariables;
+
+  SerializedVariables = NULL;
+
+  Status = SerializeVariablesNewInstance (&SerializedVariables);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = SerializeVariablesIterateSystemVariables (
+             IterateVariablesCallbackAddAllNvVariables,
+             (VOID*) SerializedVariables
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  VariableData = NULL;
+  VariableDataSize = 0;
+  Status = SerializeVariablesToBuffer (
+             SerializedVariables,
+             NULL,
+             &VariableDataSize
+             );
+  if (Status == RETURN_BUFFER_TOO_SMALL) {
+    VariableData = AllocatePool (VariableDataSize);
+    if (VariableData == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+    } else {
+      Status = SerializeVariablesToBuffer (
+                 SerializedVariables,
+                 VariableData,
+                 &VariableDataSize
+                 );
+    }
+  }
+
+  SerializeVariablesFreeInstance (SerializedVariables);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the NvVars file for writing.
+  //
+  Status = GetNvVarsFile (FsHandle, FALSE, &File);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "FsAccess.c: Unable to open file to saved NV Variables\n"));
+    return Status;
+  }
+
+  //
+  // Empty the starting file contents.
+  //
+  Status = FileHandleEmpty (File);
+  if (EFI_ERROR (Status)) {
+    FileHandleClose (File);
+    return Status;
+  }
+
+  WriteSize = VariableDataSize;
+  Status = FileHandleWrite (File, &WriteSize, VariableData);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  FileHandleClose (File);
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Write a variable to indicate we've already loaded the
+    // variable data.  If it is found, we skip the loading on
+    // subsequent attempts.
+    //
+    SetNvVarsVariable();
+
+	DEBUG ((EFI_D_INFO, "Saved NV Variables to NvVars file\n"));
+  }
+
+  return Status;
+}
+
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
new file mode 100644
index 0000000000..2e9618455d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
@@ -0,0 +1,77 @@
+/** @file
+  Save Non-Volatile Variables to a file system.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "NvVarsFileLib.h"
+#include <Library/DebugLib.h>
+#include <Library/NvVarsFileLib.h>
+
+EFI_HANDLE    mNvVarsFileLibFsHandle = NULL;
+
+
+/**
+  Attempts to connect the NvVarsFileLib to the specified file system.
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+  @return     The EFI_STATUS while attempting to connect the NvVarsFileLib
+              to the file system instance.
+  @retval     EFI_SUCCESS - The given file system was connected successfully
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectNvVarsToFileSystem (
+  IN EFI_HANDLE    FsHandle
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // We might fail to load the variable, since the file system initially
+  // will not have the NvVars file.
+  //
+  LoadNvVarsFromFs (FsHandle);
+
+  //
+  // We must be able to save the variables successfully to the file system
+  // to have connected successfully.
+  //
+  Status = SaveNvVarsToFs (FsHandle);
+  if (!EFI_ERROR (Status)) {
+    mNvVarsFileLibFsHandle = FsHandle;
+  }
+
+  return Status;
+}
+
+
+/**
+  Update non-volatile variables stored on the file system.
+
+  @return     The EFI_STATUS while attempting to update the variable on
+              the connected file system.
+  @retval     EFI_SUCCESS - The non-volatile variables were saved to the disk
+  @retval     EFI_NOT_STARTED - A file system has not been connected
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateNvVarsOnFileSystem (
+  )
+{
+  if (mNvVarsFileLibFsHandle == NULL) {
+    //
+    // A file system had not been connected to the library.
+    //
+    return EFI_NOT_STARTED;
+  } else {
+    return SaveNvVarsToFs (mNvVarsFileLibFsHandle);
+  }
+}
+
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
new file mode 100644
index 0000000000..3b71c8ae97
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -0,0 +1,419 @@
+/** @file
+  SIMICS QSP's instance of the PCI Host Bridge Library.
+
+  Copyright (C) 2016, Red Hat, Inc.
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <Register/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/Library/PeiReportFvLib/Fv.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
new file mode 100644
index 0000000000..4e3762465a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
@@ -0,0 +1,100 @@
+/** @file
+  Build FV related hobs for platform.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PiPei.h"
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+BOOLEAN mS3Supported = TRUE;
+
+/**
+  Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+  and DXE know about them.
+
+  @retval EFI_SUCCESS   Platform PEI FVs were initialized successfully.
+
+**/
+EFI_STATUS
+PeiFvInitialization (
+  VOID
+  )
+{
+  BOOLEAN SecureS3Needed;
+
+  DEBUG ((EFI_D_INFO, "Platform PEI Firmware Volume Initialization\n"));
+
+  DEBUG (
+    (EFI_D_ERROR, "Firmware Volume HOB: 0x%x 0x%x\n",
+      PcdGet32 (PcdSimicsPeiMemFvBase),
+      PcdGet32 (PcdSimicsPeiMemFvSize)
+      )
+    );
+  //
+  // Create a memory allocation HOB for the PEI FV.
+  //
+  // Allocate as ACPI NVS is S3 is supported
+  //
+  BuildMemoryAllocationHob (
+    PcdGet32 (PcdSimicsPeiMemFvBase),
+    PcdGet32 (PcdSimicsPeiMemFvSize),
+    mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+    );
+
+  //
+  // Let DXE know about the DXE FV
+  //
+  BuildFvHob (PcdGet32 (PcdSimicsDxeMemFvBase), PcdGet32 (PcdSimicsDxeMemFvSize));
+
+  SecureS3Needed = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire);
+
+  //
+  // Create a memory allocation HOB for the DXE FV.
+  //
+  // If "secure" S3 is needed, then SEC will decompress both PEI and DXE
+  // firmware volumes at S3 resume too, hence we need to keep away the OS from
+  // DXEFV as well. Otherwise we only need to keep away DXE itself from the
+  // DXEFV area.
+  //
+  BuildMemoryAllocationHob (
+    PcdGet32 (PcdSimicsDxeMemFvBase),
+    PcdGet32 (PcdSimicsDxeMemFvSize),
+    SecureS3Needed ? EfiACPIMemoryNVS : EfiBootServicesData
+    );
+
+  //
+  // Additionally, said decompression will use temporary memory above the end
+  // of DXEFV, so let's keep away the OS from there too.
+  //
+  if (SecureS3Needed) {
+    UINT32 DxeMemFvEnd;
+
+    DxeMemFvEnd = PcdGet32 (PcdSimicsDxeMemFvBase) +
+                  PcdGet32 (PcdSimicsDxeMemFvSize);
+    BuildMemoryAllocationHob (
+      DxeMemFvEnd,
+      PcdGet32 (PcdSimicsDecompressionScratchEnd) - DxeMemFvEnd,
+      EfiACPIMemoryNVS
+      );
+  }
+
+  //
+  // Let PEI know about the DXE FV so it can find the DXE Core
+  //
+  PeiServicesInstallFvInfoPpi (
+    NULL,
+    (VOID *)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBase),
+    PcdGet32 (PcdSimicsDxeMemFvSize),
+    NULL,
+    NULL
+    );
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
new file mode 100644
index 0000000000..bb5a060b8e
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
@@ -0,0 +1,119 @@
+/** @file
+  Source code file for Report Firmware Volume (FV) library
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ReportFvLib.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Library/IoLib.h>
+#include <Register/X58Ich10.h>
+
+EFI_STATUS
+PeiFvInitialization(
+  VOID
+);
+
+VOID
+ReportPreMemFv (
+  VOID
+  )
+{
+  if (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) != 0x5) { // not S3 resume
+    PeiFvInitialization();
+  }
+
+  DEBUG ((DEBUG_INFO, "Install FlashFvSecurity - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvSecurityBase), PcdGet32 (PcdFlashFvSecuritySize)));
+  PeiServicesInstallFvInfo2Ppi (
+    &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvSecurityBase))->FileSystemGuid),
+    (VOID *) (UINTN) PcdGet32 (PcdFlashFvSecurityBase),
+    PcdGet32 (PcdFlashFvSecuritySize),
+    NULL,
+    NULL,
+    0
+    );
+  DEBUG ((DEBUG_INFO, "Install FlashFvAdvanced - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvAdvancedBase), PcdGet32 (PcdFlashFvAdvancedSize)));
+  PeiServicesInstallFvInfo2Ppi (
+    &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvAdvancedBase))->FileSystemGuid),
+    (VOID *) (UINTN) PcdGet32 (PcdFlashFvAdvancedBase),
+    PcdGet32 (PcdFlashFvAdvancedSize),
+    NULL,
+    NULL,
+    0
+    );
+}
+
+VOID
+ReportPostMemFv (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_BOOT_MODE                 BootMode;
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  ///
+  /// Build HOB for DXE
+  ///
+  if (BootMode == BOOT_IN_RECOVERY_MODE) {
+    ///
+    /// Prepare the recovery service
+    ///
+  } else {
+    DEBUG ((DEBUG_INFO, "Install FlashFvPostMemory - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvPostMemoryBase), PcdGet32 (PcdFlashFvPostMemorySize)));
+    PeiServicesInstallFvInfo2Ppi (
+      &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvPostMemoryBase))->FileSystemGuid),
+      (VOID *) (UINTN) PcdGet32 (PcdFlashFvPostMemoryBase),
+      PcdGet32 (PcdFlashFvPostMemorySize),
+      NULL,
+      NULL,
+      0
+      );
+    DEBUG ((DEBUG_INFO, "Install FlashFvUefiBoot - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvUefiBootBase), PcdGet32 (PcdFlashFvUefiBootSize)));
+    PeiServicesInstallFvInfo2Ppi (
+      &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvUefiBootBase))->FileSystemGuid),
+      (VOID *) (UINTN) PcdGet32 (PcdFlashFvUefiBootBase),
+      PcdGet32 (PcdFlashFvUefiBootSize),
+      NULL,
+      NULL,
+      0
+      );
+    DEBUG ((DEBUG_INFO, "Install FlashFvOsBoot - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvOsBootBase), PcdGet32 (PcdFlashFvOsBootSize)));
+    PeiServicesInstallFvInfo2Ppi (
+      &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvOsBootBase))->FileSystemGuid),
+      (VOID *) (UINTN) PcdGet32 (PcdFlashFvOsBootBase),
+      PcdGet32 (PcdFlashFvOsBootSize),
+      NULL,
+      NULL,
+      0
+      );
+  }
+
+  //
+  // Report resource HOB for flash FV
+  //
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_MEMORY_MAPPED_IO,
+    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |
+    EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+    EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+    (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
+    (UINTN) PcdGet32 (PcdFlashAreaSize)
+    );
+  BuildMemoryAllocationHob (
+    (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
+    (UINTN) PcdGet32 (PcdFlashAreaSize),
+    EfiMemoryMappedIO
+    );
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
new file mode 100644
index 0000000000..117c72b35f
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1553 @@
+/** @file
+  Platform BDS customizations.
+
+  Copyright (c) 2004 - 2019 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.
+
+@param[in]  Mask       low byte for master PIC mask register,
+high byte for slave PIC mask register.
+@param[in]  EdgeLevel  low byte for master PIC edge/level triggered register,
+high byte for slave PIC edge/level triggered register.
+
+**/
+VOID
+Interrupt8259WriteMask(
+  IN UINT16  Mask,
+  IN UINT16  EdgeLevel
+)
+{
+  IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
+  IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
+  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8)EdgeLevel);
+  IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8)(EdgeLevel >> 8));
+}
+
+VOID
+PciAcpiInitialization (
+  )
+{
+  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
+  //
+  EnableBootLogo(PcdGetPtr(PcdLogoFile));
+
+  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/Library/PlatformBootManagerLib/PlatformData.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100644
index 0000000000..768843a8bf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/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 - 2019 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/Library/SerializeVariablesLib/SerializeVariablesLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
new file mode 100644
index 0000000000..be619c838a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
@@ -0,0 +1,869 @@
+/** @file
+  Serialize Variables Library implementation
+
+  Copyright (c) 2004 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SerializeVariablesLib.h"
+
+/**
+  Serialization format:
+
+  The SerializeVariablesLib interface does not specify a format
+  for the serialization of the variable data.  This library uses
+  a packed array of a non-uniformly sized data structure elements.
+
+  Each variable is stored (packed) as:
+    UINT32   VendorNameSize;  // Name size in bytes
+    CHAR16   VendorName[?];   // The variable unicode name including the
+                              // null terminating character.
+    EFI_GUID VendorGuid;      // The variable GUID
+    UINT32   DataSize;        // The size of variable data in bytes
+    UINT8    Data[?];         // The variable data
+
+**/
+
+
+/**
+  Unpacks the next variable from the buffer
+
+  @param[in]  Buffer - Buffer pointing to the next variable instance
+                On subsequent calls, the pointer should be incremented
+                by the returned SizeUsed value.
+  @param[in]  MaxSize - Max allowable size for the variable data
+                On subsequent calls, this should be decremented
+                by the returned SizeUsed value.
+  @param[out] Name - Variable name string (address in Buffer)
+  @param[out] NameSize - Size of Name in bytes
+  @param[out] Guid - GUID of variable (address in Buffer)
+  @param[out] Attributes - Attributes of variable
+  @param[out] Data - Buffer containing Data for variable (address in Buffer)
+  @param[out] DataSize - Size of Data in bytes
+  @param[out] SizeUsed - Total size used for this variable instance in Buffer
+
+  @return     EFI_STATUS based on the success or failure of the operation
+
+**/
+STATIC
+EFI_STATUS
+UnpackVariableFromBuffer (
+  IN  VOID     *Buffer,
+  IN  UINTN    MaxSize,
+  OUT CHAR16   **Name,
+  OUT UINT32   *NameSize,
+  OUT EFI_GUID **Guid,
+  OUT UINT32   *Attributes,
+  OUT UINT32   *DataSize,
+  OUT VOID     **Data,
+  OUT UINTN    *SizeUsed
+  )
+{
+  UINT8  *BytePtr;
+  UINTN  Offset;
+
+  BytePtr = (UINT8*)Buffer;
+  Offset = 0;
+
+  *NameSize = *(UINT32*) (BytePtr + Offset);
+  Offset = Offset + sizeof (UINT32);
+
+  if (Offset > MaxSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Name = (CHAR16*) (BytePtr + Offset);
+  Offset = Offset + *(UINT32*)BytePtr;
+  if (Offset > MaxSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Guid = (EFI_GUID*) (BytePtr + Offset);
+  Offset = Offset + sizeof (EFI_GUID);
+  if (Offset > MaxSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Attributes = *(UINT32*) (BytePtr + Offset);
+  Offset = Offset + sizeof (UINT32);
+  if (Offset > MaxSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *DataSize = *(UINT32*) (BytePtr + Offset);
+  Offset = Offset + sizeof (UINT32);
+  if (Offset > MaxSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Data = (VOID*) (BytePtr + Offset);
+  Offset = Offset + *DataSize;
+  if (Offset > MaxSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *SizeUsed = Offset;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Iterates through the variables in the buffer, and calls a callback
+  function for each variable found.
+
+  @param[in]  CallbackFunction - Function called for each variable instance
+  @param[in]  Context - Passed to each call of CallbackFunction
+  @param[in]  Buffer - Buffer containing serialized variables
+  @param[in]  MaxSize - Size of Buffer in bytes
+
+  @return     EFI_STATUS based on the success or failure of the operation
+
+**/
+STATIC
+EFI_STATUS
+IterateVariablesInBuffer (
+  IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK  CallbackFunction,
+  IN VOID                                       *CallbackContext,
+  IN VOID                                       *Buffer,
+  IN UINTN                                      MaxSize
+  )
+{
+  RETURN_STATUS Status;
+  UINTN         TotalSizeUsed;
+  UINTN         SizeUsed;
+
+  CHAR16        *Name;
+  UINT32        NameSize;
+  CHAR16        *AlignedName;
+  UINT32        AlignedNameMaxSize;
+  EFI_GUID      *Guid;
+  UINT32        Attributes;
+  UINT32        DataSize;
+  VOID          *Data;
+
+  SizeUsed = 0;
+  AlignedName = NULL;
+  AlignedNameMaxSize = 0;
+  Name = NULL;
+  Guid = NULL;
+  Attributes = 0;
+  DataSize = 0;
+  Data = NULL;
+
+  for (
+    Status = EFI_SUCCESS, TotalSizeUsed = 0;
+    !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize);
+    ) {
+    Status = UnpackVariableFromBuffer (
+               (VOID*) ((UINT8*) Buffer + TotalSizeUsed),
+               (MaxSize - TotalSizeUsed),
+               &Name,
+               &NameSize,
+               &Guid,
+               &Attributes,
+               &DataSize,
+               &Data,
+               &SizeUsed
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // We copy the name to a separately allocated buffer,
+    // to be sure it is 16-bit aligned.
+    //
+    if (NameSize > AlignedNameMaxSize) {
+      if (AlignedName != NULL) {
+        FreePool (AlignedName);
+      }
+      AlignedName = AllocatePool (NameSize);
+    }
+    if (AlignedName == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    CopyMem (AlignedName, Name, NameSize);
+
+    TotalSizeUsed = TotalSizeUsed + SizeUsed;
+
+    //
+    // Run the callback function
+    //
+    Status = (*CallbackFunction) (
+               CallbackContext,
+               AlignedName,
+               Guid,
+               Attributes,
+               DataSize,
+               Data
+               );
+
+  }
+
+  if (AlignedName != NULL) {
+    FreePool (AlignedName);
+  }
+
+  //
+  // Make sure the entire buffer was used, or else return an error
+  //
+  if (TotalSizeUsed != MaxSize) {
+    DEBUG ((
+      EFI_D_ERROR,
+      "Deserialize variables error: TotalSizeUsed(%Lu) != MaxSize(%Lu)\n",
+      (UINT64)TotalSizeUsed,
+      (UINT64)MaxSize
+      ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackNop (
+  IN  VOID                         *Context,
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid,
+  IN  UINT32                       Attributes,
+  IN  UINTN                        DataSize,
+  IN  VOID                         *Data
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackSetInInstance (
+  IN  VOID                         *Context,
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid,
+  IN  UINT32                       Attributes,
+  IN  UINTN                        DataSize,
+  IN  VOID                         *Data
+  )
+{
+  EFI_HANDLE  Instance;
+
+  Instance = (EFI_HANDLE) Context;
+
+  return SerializeVariablesAddVariable (
+           Instance,
+           VariableName,
+           VendorGuid,
+           Attributes,
+           DataSize,
+           Data
+           );
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackSetSystemVariable (
+  IN  VOID                         *Context,
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid,
+  IN  UINT32                       Attributes,
+  IN  UINTN                        DataSize,
+  IN  VOID                         *Data
+  )
+{
+  EFI_STATUS          Status;
+  STATIC CONST UINT32 AuthMask =
+                        EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
+                        EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+  Status = gRT->SetVariable (
+             VariableName,
+             VendorGuid,
+             Attributes,
+             DataSize,
+             Data
+             );
+
+  if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) {
+    DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" "
+            "failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__,
+            VariableName));
+    Status = EFI_SUCCESS;
+  } else if (Status == EFI_WRITE_PROTECTED) {
+    DEBUG ((DEBUG_WARN, "%a: setting ReadOnly variable \"%s\" "
+            "failed with EFI_WRITE_PROTECTED, ignoring\n", __FUNCTION__,
+            VariableName));
+    Status = EFI_SUCCESS;
+  }
+  return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EnsureExtraBufferSpace (
+  IN  SV_INSTANCE  *Instance,
+  IN  UINTN        Size
+  )
+{
+  VOID *NewBuffer;
+  UINTN NewSize;
+
+  NewSize = Instance->DataSize + Size;
+  if (NewSize <= Instance->BufferSize) {
+    return RETURN_SUCCESS;
+  }
+
+  //
+  // Double the required size to lessen the need to re-allocate in the future
+  //
+  NewSize = 2 * NewSize;
+
+  NewBuffer = AllocatePool (NewSize);
+  if (NewBuffer == NULL) {
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  if (Instance->BufferPtr != NULL) {
+    CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize);
+    FreePool (Instance->BufferPtr);
+  }
+
+  Instance->BufferPtr = NewBuffer;
+  Instance->BufferSize = NewSize;
+
+  return RETURN_SUCCESS;
+}
+
+
+STATIC
+VOID
+AppendToBuffer (
+  IN  SV_INSTANCE  *Instance,
+  IN  VOID         *Data,
+  IN  UINTN        Size
+  )
+{
+  UINTN NewSize;
+
+  ASSERT (Instance != NULL);
+  ASSERT (Data != NULL);
+
+  NewSize = Instance->DataSize + Size;
+  ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
+
+  CopyMem (
+    (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize),
+    Data,
+    Size
+    );
+
+  Instance->DataSize = NewSize;
+}
+
+
+/**
+  Creates a new variable serialization instance
+
+  @param[out]  Handle - Handle for a variable serialization instance
+
+  @retval      RETURN_SUCCESS - The variable serialization instance was
+                 successfully created.
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 create the variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstance (
+  OUT EFI_HANDLE                      *Handle
+  )
+{
+  SV_INSTANCE  *New;
+
+  New = AllocateZeroPool (sizeof (*New));
+  if (New == NULL) {
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  New->Signature = SV_SIGNATURE;
+
+  *Handle = (EFI_HANDLE) New;
+  return RETURN_SUCCESS;
+}
+
+
+/**
+  Free memory associated with a variable serialization instance
+
+  @param[in]  Handle - Handle for a variable serialization instance
+
+  @retval      RETURN_SUCCESS - The variable serialization instance was
+                 successfully freed.
+  @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
+                 variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesFreeInstance (
+  IN EFI_HANDLE Handle
+  )
+{
+  SV_INSTANCE    *Instance;
+
+  Instance = SV_FROM_HANDLE (Handle);
+
+  if (Instance->Signature != SV_SIGNATURE) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  Instance->Signature = 0;
+
+  if (Instance->BufferPtr != NULL) {
+    FreePool (Instance->BufferPtr);
+  }
+
+  FreePool (Instance);
+
+  return RETURN_SUCCESS;
+}
+
+
+/**
+  Creates a new variable serialization instance using the given
+  binary representation of the variables to fill the new instance
+
+  @param[out] Handle - Handle for a variable serialization instance
+  @param[in]  Buffer - A buffer with the serialized representation
+                of the variables.  Must be the same format as produced
+                by SerializeVariablesToBuffer.
+  @param[in]  Size - This is the size of the binary representation
+                of the variables.
+
+  @retval      RETURN_SUCCESS - The binary representation was successfully
+                 imported into a new variable serialization instance
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 create the new variable serialization instance
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstanceFromBuffer (
+  OUT EFI_HANDLE                          *Handle,
+  IN  VOID                                *Buffer,
+  IN  UINTN                               Size
+  )
+{
+  RETURN_STATUS Status;
+
+  Status = SerializeVariablesNewInstance (Handle);
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = IterateVariablesInBuffer (
+             IterateVariablesCallbackNop,
+             NULL,
+             Buffer,
+             Size
+             );
+  if (RETURN_ERROR (Status)) {
+    SerializeVariablesFreeInstance (*Handle);
+    return Status;
+  }
+
+  Status = IterateVariablesInBuffer (
+             IterateVariablesCallbackSetInInstance,
+             (VOID*) *Handle,
+             Buffer,
+             Size
+             );
+  if (RETURN_ERROR (Status)) {
+    SerializeVariablesFreeInstance (*Handle);
+    return Status;
+  }
+
+  return Status;
+}
+
+
+/**
+  Iterates all variables found with RuntimeServices GetNextVariableName
+
+  @param[in]   CallbackFunction - Function called for each variable instance
+  @param[in]   Context - Passed to each call of CallbackFunction
+
+  @retval      RETURN_SUCCESS - All variables were iterated without the
+                 CallbackFunction returning an error
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 iterate through the variables
+  @return      Any of RETURN_ERROR indicates an error reading the variable
+                 or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateSystemVariables (
+  IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+  IN VOID                                      *Context
+  )
+{
+  RETURN_STATUS               Status;
+  UINTN                       VariableNameBufferSize;
+  UINTN                       VariableNameSize;
+  CHAR16                      *VariableName;
+  EFI_GUID                    VendorGuid;
+  UINTN                       VariableDataBufferSize;
+  UINTN                       VariableDataSize;
+  VOID                        *VariableData;
+  UINT32                      VariableAttributes;
+  VOID                        *NewBuffer;
+
+  //
+  // Initialize the variable name and data buffer variables.
+  //
+  VariableNameBufferSize = sizeof (CHAR16);
+  VariableName = AllocateZeroPool (VariableNameBufferSize);
+
+  VariableDataBufferSize = 0;
+  VariableData = NULL;
+
+  for (;;) {
+    //
+    // Get the next variable name and guid
+    //
+    VariableNameSize = VariableNameBufferSize;
+    Status = gRT->GetNextVariableName (
+                    &VariableNameSize,
+                    VariableName,
+                    &VendorGuid
+                    );
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      //
+      // The currently allocated VariableName buffer is too small,
+      // so we allocate a larger buffer, and copy the old buffer
+      // to it.
+      //
+      NewBuffer = AllocatePool (VariableNameSize);
+      if (NewBuffer == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        break;
+      }
+      CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
+      if (VariableName != NULL) {
+        FreePool (VariableName);
+      }
+      VariableName = NewBuffer;
+      VariableNameBufferSize = VariableNameSize;
+
+      //
+      // Try to get the next variable name again with the larger buffer.
+      //
+      Status = gRT->GetNextVariableName (
+                      &VariableNameSize,
+                      VariableName,
+                      &VendorGuid
+                      );
+    }
+
+    if (EFI_ERROR (Status)) {
+      if (Status == EFI_NOT_FOUND) {
+        Status = EFI_SUCCESS;
+      }
+      break;
+    }
+
+    //
+    // Get the variable data and attributes
+    //
+    VariableDataSize = VariableDataBufferSize;
+    Status = gRT->GetVariable (
+                    VariableName,
+                    &VendorGuid,
+                    &VariableAttributes,
+                    &VariableDataSize,
+                    VariableData
+                    );
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      //
+      // The currently allocated VariableData buffer is too small,
+      // so we allocate a larger buffer.
+      //
+      if (VariableDataBufferSize != 0) {
+        FreePool (VariableData);
+        VariableData = NULL;
+        VariableDataBufferSize = 0;
+      }
+      VariableData = AllocatePool (VariableDataSize);
+      if (VariableData == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        break;
+      }
+      VariableDataBufferSize = VariableDataSize;
+
+      //
+      // Try to read the variable again with the larger buffer.
+      //
+      Status = gRT->GetVariable (
+                      VariableName,
+                      &VendorGuid,
+                      &VariableAttributes,
+                      &VariableDataSize,
+                      VariableData
+                      );
+    }
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    //
+    // Run the callback function
+    //
+    Status = (*CallbackFunction) (
+               Context,
+               VariableName,
+               &VendorGuid,
+               VariableAttributes,
+               VariableDataSize,
+               VariableData
+               );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+  }
+
+  if (VariableName != NULL) {
+    FreePool (VariableName);
+  }
+
+  if (VariableData != NULL) {
+    FreePool (VariableData);
+  }
+
+  return Status;
+}
+
+
+/**
+  Iterates all variables found in the variable serialization instance
+
+  @param[in]   Handle - Handle for a variable serialization instance
+  @param[in]   CallbackFunction - Function called for each variable instance
+  @param[in]   Context - Passed to each call of CallbackFunction
+
+  @retval      RETURN_SUCCESS - All variables were iterated without the
+                 CallbackFunction returning an error
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 iterate through the variables
+  @return      Any of RETURN_ERROR indicates an error reading the variable
+                 or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateInstanceVariables (
+  IN EFI_HANDLE                                Handle,
+  IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+  IN VOID                                      *Context
+  )
+{
+  SV_INSTANCE    *Instance;
+
+  Instance = SV_FROM_HANDLE (Handle);
+
+  if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
+    return IterateVariablesInBuffer (
+             CallbackFunction,
+             Context,
+             Instance->BufferPtr,
+             Instance->DataSize
+             );
+  } else {
+    return RETURN_SUCCESS;
+  }
+}
+
+
+/**
+  Sets all variables found in the variable serialization instance
+
+  @param[in]   Handle - Handle for a variable serialization instance
+
+  @retval      RETURN_SUCCESS - All variables were set successfully
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 set all the variables
+  @return      Any of RETURN_ERROR indicates an error reading the variables
+                 or in attempting to set a variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesSetSerializedVariables (
+  IN EFI_HANDLE                       Handle
+  )
+{
+  return SerializeVariablesIterateInstanceVariables (
+           Handle,
+           IterateVariablesCallbackSetSystemVariable,
+           NULL
+           );
+}
+
+
+/**
+  Adds a variable to the variable serialization instance
+
+  @param[in] Handle - Handle for a variable serialization instance
+  @param[in] VariableName - Refer to RuntimeServices GetVariable
+  @param[in] VendorGuid - Refer to RuntimeServices GetVariable
+  @param[in] Attributes - Refer to RuntimeServices GetVariable
+  @param[in] DataSize - Refer to RuntimeServices GetVariable
+  @param[in] Data - Refer to RuntimeServices GetVariable
+
+  @retval      RETURN_SUCCESS - All variables were set successfully
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 add the variable
+  @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
+                 variable serialization instance or
+                 VariableName, VariableGuid or Data are NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesAddVariable (
+  IN EFI_HANDLE                   Handle,
+  IN CHAR16                       *VariableName,
+  IN EFI_GUID                     *VendorGuid,
+  IN UINT32                       Attributes,
+  IN UINTN                        DataSize,
+  IN VOID                         *Data
+  )
+{
+  RETURN_STATUS  Status;
+  SV_INSTANCE    *Instance;
+  UINT32         SerializedNameSize;
+  UINT32         SerializedDataSize;
+  UINTN          SerializedSize;
+
+  Instance = SV_FROM_HANDLE (Handle);
+
+  if ((Instance->Signature != SV_SIGNATURE) ||
+      (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
+  }
+
+  SerializedNameSize = (UINT32) StrSize (VariableName);
+
+  SerializedSize =
+    sizeof (SerializedNameSize) +
+    SerializedNameSize +
+    sizeof (*VendorGuid) +
+    sizeof (Attributes) +
+    sizeof (SerializedDataSize) +
+    DataSize;
+
+  Status = EnsureExtraBufferSpace (
+             Instance,
+             SerializedSize
+             );
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Add name size (UINT32)
+  //
+  AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize));
+
+  //
+  // Add variable unicode name string
+  //
+  AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize);
+
+  //
+  // Add variable GUID
+  //
+  AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid));
+
+  //
+  // Add variable attributes
+  //
+  AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes));
+
+  //
+  // Add variable data size (UINT32)
+  //
+  SerializedDataSize = (UINT32) DataSize;
+  AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize));
+
+  //
+  // Add variable data
+  //
+  AppendToBuffer (Instance, Data, DataSize);
+
+  return RETURN_SUCCESS;
+}
+
+
+/**
+  Serializes the variables known to this instance into the
+  provided buffer.
+
+  @param[in]     Handle - Handle for a variable serialization instance
+  @param[out]    Buffer - A buffer to store the binary representation
+                   of the variables.
+  @param[in,out] Size - On input this is the size of the buffer.
+                   On output this is the size of the binary representation
+                   of the variables.
+
+  @retval      RETURN_SUCCESS - The binary representation was successfully
+                 completed and returned in the buffer.
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 save the variables to the buffer.
+  @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
+                 variable serialization instance or
+                 Size or Buffer were NULL.
+  @retval      RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by
+                 the Size parameter was too small for the serialized
+                 variable data.  Size is returned with the required size.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesToBuffer (
+  IN     EFI_HANDLE                       Handle,
+  OUT    VOID                             *Buffer,
+  IN OUT UINTN                            *Size
+  )
+{
+  SV_INSTANCE    *Instance;
+
+  Instance = SV_FROM_HANDLE (Handle);
+
+  if (Size == NULL) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  if (*Size < Instance->DataSize) {
+    *Size = Instance->DataSize;
+    return RETURN_BUFFER_TOO_SMALL;
+  }
+
+  if (Buffer == NULL) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  *Size = Instance->DataSize;
+  CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
+
+  return RETURN_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
new file mode 100644
index 0000000000..383501898d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
@@ -0,0 +1,108 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+  Performs silicon pre-mem policy initialization.
+
+  The meaning of Policy is defined by silicon code.
+  It could be the raw data, a handle, a PPI, etc.
+
+  The returned data must be used as input data for SiliconPolicyDonePreMem(),
+  and SiliconPolicyUpdateLib.SiliconPolicyUpdatePreMem().
+
+  1) In FSP path, the input Policy should be FspmUpd.
+  Value of FspmUpd has been initialized by FSP binary default value.
+  Only a subset of FspmUpd needs to be updated for different silicon sku.
+  The return data is same FspmUpd.
+
+  2) In non-FSP path, the input policy could be NULL.
+  The return data is the initialized policy.
+
+  @param[in, out] Policy       Pointer to policy.
+
+  @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPreMem (
+  IN OUT VOID *Policy OPTIONAL
+  )
+{
+  return Policy;
+}
+
+/*
+  The silicon pre-mem policy is finalized.
+  Silicon code can do initialization based upon the policy data.
+
+  The input Policy must be returned by SiliconPolicyInitPreMem().
+
+  @param[in] Policy       Pointer to policy.
+
+  @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+*/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePreMem (
+  IN VOID *Policy
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/**
+  Performs silicon post-mem policy initialization.
+
+  The meaning of Policy is defined by silicon code.
+  It could be the raw data, a handle, a PPI, etc.
+
+  The returned data must be used as input data for SiliconPolicyDonePostMem(),
+  and SiliconPolicyUpdateLib.SiliconPolicyUpdatePostMem().
+
+  1) In FSP path, the input Policy should be FspsUpd.
+  Value of FspsUpd has been initialized by FSP binary default value.
+  Only a subset of FspsUpd needs to be updated for different silicon sku.
+  The return data is same FspsUpd.
+
+  2) In non-FSP path, the input policy could be NULL.
+  The return data is the initialized policy.
+
+  @param[in, out] Policy       Pointer to policy.
+
+  @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPostMem (
+  IN OUT VOID *Policy OPTIONAL
+  )
+{
+  return Policy;
+}
+
+/*
+  The silicon post-mem policy is finalized.
+  Silicon code can do initialization based upon the policy data.
+
+  The input Policy must be returned by SiliconPolicyInitPostMem().
+
+  @param[in] Policy       Pointer to policy.
+
+  @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+*/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePostMem (
+  IN VOID *Policy
+  )
+{
+  return RETURN_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
new file mode 100644
index 0000000000..3b207a4e78
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
@@ -0,0 +1,70 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/PeiServicesLib.h>
+
+/**
+  Performs silicon pre-mem policy update.
+
+  The meaning of Policy is defined by silicon code.
+  It could be the raw data, a handle, a PPI, etc.
+
+  The input Policy must be returned by SiliconPolicyDonePreMem().
+
+  1) In FSP path, the input Policy should be FspmUpd.
+  A platform may use this API to update the FSPM UPD policy initialized
+  by the silicon module or the default UPD data.
+  The output of FSPM UPD data from this API is the final UPD data.
+
+  2) In non-FSP path, the board may use additional way to get
+  the silicon policy data field based upon the input Policy.
+
+  @param[in, out] Policy       Pointer to policy.
+
+  @return the updated policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyUpdatePreMem (
+  IN OUT VOID *Policy
+  )
+{
+  return Policy;
+}
+
+/**
+  Performs silicon post-mem policy update.
+
+  The meaning of Policy is defined by silicon code.
+  It could be the raw data, a handle, a PPI, etc.
+
+  The input Policy must be returned by SiliconPolicyDonePostMem().
+
+  1) In FSP path, the input Policy should be FspsUpd.
+  A platform may use this API to update the FSPS UPD policy initialized
+  by the silicon module or the default UPD data.
+  The output of FSPS UPD data from this API is the final UPD data.
+
+  2) In non-FSP path, the board may use additional way to get
+  the silicon policy data field based upon the input Policy.
+
+  @param[in, out] Policy       Pointer to policy.
+
+  @return the updated policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyUpdatePostMem (
+  IN OUT VOID *Policy
+  )
+{
+  return Policy;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
new file mode 100644
index 0000000000..5cbb47687b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
@@ -0,0 +1,956 @@
+/** @file
+  Main SEC phase code.  Transitions to PEI.
+
+  Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiCpuLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/ExtractGuidedSectionLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/PciCf8Lib.h>
+
+#include <Ppi/TemporaryRamSupport.h>
+#include <Register/X58Ich10.h>
+
+#define SEC_IDT_ENTRY_COUNT  34
+
+typedef struct _SEC_IDT_TABLE {
+  EFI_PEI_SERVICES          *PeiService;
+  IA32_IDT_GATE_DESCRIPTOR  IdtTable[SEC_IDT_ENTRY_COUNT];
+} SEC_IDT_TABLE;
+
+VOID
+EFIAPI
+SecStartupPhase2 (
+  IN VOID                     *Context
+  );
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+  IN CONST EFI_PEI_SERVICES   **PeiServices,
+  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
+  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
+  IN UINTN                    CopySize
+  );
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
+  TemporaryRamMigration
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gEfiTemporaryRamSupportPpiGuid,
+    &mTemporaryRamSupportPpi
+  },
+};
+
+//
+// Template of an IDT entry pointing to 10:FFFFFFE4h.
+//
+IA32_IDT_GATE_DESCRIPTOR  mIdtEntryTemplate = {
+  {                                      // Bits
+    0xffe4,                              // OffsetLow
+    0x10,                                // Selector
+    0x0,                                 // Reserved_0
+    IA32_IDT_GATE_TYPE_INTERRUPT_32,     // GateType
+    0xffff                               // OffsetHigh
+  }
+};
+
+/**
+  Locates the main boot firmware volume.
+
+  @param[in,out]  BootFv  On input, the base of the BootFv
+                          On output, the decompressed main firmware volume
+
+  @retval EFI_SUCCESS    The main firmware volume was located and decompressed
+  @retval EFI_NOT_FOUND  The main firmware volume was not found
+
+**/
+EFI_STATUS
+FindMainFv (
+  IN OUT  EFI_FIRMWARE_VOLUME_HEADER   **BootFv
+  )
+{
+  EFI_FIRMWARE_VOLUME_HEADER  *Fv;
+  UINTN                       Distance;
+
+  ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);
+
+  Fv = *BootFv;
+  Distance = (UINTN) (*BootFv)->FvLength;
+  do {
+    Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);
+    Distance += EFI_PAGE_SIZE;
+    if (Distance > SIZE_32MB) {
+      return EFI_NOT_FOUND;
+    }
+
+    if (Fv->Signature != EFI_FVH_SIGNATURE) {
+      continue;
+    }
+
+    if ((UINTN) Fv->FvLength > Distance) {
+      continue;
+    }
+
+    *BootFv = Fv;
+    return EFI_SUCCESS;
+
+  } while (TRUE);
+}
+
+/**
+  Locates a section within a series of sections
+  with the specified section type.
+
+  The Instance parameter indicates which instance of the section
+  type to return. (0 is first instance, 1 is second...)
+
+  @param[in]   Sections        The sections to search
+  @param[in]   SizeOfSections  Total size of all sections
+  @param[in]   SectionType     The section type to locate
+  @param[in]   Instance        The section instance number
+  @param[out]  FoundSection    The FFS section if found
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInstance (
+  IN  VOID                             *Sections,
+  IN  UINTN                            SizeOfSections,
+  IN  EFI_SECTION_TYPE                 SectionType,
+  IN  UINTN                            Instance,
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection
+  )
+{
+  EFI_PHYSICAL_ADDRESS        CurrentAddress;
+  UINT32                      Size;
+  EFI_PHYSICAL_ADDRESS        EndOfSections;
+  EFI_COMMON_SECTION_HEADER   *Section;
+  EFI_PHYSICAL_ADDRESS        EndOfSection;
+
+  //
+  // Loop through the FFS file sections within the PEI Core FFS file
+  //
+  EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;
+  EndOfSections = EndOfSection + SizeOfSections;
+  for (;;) {
+    if (EndOfSection == EndOfSections) {
+      break;
+    }
+    CurrentAddress = (EndOfSection + 3) & ~(3ULL);
+    if (CurrentAddress >= EndOfSections) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
+    DEBUG ((EFI_D_VERBOSE, "Section->Type: 0x%x\n", Section->Type));
+
+    Size = SECTION_SIZE (Section);
+    if (Size < sizeof (*Section)) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    EndOfSection = CurrentAddress + Size;
+    if (EndOfSection > EndOfSections) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    //
+    // Look for the requested section type
+    //
+    if (Section->Type == SectionType) {
+      if (Instance == 0) {
+        *FoundSection = Section;
+        return EFI_SUCCESS;
+      } else {
+        Instance--;
+      }
+    }
+    DEBUG ((EFI_D_VERBOSE, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Locates a section within a series of sections
+  with the specified section type.
+
+  @param[in]   Sections        The sections to search
+  @param[in]   SizeOfSections  Total size of all sections
+  @param[in]   SectionType     The section type to locate
+  @param[out]  FoundSection    The FFS section if found
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInSections (
+  IN  VOID                             *Sections,
+  IN  UINTN                            SizeOfSections,
+  IN  EFI_SECTION_TYPE                 SectionType,
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection
+  )
+{
+  return FindFfsSectionInstance (
+           Sections,
+           SizeOfSections,
+           SectionType,
+           0,
+           FoundSection
+           );
+}
+
+/**
+  Locates a FFS file with the specified file type and a section
+  within that file with the specified section type.
+
+  @param[in]   Fv            The firmware volume to search
+  @param[in]   FileType      The file type to locate
+  @param[in]   SectionType   The section type to locate
+  @param[out]  FoundSection  The FFS section if found
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsFileAndSection (
+  IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,
+  IN  EFI_FV_FILETYPE                  FileType,
+  IN  EFI_SECTION_TYPE                 SectionType,
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PHYSICAL_ADDRESS        CurrentAddress;
+  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;
+  EFI_FFS_FILE_HEADER         *File;
+  UINT32                      Size;
+  EFI_PHYSICAL_ADDRESS        EndOfFile;
+
+  if (Fv->Signature != EFI_FVH_SIGNATURE) {
+    DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;
+  EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
+
+  //
+  // Loop through the FFS files in the Boot Firmware Volume
+  //
+  for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
+
+    CurrentAddress = (EndOfFile + 7) & ~(7ULL);
+    if (CurrentAddress > EndOfFirmwareVolume) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
+    Size = *(UINT32*) File->Size & 0xffffff;
+    if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+    DEBUG ((EFI_D_VERBOSE, "File->Type: 0x%x\n", File->Type));
+
+    EndOfFile = CurrentAddress + Size;
+    if (EndOfFile > EndOfFirmwareVolume) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    //
+    // Look for the request file type
+    //
+    if (File->Type != FileType) {
+      DEBUG ((EFI_D_VERBOSE, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));
+      continue;
+    }
+
+    Status = FindFfsSectionInSections (
+               (VOID*) (File + 1),
+               (UINTN) EndOfFile - (UINTN) (File + 1),
+               SectionType,
+               FoundSection
+               );
+    if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
+      return Status;
+    }
+  }
+}
+
+/**
+  Locates the compressed main firmware volume and decompresses it.
+
+  @param[in,out]  Fv            On input, the firmware volume to search
+                                On output, the decompressed BOOT/PEI FV
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+
+**/
+EFI_STATUS
+DecompressMemFvs (
+  IN OUT EFI_FIRMWARE_VOLUME_HEADER       **Fv
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_GUID_DEFINED_SECTION          *Section;
+  UINT32                            OutputBufferSize;
+  UINT32                            ScratchBufferSize;
+  UINT16                            SectionAttribute;
+  UINT32                            AuthenticationStatus;
+  VOID                              *OutputBuffer;
+  VOID                              *ScratchBuffer;
+  EFI_COMMON_SECTION_HEADER         *FvSection;
+  EFI_FIRMWARE_VOLUME_HEADER        *PeiMemFv;
+  EFI_FIRMWARE_VOLUME_HEADER        *DxeMemFv;
+  UINT32                            FvHeaderSize;
+  UINT32                            FvSectionSize;
+
+  FvSection = (EFI_COMMON_SECTION_HEADER*) NULL;
+
+  DEBUG ((EFI_D_VERBOSE, "Find and decompress FV image.\n"));
+  Status = FindFfsFileAndSection (
+             *Fv,
+             EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
+             EFI_SECTION_GUID_DEFINED,
+             (EFI_COMMON_SECTION_HEADER**) &Section
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));
+    return Status;
+  }
+
+  Status = ExtractGuidedSectionGetInfo (
+             Section,
+             &OutputBufferSize,
+             &ScratchBufferSize,
+             &SectionAttribute
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));
+    return Status;
+  }
+
+  OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBase) + SIZE_1MB);
+  ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
+
+  DEBUG ((EFI_D_VERBOSE, "PcdSimicsDxeMemFvBase: 0x%x\n", PcdGet32 (PcdSimicsDxeMemFvBase)));
+  DEBUG ((EFI_D_VERBOSE, "OutputBuffer: 0x%x\n", OutputBuffer));
+  DEBUG ((EFI_D_VERBOSE, "OutputBufferSize: 0x%x\n", OutputBufferSize));
+  DEBUG ((EFI_D_VERBOSE, "ScratchBuffer: 0x%x\n", ScratchBuffer));
+  DEBUG ((EFI_D_VERBOSE, "ScratchBufferSize: 0x%x\n", ScratchBufferSize));
+  DEBUG ((EFI_D_VERBOSE, "PcdSimicsDecompressionScratchEnd: 0x%x\n", PcdGet32 (PcdSimicsDecompressionScratchEnd)));
+
+  DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
+    "PcdSimicsDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer,
+    OutputBufferSize, ScratchBuffer, ScratchBufferSize,
+    PcdGet32 (PcdSimicsDecompressionScratchEnd)));
+  ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize ==
+    PcdGet32 (PcdSimicsDecompressionScratchEnd));
+
+  Status = ExtractGuidedSectionDecode (
+             Section,
+             &OutputBuffer,
+             ScratchBuffer,
+             &AuthenticationStatus
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));
+    return Status;
+  }
+
+  Status = FindFfsSectionInstance (
+             OutputBuffer,
+             OutputBufferSize,
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+             0,
+             &FvSection
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));
+    return Status;
+  }
+
+  ASSERT (SECTION_SIZE (FvSection) ==
+          (PcdGet32 (PcdSimicsPeiMemFvSize) + sizeof (*FvSection)));
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+  PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsPeiMemFvBase);
+  CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdSimicsPeiMemFvSize));
+
+  if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {
+    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));
+    CpuDeadLoop ();
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  Status = FindFfsSectionInstance (
+             OutputBuffer,
+             OutputBufferSize,
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+             1,
+             &FvSection
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));
+    return Status;
+  }
+
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+  if (IS_SECTION2 (FvSection)) {
+    FvSectionSize = SECTION2_SIZE (FvSection);
+    FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+  } else {
+    FvSectionSize = SECTION_SIZE (FvSection);
+    FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
+  }
+
+  ASSERT (FvSectionSize == (PcdGet32 (PcdSimicsDxeMemFvSize) + FvHeaderSize));
+
+  DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBase);
+  CopyMem (DxeMemFv, (VOID*) ((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdSimicsDxeMemFvSize));
+
+  if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {
+    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));
+    CpuDeadLoop ();
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  *Fv = PeiMemFv;
+  return EFI_SUCCESS;
+}
+
+/**
+  Locates the PEI Core entry point address
+
+  @param[in]  Fv                 The firmware volume to search
+  @param[out] PeiCoreEntryPoint  The entry point of the PEI Core image
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindPeiCoreImageBaseInFv (
+  IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,
+  OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_COMMON_SECTION_HEADER   *Section;
+
+  DEBUG ((EFI_D_VERBOSE, "Find PEI Core image.\n"));
+  Status = FindFfsFileAndSection (
+             Fv,
+             EFI_FV_FILETYPE_PEI_CORE,
+             EFI_SECTION_PE32,
+             &Section
+             );
+  if (EFI_ERROR (Status)) {
+    Status = FindFfsFileAndSection (
+               Fv,
+               EFI_FV_FILETYPE_PEI_CORE,
+               EFI_SECTION_TE,
+               &Section
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));
+      return Status;
+    }
+  }
+
+  *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+  DEBUG ((EFI_D_VERBOSE, "PEI core image base 0x%016LX.\n", *PeiCoreImageBase));
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Reads 8-bits of CMOS data.
+
+  Reads the 8-bits of CMOS data at the location specified by Index.
+  The 8-bit read value is returned.
+
+  @param  Index  The CMOS location to read.
+
+  @return The value read.
+
+**/
+STATIC
+UINT8
+CmosRead8 (
+  IN UINTN        Index
+  )
+{
+  IoWrite8 (0x70, (UINT8) Index);
+  return IoRead8 (0x71);
+}
+
+
+STATIC
+BOOLEAN
+IsS3Resume (
+  VOID
+  )
+{
+  DEBUG((EFI_D_VERBOSE, "modeValue = %x\n", IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12)));
+  return (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) == 0x5);
+}
+
+
+STATIC
+EFI_STATUS
+GetS3ResumePeiFv (
+  IN OUT EFI_FIRMWARE_VOLUME_HEADER       **PeiFv
+  )
+{
+  *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsPeiMemFvBase);
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Locates the PEI Core entry point address
+
+  @param[in,out]  Fv                 The firmware volume to search
+  @param[out]     PeiCoreEntryPoint  The entry point of the PEI Core image
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+
+**/
+VOID
+FindPeiCoreImageBase (
+  IN OUT  EFI_FIRMWARE_VOLUME_HEADER       **BootFv,
+     OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase
+  )
+{
+  BOOLEAN S3Resume;
+
+  *PeiCoreImageBase = 0;
+
+  S3Resume = IsS3Resume ();
+  if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {
+    //
+    // A malicious runtime OS may have injected something into our previously
+    // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
+    //
+    DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));
+    GetS3ResumePeiFv (BootFv);
+  } else {
+    //
+    // We're either not resuming, or resuming "securely" -- we'll decompress
+    // both PEI FV and DXE FV from pristine flash.
+    //
+    DEBUG ((EFI_D_VERBOSE, "SEC: %a\n",
+      S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"));
+    FindMainFv (BootFv);
+
+    DecompressMemFvs (BootFv);
+  }
+
+  FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
+}
+
+/**
+  Find core image base.
+
+**/
+EFI_STATUS
+FindImageBase (
+  IN  EFI_FIRMWARE_VOLUME_HEADER       *BootFirmwareVolumePtr,
+  OUT EFI_PHYSICAL_ADDRESS             *SecCoreImageBase
+  )
+{
+  EFI_PHYSICAL_ADDRESS        CurrentAddress;
+  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;
+  EFI_FFS_FILE_HEADER         *File;
+  UINT32                      Size;
+  EFI_PHYSICAL_ADDRESS        EndOfFile;
+  EFI_COMMON_SECTION_HEADER   *Section;
+  EFI_PHYSICAL_ADDRESS        EndOfSection;
+
+  *SecCoreImageBase = 0;
+
+  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
+  EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
+
+  //
+  // Loop through the FFS files in the Boot Firmware Volume
+  //
+  for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
+
+    CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
+    if (CurrentAddress > EndOfFirmwareVolume) {
+      return EFI_NOT_FOUND;
+    }
+
+    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
+    Size = *(UINT32*) File->Size & 0xffffff;
+    if (Size < sizeof (*File)) {
+      return EFI_NOT_FOUND;
+    }
+
+    EndOfFile = CurrentAddress + Size;
+    if (EndOfFile > EndOfFirmwareVolume) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // Look for SEC Core
+    //
+    if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
+      continue;
+    }
+
+    //
+    // Loop through the FFS file sections within the FFS file
+    //
+    EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);
+    for (;;) {
+      CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
+      Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
+
+      Size = *(UINT32*) Section->Size & 0xffffff;
+      if (Size < sizeof (*Section)) {
+        return EFI_NOT_FOUND;
+      }
+
+      EndOfSection = CurrentAddress + Size;
+      if (EndOfSection > EndOfFile) {
+        return EFI_NOT_FOUND;
+      }
+
+      //
+      // Look for executable sections
+      //
+      if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
+        if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
+          *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);
+        }
+        break;
+      }
+    }
+
+    //
+    // SEC Core image found
+    //
+    if (*SecCoreImageBase != 0) {
+      return EFI_SUCCESS;
+    }
+  }
+}
+
+/*
+  Find and return Pei Core entry point.
+
+  It also find SEC and PEI Core file debug information. It will report them if
+  remote debug is enabled.
+
+**/
+VOID
+FindAndReportEntryPoints (
+  IN  EFI_FIRMWARE_VOLUME_HEADER       **BootFirmwareVolumePtr,
+  OUT EFI_PEI_CORE_ENTRY_POINT         *PeiCoreEntryPoint
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_PHYSICAL_ADDRESS             SecCoreImageBase;
+  EFI_PHYSICAL_ADDRESS             PeiCoreImageBase;
+  PE_COFF_LOADER_IMAGE_CONTEXT     ImageContext;
+
+  //
+  // Find SEC Core and PEI Core image base
+   //
+  Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
+  ASSERT_EFI_ERROR (Status);
+
+  FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
+
+  ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+  //
+  // Report SEC Core debug information when remote debug is enabled
+  //
+  ImageContext.ImageAddress = SecCoreImageBase;
+  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+  //
+  // Report PEI Core debug information when remote debug is enabled
+  //
+  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
+  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+  //
+  // Find PEI Core entry point
+  //
+  Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
+  if (EFI_ERROR (Status)) {
+    *PeiCoreEntryPoint = 0;
+  }
+
+  return;
+}
+
+VOID
+EFIAPI
+SecCoreStartupWithStack (
+  IN EFI_FIRMWARE_VOLUME_HEADER       *BootFv,
+  IN VOID                             *TopOfCurrentStack
+  )
+{
+  EFI_SEC_PEI_HAND_OFF        SecCoreData;
+  SEC_IDT_TABLE               IdtTableInStack;
+  IA32_DESCRIPTOR             IdtDescriptor;
+  UINT32                      Index;
+  volatile UINT8              *Table;
+
+  //
+  // Initialize floating point operating environment
+  // to be compliant with UEFI spec.
+  //
+  InitializeFloatingPointUnits ();
+
+  //
+  // Initialize the PCIe Configuration base register.
+  //
+  PciCf8Write32 (PCI_CF8_LIB_ADDRESS (0xFF, 0, 1, 0x50), 0xE0000001);
+
+  //
+  // To ensure SMM can't be compromised on S3 resume, we must force re-init of
+  // the BaseExtractGuidedSectionLib. Since this is before library contructors
+  // are called, we must use a loop rather than SetMem.
+  //
+  Table = (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
+  for (Index = 0;
+       Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
+       ++Index) {
+    Table[Index] = 0;
+  }
+
+  ProcessLibraryConstructorList (NULL, NULL);
+
+  DEBUG ((EFI_D_INFO,
+    "SecCoreStartupWithStack(0x%x, 0x%x)\n",
+    (UINT32)(UINTN)BootFv,
+    (UINT32)(UINTN)TopOfCurrentStack
+    ));
+
+  //
+  // Initialize IDT
+  //
+  IdtTableInStack.PeiService = NULL;
+  for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
+    CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
+  }
+
+  IdtDescriptor.Base  = (UINTN)&IdtTableInStack.IdtTable;
+  IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
+
+  AsmWriteIdtr (&IdtDescriptor);
+
+#if defined (MDE_CPU_X64)
+  //
+  // ASSERT that the Page Tables were set by the reset vector code to
+  // the address we expect.
+  //
+  ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdSimicsSecPageTablesBase));
+#endif
+
+  //
+  // |-------------|       <-- TopOfCurrentStack
+  // |   Stack     | 32k
+  // |-------------|
+  // |    Heap     | 32k
+  // |-------------|       <-- SecCoreData.TemporaryRamBase
+  //
+
+  ASSERT ((UINTN) (PcdGet32 (PcdSimicsSecPeiTempRamBase) +
+                   PcdGet32 (PcdSimicsSecPeiTempRamSize)) ==
+          (UINTN) TopOfCurrentStack);
+
+  //
+  // Initialize SEC hand-off state
+  //
+  SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
+
+  SecCoreData.TemporaryRamSize       = (UINTN) PcdGet32 (PcdSimicsSecPeiTempRamSize);
+  SecCoreData.TemporaryRamBase       = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
+
+  SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;
+  SecCoreData.PeiTemporaryRamSize    = SecCoreData.TemporaryRamSize >> 1;
+
+  SecCoreData.StackBase              = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
+  SecCoreData.StackSize              = SecCoreData.TemporaryRamSize >> 1;
+
+  SecCoreData.BootFirmwareVolumeBase = BootFv;
+  SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
+
+  //
+  // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
+  //
+  IoWrite8 (0x21, 0xff);
+  IoWrite8 (0xA1, 0xff);
+
+  //
+  // Initialize Local APIC Timer hardware and disable Local APIC Timer
+  // interrupts before initializing the Debug Agent and the debug timer is
+  // enabled.
+  //
+  InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
+  DisableApicTimerInterrupt ();
+
+  //
+  // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
+  //
+  InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
+}
+
+/**
+  Caller provided function to be invoked at the end of InitializeDebugAgent().
+
+  Entry point to the C language phase of SEC. After the SEC assembly
+  code has initialized some temporary memory and set up the stack,
+  the control is transferred to this function.
+
+  @param[in] Context    The first input parameter of InitializeDebugAgent().
+
+**/
+VOID
+EFIAPI
+SecStartupPhase2(
+  IN VOID                     *Context
+  )
+{
+  EFI_SEC_PEI_HAND_OFF        *SecCoreData;
+  EFI_FIRMWARE_VOLUME_HEADER  *BootFv;
+  EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;
+
+  SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
+
+  //
+  // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
+  // is enabled.
+  //
+  BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
+  FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
+  SecCoreData->BootFirmwareVolumeBase = BootFv;
+  SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
+
+  //
+  // Transfer the control to the PEI core
+  //
+  (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
+
+  //
+  // If we get here then the PEI Core returned, which is not recoverable.
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+  IN CONST EFI_PEI_SERVICES   **PeiServices,
+  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
+  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
+  IN UINTN                    CopySize
+  )
+{
+  IA32_DESCRIPTOR                  IdtDescriptor;
+  VOID                             *OldHeap;
+  VOID                             *NewHeap;
+  VOID                             *OldStack;
+  VOID                             *NewStack;
+  DEBUG_AGENT_CONTEXT_POSTMEM_SEC  DebugAgentContext;
+  BOOLEAN                          OldStatus;
+  BASE_LIBRARY_JUMP_BUFFER         JumpBuffer;
+
+  DEBUG ((EFI_D_INFO,
+    "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
+    TemporaryMemoryBase,
+    PermanentMemoryBase,
+    (UINT64)CopySize
+    ));
+
+  OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+  NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
+
+  OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
+  NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+  DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
+  DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
+
+  OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
+  InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
+
+  //
+  // Migrate Heap
+  //
+  CopyMem (NewHeap, OldHeap, CopySize >> 1);
+
+  //
+  // Migrate Stack
+  //
+  CopyMem (NewStack, OldStack, CopySize >> 1);
+
+  //
+  // Rebase IDT table in permanent memory
+  //
+  AsmReadIdtr (&IdtDescriptor);
+  IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
+
+  AsmWriteIdtr (&IdtDescriptor);
+
+  //
+  // Use SetJump()/LongJump() to switch to a new stack.
+  //
+  if (SetJump (&JumpBuffer) == 0) {
+#if defined (MDE_CPU_IA32)
+    JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
+#endif
+#if defined (MDE_CPU_X64)
+    JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
+#endif
+    LongJump (&JumpBuffer, (UINTN)-1);
+  }
+
+  SaveAndSetDebugTimerInterrupt (OldStatus);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
new file mode 100644
index 0000000000..b7fd4d1f6d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
@@ -0,0 +1,865 @@
+/** @file
+  This driver effectuates QSP platform configuration settings and exposes
+  them via HII.
+
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/SimicsBoardConfig.h>
+
+#include "Platform.h"
+#include "PlatformConfig.h"
+#include <Library/DxeServicesTableLib.h>
+//
+// The HiiAddPackages() library function requires that any controller (or
+// image) handle, to be associated with the HII packages under installation, be
+// "decorated" with a device path. The tradition seems to be a vendor device
+// path.
+//
+// We'd like to associate our HII packages with the driver's image handle. The
+// first idea is to use the driver image's device path. Unfortunately, loaded
+// images only come with an EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL (not the
+// usual EFI_DEVICE_PATH_PROTOCOL), ie. a different GUID. In addition, even the
+// EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL interface may be NULL, if the image
+// has been loaded from an "unnamed" memory source buffer.
+//
+// Hence let's just stick with the tradition -- use a dedicated vendor device
+// path, with the driver's FILE_GUID.
+//
+#pragma pack(1)
+typedef struct {
+  VENDOR_DEVICE_PATH       VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL End;
+} PKG_DEVICE_PATH;
+#pragma pack()
+
+STATIC PKG_DEVICE_PATH mPkgDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)     ),
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH) >> 8)
+      }
+    },
+    EFI_CALLER_ID_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8) (END_DEVICE_PATH_LENGTH     ),
+      (UINT8) (END_DEVICE_PATH_LENGTH >> 8)
+    }
+  }
+};
+
+//
+// The configuration interface between the HII engine (form display etc) and
+// this driver.
+//
+STATIC EFI_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess;
+
+//
+// The handle representing our list of packages after installation.
+//
+STATIC EFI_HII_HANDLE mInstalledPackages;
+
+//
+// The arrays below constitute our HII package list. They are auto-generated by
+// the VFR compiler and linked into the driver image during the build.
+//
+// - The strings package receives its C identifier from the driver's BASE_NAME,
+//   plus "Strings".
+//
+// - The forms package receives its C identifier from the VFR file's basename,
+//   plus "Bin".
+//
+//
+extern UINT8 SimicsDxeStrings[];
+extern UINT8 PlatformFormsBin[];
+
+//
+// We want to be notified about GOP installations until we find one GOP
+// interface that lets us populate the form.
+//
+STATIC EFI_EVENT mGopEvent;
+
+//
+// The registration record underneath this pointer allows us to iterate through
+// the GOP instances one by one.
+//
+STATIC VOID *mGopTracker;
+
+//
+// Cache the resolutions we get from the GOP.
+//
+typedef struct {
+  UINT32 X;
+  UINT32 Y;
+} GOP_MODE;
+
+STATIC UINTN    mNumGopModes;
+STATIC GOP_MODE *mGopModes;
+
+
+/**
+  Load the persistent platform configuration and translate it to binary form
+  state.
+
+  If the platform configuration is missing, then the function fills in a
+  default state.
+
+  @param[out] MainFormState  Binary form/widget state after translation.
+
+  @retval EFI_SUCCESS  Form/widget state ready.
+  @return              Error codes from underlying functions.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PlatformConfigToFormState (
+  OUT MAIN_FORM_STATE *MainFormState
+  )
+{
+  EFI_STATUS      Status;
+  PLATFORM_CONFIG PlatformConfig;
+  UINT64          OptionalElements;
+  UINTN           ModeNumber;
+
+  ZeroMem (MainFormState, sizeof *MainFormState);
+
+  Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);
+  switch (Status) {
+  case EFI_SUCCESS:
+    if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {
+      //
+      // Format the preferred resolution as text.
+      //
+      UnicodeSPrintAsciiFormat (
+        (CHAR16 *) MainFormState->CurrentPreferredResolution,
+        sizeof MainFormState->CurrentPreferredResolution,
+        "%Ldx%Ld",
+        (INT64) PlatformConfig.HorizontalResolution,
+        (INT64) PlatformConfig.VerticalResolution);
+
+      //
+      // Try to locate it in the drop-down list too. This may not succeed, but
+      // that's fine.
+      //
+      for (ModeNumber = 0; ModeNumber < mNumGopModes; ++ModeNumber) {
+        if (mGopModes[ModeNumber].X == PlatformConfig.HorizontalResolution &&
+            mGopModes[ModeNumber].Y == PlatformConfig.VerticalResolution) {
+          MainFormState->NextPreferredResolution = (UINT32) ModeNumber;
+          break;
+        }
+      }
+
+      break;
+    }
+    //
+    // fall through otherwise
+    //
+
+  case EFI_NOT_FOUND:
+    UnicodeSPrintAsciiFormat (
+      (CHAR16 *) MainFormState->CurrentPreferredResolution,
+      sizeof MainFormState->CurrentPreferredResolution,
+      "Unset");
+    break;
+
+  default:
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function is called by the HII machinery when it fetches the form state.
+
+  See the precise documentation in the UEFI spec.
+
+  @param[in]  This      The Config Access Protocol instance.
+
+  @param[in]  Request   A <ConfigRequest> format UCS-2 string describing the
+                        query.
+
+  @param[out] Progress  A pointer into Request on output, identifying the query
+                        element where processing failed.
+
+  @param[out] Results   A <MultiConfigAltResp> format UCS-2 string that has
+                        all values filled in for the names in the Request
+                        string.
+
+  @retval EFI_SUCCESS  Extraction of form state in <MultiConfigAltResp>
+                       encoding successful.
+  @return              Status codes from underlying functions.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+)
+{
+  MAIN_FORM_STATE MainFormState;
+  EFI_STATUS      Status;
+
+  DEBUG ((EFI_D_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request));
+
+  Status = PlatformConfigToFormState (&MainFormState);
+  if (EFI_ERROR (Status)) {
+    *Progress = Request;
+    return Status;
+  }
+
+  //
+  // Answer the textual request keying off the binary form state.
+  //
+  Status = gHiiConfigRouting->BlockToConfig (gHiiConfigRouting, Request,
+                                (VOID *) &MainFormState, sizeof MainFormState,
+                                Results, Progress);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: BlockToConfig(): %r, Progress=\"%s\"\n",
+      __FUNCTION__, Status, (Status == EFI_DEVICE_ERROR) ? NULL : *Progress));
+  } else {
+    DEBUG ((EFI_D_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results));
+  }
+  return Status;
+}
+
+
+/**
+  Interpret the binary form state and save it as persistent platform
+  configuration.
+
+  @param[in] MainFormState  Binary form/widget state to verify and save.
+
+  @retval EFI_SUCCESS  Platform configuration saved.
+  @return              Error codes from underlying functions.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FormStateToPlatformConfig (
+  IN CONST MAIN_FORM_STATE *MainFormState
+  )
+{
+  EFI_STATUS      Status;
+  PLATFORM_CONFIG PlatformConfig;
+  CONST GOP_MODE  *GopMode;
+
+  //
+  // There's nothing to do with the textual CurrentPreferredResolution field.
+  // We verify and translate the selection in the drop-down list.
+  //
+  if (MainFormState->NextPreferredResolution >= mNumGopModes) {
+    return EFI_INVALID_PARAMETER;
+  }
+  GopMode = mGopModes + MainFormState->NextPreferredResolution;
+
+  ZeroMem (&PlatformConfig, sizeof PlatformConfig);
+  PlatformConfig.HorizontalResolution = GopMode->X;
+  PlatformConfig.VerticalResolution   = GopMode->Y;
+
+  Status = PlatformConfigSave (&PlatformConfig);
+  return Status;
+}
+
+
+/**
+  This function is called by the HII machinery when it wants the driver to
+  interpret and persist the form state.
+
+  See the precise documentation in the UEFI spec.
+
+  @param[in]  This           The Config Access Protocol instance.
+
+  @param[in]  Configuration  A <ConfigResp> format UCS-2 string describing the
+                             form state.
+
+  @param[out] Progress       A pointer into Configuration on output,
+                             identifying the element where processing failed.
+
+  @retval EFI_SUCCESS  Configuration verified, state permanent.
+
+  @return              Status codes from underlying functions.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+RouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+)
+{
+  MAIN_FORM_STATE MainFormState;
+  UINTN           BlockSize;
+  EFI_STATUS      Status;
+
+  DEBUG ((EFI_D_VERBOSE, "%a: Configuration=\"%s\"\n", __FUNCTION__,
+    Configuration));
+
+  //
+  // the "read" step in RMW
+  //
+  Status = PlatformConfigToFormState (&MainFormState);
+  if (EFI_ERROR (Status)) {
+    *Progress = Configuration;
+    return Status;
+  }
+
+  //
+  // the "modify" step in RMW
+  //
+  // (Update the binary form state. This update may be partial, which is why in
+  // general we must pre-load the form state from the platform config.)
+  //
+  BlockSize = sizeof MainFormState;
+  Status = gHiiConfigRouting->ConfigToBlock (gHiiConfigRouting, Configuration,
+                                (VOID *) &MainFormState, &BlockSize, Progress);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: ConfigToBlock(): %r, Progress=\"%s\"\n",
+      __FUNCTION__, Status,
+      (Status == EFI_BUFFER_TOO_SMALL) ? NULL : *Progress));
+    return Status;
+  }
+
+  //
+  // the "write" step in RMW
+  //
+  Status = FormStateToPlatformConfig (&MainFormState);
+  if (EFI_ERROR (Status)) {
+    *Progress = Configuration;
+  }
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+Callback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  )
+{
+  DEBUG ((EFI_D_VERBOSE, "%a: Action=0x%Lx QuestionId=%d Type=%d\n",
+    __FUNCTION__, (UINT64) Action, QuestionId, Type));
+
+  if (Action != EFI_BROWSER_ACTION_CHANGED) {
+    return EFI_UNSUPPORTED;
+  }
+
+  switch (QuestionId) {
+  case QUESTION_SAVE_EXIT:
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+    break;
+
+  case QUESTION_DISCARD_EXIT:
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+    break;
+
+  default:
+    break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Query and save all resolutions supported by the GOP.
+
+  @param[in]  Gop          The Graphics Output Protocol instance to query.
+
+  @param[out] NumGopModes  The number of modes supported by the GOP. On output,
+                           this parameter will be positive.
+
+  @param[out] GopModes     On output, a dynamically allocated array containing
+                           the resolutions returned by the GOP. The caller is
+                           responsible for freeing the array after use.
+
+  @retval EFI_UNSUPPORTED       No modes found.
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate GopModes.
+  @return                       Error codes from Gop->QueryMode().
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+QueryGopModes (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
+  OUT UINTN                        *NumGopModes,
+  OUT GOP_MODE                     **GopModes
+  )
+{
+  EFI_STATUS Status;
+  UINT32     ModeNumber;
+
+  if (Gop->Mode->MaxMode == 0) {
+    return EFI_UNSUPPORTED;
+  }
+  *NumGopModes = Gop->Mode->MaxMode;
+
+  *GopModes = AllocatePool (Gop->Mode->MaxMode * sizeof **GopModes);
+  if (*GopModes == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (ModeNumber = 0; ModeNumber < Gop->Mode->MaxMode; ++ModeNumber) {
+    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+    UINTN                                SizeOfInfo;
+
+    Status = Gop->QueryMode (Gop, ModeNumber, &SizeOfInfo, &Info);
+    if (EFI_ERROR (Status)) {
+      goto FreeGopModes;
+    }
+
+    (*GopModes)[ModeNumber].X = Info->HorizontalResolution;
+    (*GopModes)[ModeNumber].Y = Info->VerticalResolution;
+    FreePool (Info);
+  }
+
+  return EFI_SUCCESS;
+
+FreeGopModes:
+  FreePool (*GopModes);
+
+  return Status;
+}
+
+
+/**
+  Create a set of "one-of-many" (ie. "drop down list") option IFR opcodes,
+  based on available GOP resolutions, to be placed under a "one-of-many" (ie.
+  "drop down list") opcode.
+
+  @param[in]  PackageList   The package list with the formset and form for
+                            which the drop down options are produced. Option
+                            names are added as new strings to PackageList.
+
+  @param[out] OpCodeBuffer  On output, a dynamically allocated opcode buffer
+                            with drop down list options corresponding to GOP
+                            resolutions. The caller is responsible for freeing
+                            OpCodeBuffer with HiiFreeOpCodeHandle() after use.
+
+  @param[in]  NumGopModes   Number of entries in GopModes.
+
+  @param[in]  GopModes      Array of resolutions retrieved from the GOP.
+
+  @retval EFI_SUCESS  Opcodes have been successfully produced.
+
+  @return             Status codes from underlying functions. PackageList may
+                      have been extended with new strings. OpCodeBuffer is
+                      unchanged.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CreateResolutionOptions (
+  IN  EFI_HII_HANDLE  *PackageList,
+  OUT VOID            **OpCodeBuffer,
+  IN  UINTN           NumGopModes,
+  IN  GOP_MODE        *GopModes
+  )
+{
+  EFI_STATUS Status;
+  VOID       *OutputBuffer;
+  UINTN      ModeNumber;
+
+  OutputBuffer = HiiAllocateOpCodeHandle ();
+  if (OutputBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (ModeNumber = 0; ModeNumber < NumGopModes; ++ModeNumber) {
+    CHAR16        Desc[MAXSIZE_RES_CUR];
+    EFI_STRING_ID NewString;
+    VOID          *OpCode;
+
+    UnicodeSPrintAsciiFormat (Desc, sizeof Desc, "%Ldx%Ld",
+      (INT64) GopModes[ModeNumber].X, (INT64) GopModes[ModeNumber].Y);
+    NewString = HiiSetString (PackageList, 0 /* new string */, Desc,
+                  NULL /* for all languages */);
+    if (NewString == 0) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto FreeOutputBuffer;
+    }
+    OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString,
+               0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, ModeNumber);
+    if (OpCode == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto FreeOutputBuffer;
+    }
+  }
+
+  *OpCodeBuffer = OutputBuffer;
+  return EFI_SUCCESS;
+
+FreeOutputBuffer:
+  HiiFreeOpCodeHandle (OutputBuffer);
+
+  return Status;
+}
+
+
+/**
+  Populate the form identified by the (PackageList, FormSetGuid, FormId)
+  triplet.
+
+  The drop down list of video resolutions is generated from (NumGopModes,
+  GopModes).
+
+  @retval EFI_SUCESS  Form successfully updated.
+  @return             Status codes from underlying functions.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PopulateForm (
+  IN  EFI_HII_HANDLE  *PackageList,
+  IN  EFI_GUID        *FormSetGuid,
+  IN  EFI_FORM_ID     FormId,
+  IN  UINTN           NumGopModes,
+  IN  GOP_MODE        *GopModes
+  )
+{
+  EFI_STATUS         Status;
+  VOID               *OpCodeBuffer;
+  VOID               *OpCode;
+  EFI_IFR_GUID_LABEL *Anchor;
+  VOID               *OpCodeBuffer2;
+
+  OpCodeBuffer2 = NULL;
+
+  //
+  // 1. Allocate an empty opcode buffer.
+  //
+  OpCodeBuffer = HiiAllocateOpCodeHandle ();
+  if (OpCodeBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // 2. Create a label opcode (which is a Tiano extension) inside the buffer.
+  // The label's number must match the "anchor" label in the form.
+  //
+  OpCode = HiiCreateGuidOpCode (OpCodeBuffer, &gEfiIfrTianoGuid,
+             NULL /* optional copy origin */, sizeof *Anchor);
+  if (OpCode == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto FreeOpCodeBuffer;
+  }
+  Anchor               = OpCode;
+  Anchor->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  Anchor->Number       = LABEL_RES_NEXT;
+
+  //
+  // 3. Create the opcodes inside the buffer that are to be inserted into the
+  // form.
+  //
+  // 3.1. Get a list of resolutions.
+  //
+  Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2,
+             NumGopModes, GopModes);
+  if (EFI_ERROR (Status)) {
+    goto FreeOpCodeBuffer;
+  }
+
+  //
+  // 3.2. Create a one-of-many question with the above options.
+  //
+  OpCode = HiiCreateOneOfOpCode (
+             OpCodeBuffer,                        // create opcode inside this
+                                                  //   opcode buffer,
+             QUESTION_RES_NEXT,                   // ID of question,
+             FORMSTATEID_MAIN_FORM,               // identifies form state
+                                                  //   storage,
+             (UINT16) OFFSET_OF (MAIN_FORM_STATE, // value of question stored
+                        NextPreferredResolution), //   at this offset,
+             STRING_TOKEN (STR_RES_NEXT),         // Prompt,
+             STRING_TOKEN (STR_RES_NEXT_HELP),    // Help,
+             0,                                   // QuestionFlags,
+             EFI_IFR_NUMERIC_SIZE_4,              // see sizeof
+                                                  //   NextPreferredResolution,
+             OpCodeBuffer2,                       // buffer with possible
+                                                  //   choices,
+             NULL                                 // DEFAULT opcodes
+             );
+  if (OpCode == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto FreeOpCodeBuffer2;
+  }
+
+  //
+  // 4. Update the form with the opcode buffer.
+  //
+  Status = HiiUpdateForm (PackageList, FormSetGuid, FormId,
+             OpCodeBuffer, // buffer with head anchor, and new contents to be
+                           // inserted at it
+             NULL          // buffer with tail anchor, for deleting old
+                           // contents up to it
+             );
+
+FreeOpCodeBuffer2:
+  HiiFreeOpCodeHandle (OpCodeBuffer2);
+
+FreeOpCodeBuffer:
+  HiiFreeOpCodeHandle (OpCodeBuffer);
+
+  return Status;
+}
+
+
+/**
+  Load and execute the platform configuration.
+
+  @retval EFI_SUCCESS            Configuration loaded and executed.
+  @return                        Status codes from PlatformConfigLoad().
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ExecutePlatformConfig (
+  VOID
+  )
+{
+  EFI_STATUS      Status;
+  PLATFORM_CONFIG PlatformConfig;
+  UINT64          OptionalElements;
+
+  Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);
+  if (EFI_ERROR (Status)) {
+    DEBUG (((Status == EFI_NOT_FOUND) ? EFI_D_VERBOSE : EFI_D_ERROR,
+      "%a: failed to load platform config: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {
+    //
+    // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs.
+    //
+    PcdSet32 (PcdVideoHorizontalResolution,
+      PlatformConfig.HorizontalResolution);
+    PcdSet32 (PcdVideoVerticalResolution,
+      PlatformConfig.VerticalResolution);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Notification callback for GOP interface installation.
+
+  @param[in] Event    Event whose notification function is being invoked.
+
+  @param[in] Context  The pointer to the notification function's context, which
+                      is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+GopInstalled (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+  ASSERT (Event == mGopEvent);
+
+  //
+  // Check further GOPs.
+  //
+  for (;;) {
+    mNumGopModes = 0;
+    mGopModes = NULL;
+
+    Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, mGopTracker,
+                    (VOID **) &Gop);
+    if (EFI_ERROR (Status)) {
+      return;
+    }
+
+    Status = QueryGopModes (Gop, &mNumGopModes, &mGopModes);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    Status = PopulateForm (mInstalledPackages, &gSimicsBoardConfigGuid,
+               FORMID_MAIN_FORM, mNumGopModes, mGopModes);
+    if (EFI_ERROR (Status)) {
+      FreePool (mGopModes);
+      continue;
+    }
+
+    break;
+  }
+
+  //
+  // Success -- so uninstall this callback. Closing the event removes all
+  // pending notifications and all protocol registrations.
+  //
+  Status = gBS->CloseEvent (mGopEvent);
+  ASSERT_EFI_ERROR (Status);
+  mGopEvent = NULL;
+  mGopTracker = NULL;
+}
+
+
+/**
+  Entry point for this driver.
+
+  @param[in] ImageHandle  Image handle of this driver.
+  @param[in] SystemTable  Pointer to SystemTable.
+
+  @retval EFI_SUCESS            Driver has loaded successfully.
+  @retval EFI_OUT_OF_RESOURCES  Failed to install HII packages.
+  @return                       Error codes from lower level functions.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformInit (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS Status;
+
+  ExecutePlatformConfig ();
+
+  mConfigAccess.ExtractConfig = &ExtractConfig;
+  mConfigAccess.RouteConfig   = &RouteConfig;
+  mConfigAccess.Callback      = &Callback;
+
+  //
+  // Declare ourselves suitable for HII communication.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+                  &gEfiDevicePathProtocolGuid,      &mPkgDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Publish the HII package list to HII Database.
+  //
+  mInstalledPackages = HiiAddPackages (
+                         &gEfiCallerIdGuid,  // PackageListGuid
+                         ImageHandle,        // associated DeviceHandle
+                         SimicsDxeStrings,   // 1st package
+                         PlatformFormsBin,   // 2nd package
+                         NULL                // terminator
+                         );
+  if (mInstalledPackages == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto UninstallProtocols;
+  }
+
+  Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, &GopInstalled,
+                  NULL /* Context */, &mGopEvent);
+  if (EFI_ERROR (Status)) {
+    goto RemovePackages;
+  }
+
+  Status = gBS->RegisterProtocolNotify (&gEfiGraphicsOutputProtocolGuid,
+                  mGopEvent, &mGopTracker);
+  if (EFI_ERROR (Status)) {
+    goto CloseGopEvent;
+  }
+
+  //
+  // Check already installed GOPs.
+  //
+  Status = gBS->SignalEvent (mGopEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+
+CloseGopEvent:
+  gBS->CloseEvent (mGopEvent);
+
+RemovePackages:
+  HiiRemovePackages (mInstalledPackages);
+
+UninstallProtocols:
+  gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
+         &gEfiDevicePathProtocolGuid,      &mPkgDevicePath,
+         &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,
+         NULL);
+  return Status;
+}
+
+/**
+  Unload the driver.
+
+  @param[in]  ImageHandle  Handle that identifies the image to evict.
+
+  @retval EFI_SUCCESS  The image has been unloaded.
+**/
+EFI_STATUS
+EFIAPI
+PlatformUnload (
+  IN  EFI_HANDLE  ImageHandle
+  )
+{
+  if (mGopEvent == NULL) {
+    //
+    // The GOP callback ran successfully and unregistered itself. Release the
+    // resources allocated there.
+    //
+    ASSERT (mGopModes != NULL);
+    FreePool (mGopModes);
+  } else {
+    //
+    // Otherwise we need to unregister the callback.
+    //
+    ASSERT (mGopModes == NULL);
+    gBS->CloseEvent (mGopEvent);
+  }
+
+  //
+  // Release resources allocated by the entry point.
+  //
+  HiiRemovePackages (mInstalledPackages);
+  gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
+         &gEfiDevicePathProtocolGuid,      &mPkgDevicePath,
+         &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,
+         NULL);
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
new file mode 100644
index 0000000000..09929e830a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
@@ -0,0 +1,124 @@
+/** @file
+  Utility functions for serializing (persistently storing) and deserializing
+  SIMICS QSP's platform configuration.
+
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/SimicsBoardConfig.h>
+
+#include "PlatformConfig.h"
+
+//
+// Name of the UEFI variable that we use for persistent storage.
+//
+STATIC CHAR16 mVariableName[] = L"PlatformConfig";
+
+
+/**
+  Serialize and persistently save platform configuration.
+
+  @param[in] PlatformConfig  The platform configuration to serialize and save.
+
+  @return  Status codes returned by gRT->SetVariable().
+**/
+EFI_STATUS
+EFIAPI
+PlatformConfigSave (
+  IN PLATFORM_CONFIG *PlatformConfig
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // We could implement any kind of translation here, as part of serialization.
+  // For example, we could expose the platform configuration in separate
+  // variables with human-readable contents, allowing other tools to access
+  // them more easily. For now, just save a binary dump.
+  //
+  Status = gRT->SetVariable (mVariableName, &gSimicsBoardConfigGuid,
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                    EFI_VARIABLE_RUNTIME_ACCESS,
+                  sizeof *PlatformConfig, PlatformConfig);
+  return Status;
+}
+
+
+/**
+  Load and deserialize platform configuration.
+
+  When the function fails, output parameters are indeterminate.
+
+  @param[out] PlatformConfig    The platform configuration to receive the
+                                loaded data.
+
+  @param[out] OptionalElements  This bitmap describes the presence of optional
+                                configuration elements that have been loaded.
+                                PLATFORM_CONFIG_F_DOWNGRADE means that some
+                                unknown elements, present in the wire format,
+                                have been ignored.
+
+  @retval  EFI_SUCCESS         Loading & deserialization successful.
+  @return                      Error codes returned by GetVariable2().
+**/
+EFI_STATUS
+EFIAPI
+PlatformConfigLoad (
+  OUT PLATFORM_CONFIG *PlatformConfig,
+  OUT UINT64          *OptionalElements
+  )
+{
+  VOID       *Data;
+  UINTN      DataSize;
+  EFI_STATUS Status;
+
+  //
+  // Any translation done in PlatformConfigSave() would have to be mirrored
+  // here. For now, just load the binary dump.
+  //
+  // Versioning of the binary wire format is implemented based on size
+  // (only incremental changes, ie. new fields), and on GUID.
+  // (Incompatible changes require a GUID change.)
+  //
+  Status = GetVariable2 (mVariableName, &gSimicsBoardConfigGuid, &Data,
+             &DataSize);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *OptionalElements = 0;
+  if (DataSize > sizeof *PlatformConfig) {
+    //
+    // Handle firmware downgrade -- keep only leading part.
+    //
+    CopyMem (PlatformConfig, Data, sizeof *PlatformConfig);
+    *OptionalElements |= PLATFORM_CONFIG_F_DOWNGRADE;
+  } else {
+    CopyMem (PlatformConfig, Data, DataSize);
+
+    //
+    // Handle firmware upgrade -- zero out missing fields.
+    //
+    ZeroMem ((UINT8 *)PlatformConfig + DataSize,
+      sizeof *PlatformConfig - DataSize);
+  }
+
+  //
+  // Based on DataSize, report the optional features that we recognize.
+  //
+  if (DataSize >= (OFFSET_OF (PLATFORM_CONFIG, VerticalResolution) +
+                   sizeof PlatformConfig->VerticalResolution)) {
+    *OptionalElements |= PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION;
+  }
+
+  FreePool (Data);
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
new file mode 100644
index 0000000000..b34ba9283b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
@@ -0,0 +1,57 @@
+/** @file
+  PC/AT CMOS access routines
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Cmos.h"
+#include "Library/IoLib.h"
+
+/**
+  Reads 8-bits of CMOS data.
+
+  Reads the 8-bits of CMOS data at the location specified by Index.
+  The 8-bit read value is returned.
+
+  @param  Index  The CMOS location to read.
+
+  @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+  IN      UINTN                     Index
+  )
+{
+  IoWrite8 (0x70, (UINT8) Index);
+  return IoRead8 (0x71);
+}
+
+
+/**
+  Writes 8-bits of CMOS data.
+
+  Writes 8-bits of CMOS data to the location specified by Index
+  with the value specified by Value and returns Value.
+
+  @param  Index  The CMOS location to write.
+  @param  Value  The value to write to CMOS.
+
+  @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+  IN      UINTN                     Index,
+  IN      UINT8                     Value
+  )
+{
+  IoWrite8 (0x70, (UINT8) Index);
+  IoWrite8 (0x71, Value);
+  return Value;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
new file mode 100644
index 0000000000..9d2fc65a14
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
@@ -0,0 +1,115 @@
+/** @file
+  Install a callback when necessary for setting the Feature Control MSR on all
+  processors.
+
+  Copyright (C) 2016, Red Hat, Inc.
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/MpServices.h>
+#include <Register/Intel/Msr/Core2Msr.h>
+
+#include "Platform.h"
+
+//
+// The value to be written to the Feature Control MSR, retrieved from fw_cfg.
+//
+STATIC UINT64 mFeatureControlValue = 0x00000005;
+
+/**
+  Write the Feature Control MSR on an Application Processor or the Boot
+  Processor.
+
+  All APs execute this function in parallel. The BSP executes the function
+  separately.
+
+  @param[in,out] WorkSpace  Pointer to the input/output argument workspace
+                            shared by all processors.
+**/
+STATIC
+VOID
+EFIAPI
+WriteFeatureControl (
+  IN OUT VOID *WorkSpace
+  )
+{
+  AsmWriteMsr64 (MSR_CORE2_FEATURE_CONTROL, mFeatureControlValue);
+}
+
+/**
+  Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
+
+  @param[in] PeiServices      Indirect reference to the PEI Services Table.
+  @param[in] NotifyDescriptor Address of the notification descriptor data
+                              structure.
+  @param[in] Ppi              Address of the PPI that was installed.
+
+  @return  Status of the notification. The status code returned from this
+           function is ignored.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+OnMpServicesAvailable (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_PEI_MP_SERVICES_PPI *MpServices;
+  EFI_STATUS              Status;
+
+  DEBUG ((EFI_D_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
+  //
+  // Write the MSR on all the APs in parallel.
+  //
+  MpServices = Ppi;
+  Status = MpServices->StartupAllAPs (
+                         (CONST EFI_PEI_SERVICES **)PeiServices,
+                         MpServices,
+                         WriteFeatureControl, // Procedure
+                         FALSE,               // SingleThread
+                         0,                   // TimeoutInMicroSeconds: inf.
+                         NULL                 // ProcedureArgument
+                         );
+  if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
+    DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  //
+  // Now write the MSR on the BSP too.
+  //
+  WriteFeatureControl (NULL);
+
+  return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EFI_PEI_MP_SERVICES_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
+  EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gEfiPeiMpServicesPpiGuid,               // Guid
+  OnMpServicesAvailable                    // Notify
+};
+
+VOID
+InstallFeatureControlCallback (
+  VOID
+  )
+{
+  EFI_STATUS           Status;
+
+  Status = PeiServicesNotifyPpi (&mMpServicesNotify);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: failed to set up MP Services callback: %r\n",
+      __FUNCTION__, Status));
+  }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
new file mode 100644
index 0000000000..90e6d1d3cf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
@@ -0,0 +1,568 @@
+/** @file
+  Memory Detection for Virtual Machines.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/MtrrLib.h>
+#include <SimicsPlatforms.h>
+#include <Guid/SmramMemoryReserve.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+UINT8 mPhysMemAddressWidth;
+
+STATIC UINT32 mS3AcpiReservedMemoryBase;
+STATIC UINT32 mS3AcpiReservedMemorySize;
+
+STATIC UINT16 mX58TsegMbytes;
+
+VOID
+X58TsegMbytesInitialization(
+  VOID
+)
+{
+
+  if (mHostBridgeDevId != INTEL_ICH10_DEVICE_ID) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
+      "only DID=0x%04x (X58) is supported\n",
+      __FUNCTION__,
+      mHostBridgeDevId,
+      INTEL_ICH10_DEVICE_ID
+      ));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+
+  //
+  // Check if QEMU offers an extended TSEG.
+  //
+  // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TSEG_MB
+  // register, and reading back the register.
+  //
+  // On a QEMU machine type that does not offer an extended TSEG, the initial
+  // write overwrites whatever value a malicious guest OS may have placed in
+  // the (unimplemented) register, before entering S3 or rebooting.
+  // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.
+  //
+  // On a QEMU machine type that offers an extended TSEG, the initial write
+  // triggers an update to the register. Subsequently, the value read back
+  // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us the
+  // number of megabytes.
+  //
+  mX58TsegMbytes = FixedPcdGet8(PcdX58TsegMbytes);
+  return;
+}
+
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+  VOID
+  )
+{
+  UINT8 Cmos0x34;
+  UINT8 Cmos0x35;
+
+  //
+  // CMOS 0x34/0x35 specifies the system memory above 16 MB.
+  // * CMOS(0x35) is the high byte
+  // * CMOS(0x34) is the low byte
+  // * The size is specified in 64kb chunks
+  // * Since this is memory above 16MB, the 16MB must be added
+  //   into the calculation to get the total memory size.
+  //
+
+  Cmos0x34 = (UINT8) CmosRead8 (0x34);
+  Cmos0x35 = (UINT8) CmosRead8 (0x35);
+
+  return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+}
+
+
+STATIC
+UINT64
+GetSystemMemorySizeAbove4gb (
+  )
+{
+  UINT32 Size;
+  UINTN  CmosIndex;
+
+  //
+  // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
+  // * CMOS(0x5d) is the most significant size byte
+  // * CMOS(0x5c) is the middle size byte
+  // * CMOS(0x5b) is the least significant size byte
+  // * The size is specified in 64kb chunks
+  //
+
+  Size = 0;
+  for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+    Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
+  }
+
+  return LShiftU64 (Size, 16);
+}
+
+
+/**
+  Return the highest address that DXE could possibly use, plus one.
+**/
+STATIC
+UINT64
+GetFirstNonAddress (
+  VOID
+  )
+{
+  UINT64               FirstNonAddress;
+  UINT64               Pci64Base, Pci64Size;
+
+  FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();
+
+  //
+  // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
+  // resources to 32-bit anyway. See DegradeResource() in
+  // "PciResourceSupport.c".
+  //
+#ifdef MDE_CPU_IA32
+  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+    return FirstNonAddress;
+  }
+#endif
+
+  //
+  // Otherwise, in order to calculate the highest address plus one, we must
+  // consider the 64-bit PCI host aperture too. Fetch the default size.
+  //
+  Pci64Size = PcdGet64 (PcdPciMmio64Size);
+
+  if (Pci64Size == 0) {
+    if (mBootMode != BOOT_ON_S3_RESUME) {
+      DEBUG ((EFI_D_INFO, "%a: disabling 64-bit PCI host aperture\n",
+        __FUNCTION__));
+      PcdSet64 (PcdPciMmio64Size, 0);
+    }
+
+    //
+    // There's nothing more to do; the amount of memory above 4GB fully
+    // determines the highest address plus one. The memory hotplug area (see
+    // below) plays no role for the firmware in this case.
+    //
+    return FirstNonAddress;
+  }
+
+  //
+  // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
+  // that the host can map it with 1GB hugepages. Follow suit.
+  //
+  Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
+  Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);
+
+  //
+  // The 64-bit PCI host aperture should also be "naturally" aligned. The
+  // alignment is determined by rounding the size of the aperture down to the
+  // next smaller or equal power of two. That is, align the aperture by the
+  // largest BAR size that can fit into it.
+  //
+  Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
+
+  if (mBootMode != BOOT_ON_S3_RESUME) {
+    //
+    // The core PciHostBridgeDxe driver will automatically add this range to
+    // the GCD memory space map through our PciHostBridgeLib instance; here we
+    // only need to set the PCDs.
+    //
+    PcdSet64 (PcdPciMmio64Base, Pci64Base);
+    PcdSet64 (PcdPciMmio64Size, Pci64Size);
+    DEBUG ((EFI_D_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",
+      __FUNCTION__, Pci64Base, Pci64Size));
+  }
+
+  //
+  // The useful address space ends with the 64-bit PCI host aperture.
+  //
+  FirstNonAddress = Pci64Base + Pci64Size;
+  return FirstNonAddress;
+}
+
+
+/**
+  Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
+**/
+VOID
+AddressWidthInitialization (
+  VOID
+  )
+{
+  UINT64 FirstNonAddress;
+
+  //
+  // As guest-physical memory size grows, the permanent PEI RAM requirements
+  // are dominated by the identity-mapping page tables built by the DXE IPL.
+  // The DXL IPL keys off of the physical address bits advertized in the CPU
+  // HOB. To conserve memory, we calculate the minimum address width here.
+  //
+  FirstNonAddress      = GetFirstNonAddress ();
+  mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
+
+  //
+  // If FirstNonAddress is not an integral power of two, then we need an
+  // additional bit.
+  //
+  if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
+    ++mPhysMemAddressWidth;
+  }
+
+  //
+  // The minimum address width is 36 (covers up to and excluding 64 GB, which
+  // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
+  // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
+  // can simply assert that here, since 48 bits are good enough for 256 TB.
+  //
+  if (mPhysMemAddressWidth <= 36) {
+    mPhysMemAddressWidth = 36;
+  }
+  ASSERT (mPhysMemAddressWidth <= 48);
+}
+
+
+/**
+  Calculate the cap for the permanent PEI memory.
+**/
+STATIC
+UINT32
+GetPeiMemoryCap (
+  VOID
+  )
+{
+  BOOLEAN Page1GSupport;
+  UINT32  RegEax;
+  UINT32  RegEdx;
+  UINT32  Pml4Entries;
+  UINT32  PdpEntries;
+  UINTN   TotalPages;
+
+  //
+  // If DXE is 32-bit, then just return the traditional 64 MB cap.
+  //
+#ifdef MDE_CPU_IA32
+  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+    return SIZE_64MB;
+  }
+#endif
+
+  //
+  // Dependent on physical address width, PEI memory allocations can be
+  // dominated by the page tables built for 64-bit DXE. So we key the cap off
+  // of those. The code below is based on CreateIdentityMappingPageTables() in
+  // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".
+  //
+  Page1GSupport = FALSE;
+  if (PcdGetBool (PcdUse1GPageTable)) {
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+    if (RegEax >= 0x80000001) {
+      AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+      if ((RegEdx & BIT26) != 0) {
+        Page1GSupport = TRUE;
+      }
+    }
+  }
+
+  if (mPhysMemAddressWidth <= 39) {
+    Pml4Entries = 1;
+    PdpEntries = 1 << (mPhysMemAddressWidth - 30);
+    ASSERT (PdpEntries <= 0x200);
+  } else {
+    Pml4Entries = 1 << (mPhysMemAddressWidth - 39);
+    ASSERT (Pml4Entries <= 0x200);
+    PdpEntries = 512;
+  }
+
+  TotalPages = Page1GSupport ? Pml4Entries + 1 :
+                               (PdpEntries + 1) * Pml4Entries + 1;
+  ASSERT (TotalPages <= 0x40201);
+
+  //
+  // Add 64 MB for miscellaneous allocations. Note that for
+  // mPhysMemAddressWidth values close to 36, the cap will actually be
+  // dominated by this increment.
+  //
+  return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);
+}
+
+
+/**
+  Publish PEI core memory
+
+  @return EFI_SUCCESS     The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+PublishPeiMemory (
+  VOID
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PHYSICAL_ADDRESS        MemoryBase;
+  UINT64                      MemorySize;
+  UINT32                      LowerMemorySize;
+  UINT32                      PeiMemoryCap;
+
+  LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+  if (FeaturePcdGet (PcdSmmSmramRequire)) {
+    //
+    // TSEG is chipped from the end of low RAM
+    //
+    LowerMemorySize -= mX58TsegMbytes * SIZE_1MB;
+  }
+
+  //
+  // If S3 is supported, then the S3 permanent PEI memory is placed next,
+  // downwards. Its size is primarily dictated by CpuMpPei. The formula below
+  // is an approximation.
+  //
+  if (mS3Supported) {
+    mS3AcpiReservedMemorySize = SIZE_512KB +
+      mMaxCpuCount *
+      PcdGet32 (PcdCpuApStackSize);
+    mS3AcpiReservedMemoryBase = LowerMemorySize - mS3AcpiReservedMemorySize;
+    LowerMemorySize = mS3AcpiReservedMemoryBase;
+  }
+
+  if (mBootMode == BOOT_ON_S3_RESUME) {
+    MemoryBase = mS3AcpiReservedMemoryBase;
+    MemorySize = mS3AcpiReservedMemorySize;
+  } else {
+    PeiMemoryCap = GetPeiMemoryCap ();
+    DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",
+      __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));
+
+    //
+    // Determine the range of memory to use during PEI
+    //
+    // Technically we could lay the permanent PEI RAM over SEC's temporary
+    // decompression and scratch buffer even if "secure S3" is needed, since
+    // their lifetimes don't overlap. However, PeiFvInitialization() will cover
+    // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory
+    // allocation HOB, and other allocations served from the permanent PEI RAM
+    // shouldn't overlap with that HOB.
+    //
+    MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?
+      PcdGet32 (PcdSimicsDecompressionScratchEnd) :
+      PcdGet32 (PcdSimicsDxeMemFvBase) + PcdGet32 (PcdSimicsDxeMemFvSize);
+    MemorySize = LowerMemorySize - MemoryBase;
+  }
+  DEBUG((EFI_D_INFO, "MemoryBase=0x%lx MemorySize=0x%lx\n", MemoryBase, MemorySize));
+  //
+  // Publish this memory to the PEI Core
+  //
+  Status = PublishSystemMemory(MemoryBase, MemorySize);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+
+/**
+  Peform Memory Detection for QEMU / KVM
+
+**/
+STATIC
+VOID
+QemuInitializeRam (
+  VOID
+  )
+{
+  UINT64                               LowerMemorySize;
+  UINT64                               UpperMemorySize;
+  UINTN                                 BufferSize;
+  UINT8                                 SmramIndex;
+  UINT8                                 SmramRanges;
+  EFI_PEI_HOB_POINTERS                  Hob;
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK        *SmramHobDescriptorBlock;
+  UINT8                                 Index;
+
+  DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));
+
+  //
+  // Determine total memory size available
+  //
+  LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+  UpperMemorySize = GetSystemMemorySizeAbove4gb ();
+
+  if (mBootMode == BOOT_ON_S3_RESUME) {
+    //
+    // Create the following memory HOB as an exception on the S3 boot path.
+    //
+    // Normally we'd create memory HOBs only on the normal boot path. However,
+    // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
+    // well, for "borrowing" a subset of it temporarily, for the AP startup
+    // vector.
+    //
+    // CpuMpPei saves the original contents of the borrowed area in permanent
+    // PEI RAM, in a backup buffer allocated with the normal PEI services.
+    // CpuMpPei restores the original contents ("returns" the borrowed area) at
+    // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
+    // transferring control to the OS's wakeup vector in the FACS.
+    //
+    // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
+    // restore the original contents. Furthermore, we expect all such PEIMs
+    // (CpuMpPei included) to claim the borrowed areas by producing memory
+    // allocation HOBs, and to honor preexistent memory allocation HOBs when
+    // looking for an area to borrow.
+    //
+    AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+  } else {
+    //
+    // Create memory HOBs
+    //
+    AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+
+    if (FeaturePcdGet (PcdSmmSmramRequire)) {
+      UINT32 TsegSize;
+
+      TsegSize = mX58TsegMbytes * SIZE_1MB;
+      AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
+      AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,
+        TRUE);
+
+	  BufferSize = sizeof(EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);
+	  SmramRanges = 1;
+
+      Hob.Raw = BuildGuidHob(
+          &gEfiSmmPeiSmramMemoryReserveGuid,
+          BufferSize
+      );
+      ASSERT(Hob.Raw);
+
+      SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)(Hob.Raw);
+      SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;
+
+      SmramIndex = 0;
+      for (Index = 0; Index < SmramRanges; Index++) {
+        //
+        // This is an SMRAM range, create an SMRAM descriptor
+        //
+        SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = LowerMemorySize - TsegSize;
+        SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = LowerMemorySize - TsegSize;
+        SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = TsegSize;
+        SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+        SmramIndex++;
+      }
+
+    } else {
+      AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
+    }
+
+    //
+    // If QEMU presents an E820 map, then create memory HOBs for the >=4GB RAM
+    // entries. Otherwise, create a single memory HOB with the flat >=4GB
+    // memory size read from the CMOS.
+    //
+    if (UpperMemorySize != 0) {
+      AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
+    }
+  }
+}
+
+/**
+  Publish system RAM and reserve memory regions
+
+**/
+VOID
+InitializeRamRegions (
+  VOID
+  )
+{
+  QemuInitializeRam ();
+
+  if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) {
+    //
+    // This is the memory range that will be used for PEI on S3 resume
+    //
+    BuildMemoryAllocationHob (
+      mS3AcpiReservedMemoryBase,
+      mS3AcpiReservedMemorySize,
+      EfiACPIMemoryNVS
+      );
+
+    //
+    // Cover the initial RAM area used as stack and temporary PEI heap.
+    //
+    // This is reserved as ACPI NVS so it can be used on S3 resume.
+    //
+    BuildMemoryAllocationHob (
+      PcdGet32 (PcdSimicsSecPeiTempRamBase),
+      PcdGet32 (PcdSimicsSecPeiTempRamSize),
+      EfiACPIMemoryNVS
+      );
+
+    //
+    // SEC stores its table of GUIDed section handlers here.
+    //
+    BuildMemoryAllocationHob (
+      PcdGet64 (PcdGuidedExtractHandlerTableAddress),
+      PcdGet32 (PcdGuidedExtractHandlerTableSize),
+      EfiACPIMemoryNVS
+      );
+
+  }
+
+  if (mBootMode != BOOT_ON_S3_RESUME) {
+    if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+      //
+      // Reserve the lock box storage area
+      //
+      // Since this memory range will be used on S3 resume, it must be
+      // reserved as ACPI NVS.
+      //
+      // If S3 is unsupported, then various drivers might still write to the
+      // LockBox area. We ought to prevent DXE from serving allocation requests
+      // such that they would overlap the LockBox storage.
+      //
+      ZeroMem (
+        (VOID*)(UINTN) PcdGet32 (PcdSimicsLockBoxStorageBase),
+        (UINTN) PcdGet32 (PcdSimicsLockBoxStorageSize)
+        );
+      BuildMemoryAllocationHob (
+        (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdSimicsLockBoxStorageBase),
+        (UINT64)(UINTN) PcdGet32 (PcdSimicsLockBoxStorageSize),
+        mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+        );
+    }
+
+    if (FeaturePcdGet (PcdSmmSmramRequire)) {
+      UINT32 TsegSize;
+
+      //
+      // Make sure the TSEG area that we reported as a reserved memory resource
+      // cannot be used for reserved memory allocations.
+      //
+      TsegSize = mX58TsegMbytes * SIZE_1MB;
+      BuildMemoryAllocationHob (
+        GetSystemMemorySizeBelow4gb() - TsegSize,
+        TsegSize,
+        EfiReservedMemoryType
+        );
+    }
+  }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
new file mode 100644
index 0000000000..2fe34b02c4
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
@@ -0,0 +1,630 @@
+/** @file
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Ppi/MasterBootMode.h>
+#include <IndustryStandard/Pci22.h>
+#include <SimicsPlatforms.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+  { EfiACPIMemoryNVS,       0x004 },
+  { EfiACPIReclaimMemory,   0x008 },
+  { EfiReservedMemoryType,  0x004 },
+  { EfiRuntimeServicesData, 0x024 },
+  { EfiRuntimeServicesCode, 0x030 },
+  { EfiBootServicesCode,    0x180 },
+  { EfiBootServicesData,    0xF00 },
+  { EfiMaxMemoryType,       0x000 }
+};
+
+
+EFI_PEI_PPI_DESCRIPTOR   mPpiBootMode[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gEfiPeiMasterBootModePpiGuid,
+    NULL
+  }
+};
+
+
+UINT16 mHostBridgeDevId;
+
+EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+BOOLEAN mS3Supported = FALSE;
+
+UINT32 mMaxCpuCount;
+
+VOID
+AddIoMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_MEMORY_MAPPED_IO,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT     |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_TESTED,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+VOID
+AddReservedMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize,
+  BOOLEAN                     Cacheable
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_MEMORY_RESERVED,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT     |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      (Cacheable ?
+       EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+       EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+       EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :
+       0
+       ) |
+      EFI_RESOURCE_ATTRIBUTE_TESTED,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+VOID
+AddIoMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  )
+{
+  AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+AddMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_SYSTEM_MEMORY,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_TESTED,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+
+VOID
+AddMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  )
+{
+  AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+AddUntestedMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_SYSTEM_MEMORY,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+
+VOID
+AddUntestedMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  )
+{
+  AddUntestedMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+VOID
+AddFlashDeviceRange (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_FIRMWARE_DEVICE,
+    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+    MemoryBase,
+    MemorySize
+    );
+
+  BuildMemoryAllocationHob (
+    MemoryBase,
+    MemorySize,
+    EfiMemoryMappedIO
+    );
+}
+
+VOID
+MemMapInitialization (
+  VOID
+  )
+{
+  UINT64 PciIoBase;
+  UINT64 PciIoSize;
+
+  UINT32  TopOfLowRam;
+  UINT64  PciExBarBase;
+  UINT32  PciBase;
+  UINT32  PciSize;
+
+  PciIoBase = 0xC000;
+  PciIoSize = 0x4000;
+
+  //
+  // Create Memory Type Information HOB
+  //
+  BuildGuidDataHob (
+    &gEfiMemoryTypeInformationGuid,
+    mDefaultMemoryTypeInformation,
+    sizeof(mDefaultMemoryTypeInformation)
+    );
+
+  //
+  // Video memory + Legacy BIOS region
+  //
+  AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
+
+  TopOfLowRam = GetSystemMemorySizeBelow4gb ();
+  PciExBarBase = 0;
+  if (mHostBridgeDevId == INTEL_ICH10_DEVICE_ID) {
+    //
+    // The MMCONFIG area is expected to fall between the top of low RAM and
+    // the base of the 32-bit PCI host aperture.
+    //
+    PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
+    ASSERT (TopOfLowRam <= PciExBarBase);
+    ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
+    PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
+  } else {
+    PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
+  }
+
+  //
+  // address       purpose   size
+  // ------------  --------  -------------------------
+  // 0x00000000    TopOfLowRam   0xDF000000
+  // 0xDF000000    Tseg+UMA      0x01000000
+  // 0xE0000000    PciExBarBase  0x10000000
+  // 0xF0000000    PciBase       0x0C000000
+  // -------------------------------------------------
+  // max(top, 2g)  PCI MMIO  0xFC000000 - max(top, 2g)
+  // 0xFC000000    gap                           44 MB
+  // 0xFEC00000    IO-APIC                        4 KB
+  // 0xFEC01000    gap                         1020 KB
+  // 0xFED00000    HPET                           1 KB
+  // 0xFED00400    gap                          111 KB
+  // 0xFED1C000    gap (PIIX4) / RCRB (ICH9)     16 KB
+  // 0xFED20000    gap                          896 KB
+  // 0xFEE00000    LAPIC                          1 MB
+  //
+  PciSize = 0xFC000000 - PciBase;
+  AddIoMemoryBaseSizeHob (PciBase, PciSize);
+  PcdSet64 (PcdPciMmio32Base, PciBase);
+  PcdSet64 (PcdPciMmio32Size, PciSize);
+  AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
+  AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
+  if (mHostBridgeDevId == INTEL_ICH10_DEVICE_ID) {
+    AddIoMemoryBaseSizeHob (ICH10_ROOT_COMPLEX_BASE, SIZE_16KB);
+    //
+    // Note: there should be an
+    //
+    //   AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
+    //   BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB, EfiMemoryMappedIO);
+    //
+    // call below, just like the one above for RCBA. However, Linux insists
+    // that the MMCONFIG area be marked in the E820 or UEFI memory map as
+    // "reserved memory" -- Linux does not content itself with a simple gap
+    // in the memory map wherever the MCFG ACPI table points to.
+    //
+    // This appears to be a safety measure. The PCI Firmware Specification
+    // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
+    // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
+    // [...]". (Emphasis added here.)
+    //
+    // Normally we add memory resource descriptor HOBs in
+    // QemuInitializeRam(), and pre-allocate from those with memory
+    // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
+    // is most definitely not RAM; so, as an exception, cover it with
+    // uncacheable reserved memory right here.
+    //
+      AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
+      BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
+        EfiReservedMemoryType);
+  }
+  AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
+
+  // Add PCI IO Port space available for PCI resource allocations.
+  //
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_IO,
+    EFI_RESOURCE_ATTRIBUTE_PRESENT     |
+    EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
+    PciIoBase,
+    PciIoSize
+    );
+  PcdSet64 (PcdPciIoBase, PciIoBase);
+  PcdSet64 (PcdPciIoSize, PciIoSize);
+
+  //
+  // Add flash range.
+  //
+  AddFlashDeviceRange (PcdGet32(PcdFlashAreaBaseAddress), PcdGet32(PcdFlashAreaSize));
+  //
+  // Video memory / ABSEG
+  //
+  AddIoMemoryBaseSizeHob (0x0A0000, 0x20000);
+  //
+  // Legacy BIOS region.
+  //
+  AddReservedMemoryBaseSizeHob (0xC0000, 0x40000, TRUE);
+}
+
+VOID
+MiscInitialization (
+  VOID
+  )
+{
+  UINTN         PmCmd;
+  UINTN         Pmba;
+  UINT32        PmbaAndVal;
+  UINT32        PmbaOrVal;
+  UINTN         AcpiCtlReg;
+  UINT8         AcpiEnBit;
+
+  //
+  // Disable A20 Mask
+  //
+  IoOr8 (0x92, BIT1);
+
+  //
+  // Build the CPU HOB with guest RAM size dependent address width and 16-bits
+  // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
+  // S3 resume as well, so we build it unconditionally.)
+  //
+  BuildCpuHob (mPhysMemAddressWidth, 16);
+
+  //
+  // Determine platform type and save Host Bridge DID to PCD
+  //
+  switch (mHostBridgeDevId) {
+    case INTEL_82441_DEVICE_ID:
+      PmCmd      = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
+      Pmba       = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+      PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
+      PmbaOrVal  = PIIX4_PMBA_VALUE;
+      AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
+      AcpiEnBit  = PIIX4_PMREGMISC_PMIOSE;
+      break;
+    case INTEL_ICH10_DEVICE_ID:
+      PmCmd      = POWER_MGMT_REGISTER_ICH10 (PCI_COMMAND_OFFSET);
+      Pmba       = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
+      PmbaAndVal = ~(UINT32)ICH10_PMBASE_MASK;
+      PmbaOrVal  = ICH10_PMBASE_VALUE;
+      AcpiCtlReg = POWER_MGMT_REGISTER_ICH10 (ICH10_ACPI_CNTL);
+      AcpiEnBit  = ICH10_ACPI_CNTL_ACPI_EN;
+      break;
+    default:
+      DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+        __FUNCTION__, mHostBridgeDevId));
+      ASSERT (FALSE);
+      return;
+  }
+  PcdSet16 (PcdSimicsX58HostBridgePciDevId, mHostBridgeDevId);
+
+  //
+  // If the appropriate IOspace enable bit is set, assume the ACPI PMBA
+  // has been configured and skip the setup here.
+  // This matches the logic in AcpiTimerLibConstructor ().
+  //
+  if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
+    //
+    // The PEI phase should be exited with fully accessibe ACPI PM IO space:
+    // 1. set PMBA
+    //
+    PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
+
+    //
+    // 2. set PCICMD/IOSE
+    //
+    PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
+
+    //
+    // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
+    //
+    PciOr8 (AcpiCtlReg, AcpiEnBit);
+  }
+
+  if (mHostBridgeDevId == INTEL_ICH10_DEVICE_ID) {
+    //
+    // Set Root Complex Register Block BAR
+    //
+    PciWrite32 (
+      POWER_MGMT_REGISTER_ICH10 (ICH10_RCBA),
+      ICH10_ROOT_COMPLEX_BASE | ICH10_RCBA_EN
+      );
+
+  }
+  //
+  // Set the PM I/O base address to 0x400
+  //
+  PciAndThenOr32 (
+    PCI_LIB_ADDRESS (
+      0,
+      31,
+      0,
+      0x40
+      ),
+    (UINT32) ~0xfc0, ICH10_PMBASE_VALUE
+    );
+  //
+  // Enable AHCI and all ports on the SATA controller.
+  //
+  // Address MAP Reg, setting AHCI mode
+  //
+  PciOr16 (PCI_LIB_ADDRESS (0, 31, 2, 0x90), 0x0060);
+  //
+  //Enabling Ports 0-5
+  //
+  PciOr16 (PCI_LIB_ADDRESS (0, 31, 2, 0x92), 0x003F);
+  //
+  //Disabling Sata Controller 2, bit 25 = 1, bit 0 = 1
+  //
+  MmioWrite32(0xFED1F418, 0x02000001);
+  //
+  //Enable HPET at FED0_0000h – FED0_03FFh
+  //
+  MmioWrite8(ICH10_ROOT_COMPLEX_BASE + 0x3404, 0x80);
+  //
+  //Config and enable APIC
+  //
+  MmioWrite32(0xFEC00000 + 0X0, 0);
+  MmioWrite32(0xFEC00000 + 0X10, PcdGet8(PcdIoApicId)<<24);
+  MmioWrite8(ICH10_ROOT_COMPLEX_BASE + 0x31FF, 0x01);
+}
+
+
+VOID
+BootModeInitialization (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+
+ DEBUG((EFI_D_INFO, "modeValue = %x\n", IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12)));
+  if (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) == 0x5) {
+    mBootMode = BOOT_ON_S3_RESUME;
+  }
+
+  Status = PeiServicesSetBootMode (mBootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PeiServicesInstallPpi (mPpiBootMode);
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+VOID
+ReserveEmuVariableNvStore (
+  )
+{
+  EFI_PHYSICAL_ADDRESS VariableStore;
+
+  //
+  // Allocate storage for NV variables early on so it will be
+  // at a consistent address.  Since VM memory is preserved
+  // across reboots, this allows the NV variable storage to survive
+  // a VM reboot.
+  //
+  VariableStore =
+    (EFI_PHYSICAL_ADDRESS)(UINTN)
+      AllocateRuntimePages (
+        EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
+        );
+  DEBUG ((EFI_D_INFO,
+          "Reserved variable store memory: 0x%lX; size: %dkb\n",
+          VariableStore,
+          (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
+        ));
+  PcdSet64 (PcdEmuVariableNvStoreReserved, VariableStore);
+}
+
+
+VOID
+SimicsVersionCheck(
+  VOID
+  )
+{
+
+  UINTN           PciAddrPtr;
+  UINT8           CapOffset;
+  STATIC CHAR8    SimicsStr[0x100];
+  UINTN           i;
+  UINT32          MajorVersion;
+  UINT32          MinorVersion;
+  UINT32          ModelNumber;
+
+  PciAddrPtr = PCI_LIB_ADDRESS(0, SIMICS_SIDEBANDPCI_DEV, SIMICS_SIDEBANDPCI_FUNC, 0);
+  CapOffset = PciRead8(PciAddrPtr + PCI_CAPBILITY_POINTER_OFFSET);
+  if (CapOffset != 0xFF) {
+    ModelNumber = PciRead32(PciAddrPtr + CapOffset + 4);
+    MajorVersion = PciRead32(PciAddrPtr + CapOffset + 8);
+    MinorVersion = PciRead32(PciAddrPtr + CapOffset + 0xc);
+    for (i = 0; i < 0x80; i++) {
+      SimicsStr[i] = PciRead8(PciAddrPtr + CapOffset + 0x10 + i);
+    }
+    DEBUG((EFI_D_INFO, "=============SIMICS Version info=============\n"));
+    DEBUG((EFI_D_INFO, "Model number = %d\n", ModelNumber));
+    DEBUG((EFI_D_INFO, "Major version = %d\n", MajorVersion));
+    DEBUG((EFI_D_INFO, "Minor version = %d\n", MinorVersion));
+    DEBUG((EFI_D_INFO, "%a\n", SimicsStr));
+    DEBUG((EFI_D_INFO, "=============================================\n"));
+  }
+}
+
+VOID
+DebugDumpCmos (
+  VOID
+  )
+{
+  UINT32 Loop;
+
+  DEBUG ((EFI_D_INFO, "CMOS:\n"));
+
+  for (Loop = 0; Loop < 0x80; Loop++) {
+    if ((Loop % 0x10) == 0) {
+      DEBUG ((EFI_D_INFO, "%02x:", Loop));
+    }
+    DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));
+    if ((Loop % 0x10) == 0xf) {
+      DEBUG ((EFI_D_INFO, "\n"));
+    }
+  }
+}
+
+
+/**
+  Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules.
+  Set the mMaxCpuCount variable.
+**/
+VOID
+MaxCpuCountInitialization (
+  VOID
+  )
+{
+  mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+  return;
+}
+
+/**
+  Determine if S3 support is explicitly enabled.
+
+  @retval  TRUE   If S3 support is explicitly enabled. Other functions in this
+  library may be called (subject to their individual
+  restrictions).
+
+  FALSE  Otherwise. This includes unavailability of the firmware
+  configuration interface. No other function in this library
+  must be called.
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgS3Enabled(
+  VOID
+)
+{
+  //TO DO IF NEEDED
+  return TRUE;
+}
+
+/**
+  Perform Platform PEI initialization.
+
+  @param  FileHandle      Handle of the file being invoked.
+  @param  PeiServices     Describes the list of possible PEI Services.
+
+  @return EFI_SUCCESS     The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatform (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS    Status;
+
+  DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n"));
+
+  SimicsVersionCheck ();
+  DebugDumpCmos ();
+
+  if (QemuFwCfgS3Enabled ()) {
+    DEBUG ((EFI_D_INFO, "S3 support was detected on SIMICS\n"));
+    mS3Supported = TRUE;
+    Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
+    ASSERT_EFI_ERROR (Status);
+  }
+  AddressWidthInitialization ();
+  MaxCpuCountInitialization ();
+
+  mHostBridgeDevId = PciRead16(SIMICS_HOSTBRIDGE_DID);
+
+  if (FeaturePcdGet (PcdSmmSmramRequire)) {
+    X58TsegMbytesInitialization ();
+  }
+
+  PublishPeiMemory ();
+
+  InitializeRamRegions ();
+
+  if (mBootMode != BOOT_ON_S3_RESUME) {
+    if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+      ReserveEmuVariableNvStore ();
+    }
+    MemMapInitialization ();
+  }
+
+  MiscInitialization ();
+  InstallFeatureControlCallback ();
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
new file mode 100644
index 0000000000..7165c0a0c3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
@@ -0,0 +1,148 @@
+/** @file
+  This driver installs SMBIOS information for QSP
+
+  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+  Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SmbiosPlatformDxe.h"
+
+
+/**
+Reads 8-bits of CMOS data.
+
+Reads the 8-bits of CMOS data at the location specified by Index.
+The 8-bit read value is returned.
+
+@param  Index  The CMOS location to read.
+
+@return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8(
+  IN      UINTN                     Index
+  )
+{
+  IoWrite8(0x70, (UINT8)Index);
+  return IoRead8(0x71);
+}
+
+UINT32
+GetSystemMemorySizeBelow4gb(
+  VOID
+  )
+{
+  UINT8 Cmos0x34;
+  UINT8 Cmos0x35;
+
+  //
+  // CMOS 0x34/0x35 specifies the system memory above 16 MB.
+  // * CMOS(0x35) is the high byte
+  // * CMOS(0x34) is the low byte
+  // * The size is specified in 64kb chunks
+  // * Since this is memory above 16MB, the 16MB must be added
+  //   into the calculation to get the total memory size.
+  //
+
+  Cmos0x34 = (UINT8)CmosRead8(0x34);
+  Cmos0x35 = (UINT8)CmosRead8(0x35);
+
+  return (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+}
+
+STATIC
+UINT64
+GetSystemMemorySizeAbove4gb(
+  VOID
+)
+{
+  UINT32 Size;
+  UINTN  CmosIndex;
+
+  //
+  // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
+  // * CMOS(0x5d) is the most significant size byte
+  // * CMOS(0x5c) is the middle size byte
+  // * CMOS(0x5b) is the least significant size byte
+  // * The size is specified in 64kb chunks
+  //
+
+  Size = 0;
+  for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+    Size = (UINT32)(Size << 8) + (UINT32)CmosRead8(CmosIndex);
+  }
+
+  return LShiftU64(Size, 16);
+}
+
+/**
+  Installs SMBIOS information for SIMICS QSP
+
+  @param ImageHandle     Module's image handle
+  @param SystemTable     Pointer of EFI_SYSTEM_TABLE
+
+  @retval EFI_SUCCESS    Smbios data successfully installed
+  @retval Other          Smbios data was not installed
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosTablePublishEntry (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  EFI_SMBIOS_PROTOCOL       *Smbios;
+  SMBIOS_TABLE_TYPE19       *Type19Record;
+  EFI_SMBIOS_HANDLE         MemArrayMappedAddrSmbiosHandle;
+  UINT8                     NumSlots;
+  UINT64                    TotalMemorySize;
+
+  //
+  // Find the SMBIOS protocol
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiSmbiosProtocolGuid,
+                  NULL,
+                  (VOID**)&Smbios
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Generate Memory Array Mapped Address info
+  //
+  NumSlots = 2;
+  TotalMemorySize = 0;
+  TotalMemorySize = GetSystemMemorySizeBelow4gb();
+  Type19Record = AllocatePool(sizeof(SMBIOS_TABLE_TYPE19));
+  ZeroMem(Type19Record, sizeof(SMBIOS_TABLE_TYPE19));
+  Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
+  Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);
+  Type19Record->Hdr.Handle = 0;
+  Type19Record->StartingAddress = 0;
+  Type19Record->EndingAddress = (UINT32)RShiftU64(TotalMemorySize, 10) - 1;
+  Type19Record->MemoryArrayHandle = SMBIOS_HANDLE_PI_RESERVED;
+  Type19Record->PartitionWidth = (UINT8)(NumSlots);
+
+  MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+  Status = Smbios->Add(Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*)Type19Record);
+  ASSERT_EFI_ERROR(Status);
+
+  TotalMemorySize = GetSystemMemorySizeAbove4gb();
+  Type19Record->StartingAddress = 0xFFFFFFFF;
+  Type19Record->ExtendedStartingAddress = 0xFFFFFFFF;
+  Type19Record->ExtendedEndingAddress = TotalMemorySize + 0xFFFFFFFF - 1;
+
+  MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+  Status = Smbios->Add(Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*)Type19Record);
+  FreePool(Type19Record);
+  ASSERT_EFI_ERROR(Status);
+
+  return Status;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h b/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
new file mode 100644
index 0000000000..acb2c4eee4
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
@@ -0,0 +1,18 @@
+/** @file
+  GUID for UEFI variables that are specific to Simics Board configuration.
+
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SIMICS_BOARD_CONFIG_H__
+#define __SIMICS_BOARD_CONFIG_H__
+
+#define SIMICS_BOARD_CONFIG_GUID \
+{0x8a318e00, 0xfaf5, 0x499f, { 0x91,0x75, 0xce, 0x4d, 0x8d, 0xa6, 0x70, 0xae}}
+
+extern EFI_GUID gSimicsBoardConfigGuid;
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
new file mode 100644
index 0000000000..a2225493f7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
@@ -0,0 +1,50 @@
+/** @file
+  Various register numbers and value bits based on the following publications:
+  - Intel(R) datasheet 290549-001
+  - Intel(R) datasheet 290562-001
+  - Intel(R) datasheet 297654-006
+  - Intel(R) datasheet 297738-017
+
+  Copyright (C) 2015, Red Hat, Inc.
+  Copyright (c) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __I440FX_PIIX4_H__
+#define __I440FX_PIIX4_H__
+
+#include <Library/PciLib.h>
+
+//
+// Host Bridge Device ID (DID) value for I440FX
+//
+#define INTEL_82441_DEVICE_ID 0x1237
+
+//
+// B/D/F/Type: 0/0/0/PCI
+//
+#define PMC_REGISTER_PIIX4(Offset) PCI_LIB_ADDRESS (0, 0, 0, (Offset))
+
+#define PIIX4_PAM0              0x59
+#define PIIX4_PAM1              0x5A
+#define PIIX4_PAM2              0x5B
+#define PIIX4_PAM3              0x5C
+#define PIIX4_PAM4              0x5D
+#define PIIX4_PAM5              0x5E
+#define PIIX4_PAM6              0x5F
+
+//
+// B/D/F/Type: 0/1/3/PCI
+//
+#define POWER_MGMT_REGISTER_PIIX4(Offset) PCI_LIB_ADDRESS (0, 1, 3, (Offset))
+
+#define PIIX4_PMBA             0x40
+#define PIIX4_PMBA_MASK          (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | \
+                                  BIT10 | BIT9  | BIT8  | BIT7  | BIT6)
+
+#define PIIX4_PMREGMISC        0x80
+#define PIIX4_PMREGMISC_PMIOSE   BIT0
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
new file mode 100644
index 0000000000..2708b1891d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
@@ -0,0 +1,159 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LINUX_BZIMAGE_H__
+#define __LINUX_BZIMAGE_H__
+
+#define BOOTSIG         0x1FE
+#define SETUP_HDR       0x53726448  /* 0x53726448 == "HdrS" */
+
+#define E820_RAM        1
+#define E820_RESERVED   2
+#define E820_ACPI       3
+#define E820_NVS        4
+#define E820_UNUSABLE   5
+
+#pragma pack(1)
+
+struct setup_header {
+  UINT8 setup_secs;  /* Sectors for setup code */
+  UINT16 root_flags;
+  UINT32 sys_size;
+  UINT16 ram_size;
+  UINT16 video_mode;
+  UINT16 root_dev;
+  UINT16 signature;  /* Boot signature */
+  UINT16 jump;
+  UINT32 header;
+  UINT16 version;
+  UINT16 su_switch;
+  UINT16 setup_seg;
+  UINT16 start_sys;
+  UINT16 kernel_ver;
+  UINT8 loader_id;
+  UINT8 load_flags;
+  UINT16 movesize;
+  UINT32 code32_start;  /* Start of code loaded high */
+  UINT32 ramdisk_start;  /* Start of initial ramdisk */
+  UINT32 ramdisk_len;  /* Length of initial ramdisk */
+  UINT32 bootsect_kludge;
+  UINT16 heap_end;
+  UINT8 ext_loader_ver;  /* Extended boot loader version */
+  UINT8 ext_loader_type; /* Extended boot loader ID */
+  UINT32 cmd_line_ptr;   /* 32-bit pointer to the kernel command line */
+  UINT32 ramdisk_max;    /* Highest legal initrd address */
+  UINT32 kernel_alignment;  /* Physical addr alignment required for kernel */
+  UINT8 relocatable_kernel;  /* Whether kernel is relocatable or not */
+  UINT8 min_alignment;
+  UINT16 xloadflags;
+  UINT32 cmdline_size;
+  UINT32 hardware_subarch;
+  UINT64 hardware_subarch_data;
+  UINT32 payload_offset;
+  UINT32 payload_length;
+  UINT64 setup_data;
+  UINT64 pref_address;
+  UINT32 init_size;
+  UINT32 handover_offset;
+};
+
+struct efi_info {
+  UINT32 efi_loader_signature;
+  UINT32 efi_systab;
+  UINT32 efi_memdesc_size;
+  UINT32 efi_memdesc_version;
+  UINT32 efi_memmap;
+  UINT32 efi_memmap_size;
+  UINT32 efi_systab_hi;
+  UINT32 efi_memmap_hi;
+};
+
+struct e820_entry {
+  UINT64 addr;  /* start of memory segment */
+  UINT64 size;  /* size of memory segment */
+  UINT32 type;  /* type of memory segment */
+};
+
+struct screen_info {
+        UINT8  orig_x;           /* 0x00 */
+        UINT8  orig_y;           /* 0x01 */
+        UINT16 ext_mem_k;        /* 0x02 */
+        UINT16 orig_video_page;  /* 0x04 */
+        UINT8  orig_video_mode;  /* 0x06 */
+        UINT8  orig_video_cols;  /* 0x07 */
+        UINT8  flags;            /* 0x08 */
+        UINT8  unused2;          /* 0x09 */
+        UINT16 orig_video_ega_bx;/* 0x0a */
+        UINT16 unused3;          /* 0x0c */
+        UINT8  orig_video_lines; /* 0x0e */
+        UINT8  orig_video_isVGA; /* 0x0f */
+        UINT16 orig_video_points;/* 0x10 */
+
+  /* VESA graphic mode -- linear frame buffer */
+        UINT16 lfb_width;        /* 0x12 */
+        UINT16 lfb_height;       /* 0x14 */
+        UINT16 lfb_depth;        /* 0x16 */
+        UINT32 lfb_base;         /* 0x18 */
+        UINT32 lfb_size;         /* 0x1c */
+        UINT16 cl_magic, cl_offset; /* 0x20 */
+        UINT16 lfb_linelength;   /* 0x24 */
+        UINT8  red_size;         /* 0x26 */
+        UINT8  red_pos;          /* 0x27 */
+        UINT8  green_size;       /* 0x28 */
+        UINT8  green_pos;        /* 0x29 */
+        UINT8  blue_size;        /* 0x2a */
+        UINT8  blue_pos;         /* 0x2b */
+        UINT8  rsvd_size;        /* 0x2c */
+        UINT8  rsvd_pos;         /* 0x2d */
+        UINT16 vesapm_seg;       /* 0x2e */
+        UINT16 vesapm_off;       /* 0x30 */
+        UINT16 pages;            /* 0x32 */
+        UINT16 vesa_attributes;  /* 0x34 */
+        UINT32 capabilities;     /* 0x36 */
+        UINT8  _reserved[6];     /* 0x3a */
+};
+
+struct boot_params {
+struct screen_info screen_info;
+  UINT8 apm_bios_info[0x14];
+  UINT8 _pad2[4];
+  UINT64 tboot_addr;
+  UINT8 ist_info[0x10];
+  UINT8 _pad3[16];
+  UINT8 hd0_info[16];
+  UINT8 hd1_info[16];
+  UINT8 sys_desc_table[0x10];
+  UINT8 olpc_ofw_header[0x10];
+  UINT8 _pad4[128];
+  UINT8 edid_info[0x80];
+  struct efi_info efi_info;
+  UINT32 alt_mem_k;
+  UINT32 scratch;
+  UINT8 e820_entries;
+  UINT8 eddbuf_entries;
+  UINT8 edd_mbr_sig_buf_entries;
+  UINT8 _pad6[6];
+  struct setup_header hdr;
+  UINT8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+  UINT32 edd_mbr_sig_buffer[16];
+  struct e820_entry e820_map[128];
+  UINT8 _pad8[48];
+  UINT8 eddbuf[0x1ec];
+  UINT8 _pad9[276];
+};
+
+typedef struct {
+  UINT16 limit;
+  UINT64 *base;
+} dt_addr_t;
+
+#pragma pack()
+
+extern EFI_STATUS setup_graphics(struct boot_params *buf);
+
+#endif /* __LINUX_BZIMAGE_H__ */
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
new file mode 100644
index 0000000000..483f8d4b9c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
@@ -0,0 +1,205 @@
+/** @file
+  Load/boot UEFI Linux.
+
+  Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LOAD_LINUX_LIB__
+#define __LOAD_LINUX_LIB__
+
+
+/**
+  Verifies that the kernel setup image is valid and supported.
+  The kernel setup image should be checked before using other library
+  routines which take the kernel setup as an input.
+
+  @param[in]     KernelSetup - The kernel setup image
+  @param[in]     KernelSetupSize - The kernel setup size
+
+  @retval    EFI_SUCCESS - The Linux kernel setup is valid and supported
+  @retval    EFI_INVALID_PARAMETER - KernelSetup was NULL
+  @retval    EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxCheckKernelSetup (
+  IN VOID        *KernelSetup,
+  IN UINTN       KernelSetupSize
+  );
+
+
+/**
+  Gets the initial runtime size of the Linux kernel image by examining
+  the kernel setup image.
+
+  @param[in]     KernelSetup - The kernel setup image
+  @param[in]     KernelSize - The kernel size on disk.
+
+  @retval    0                An error occurred
+  @retval    !0               The initial size required by the kernel to
+                              begin execution.
+
+**/
+UINTN
+EFIAPI
+LoadLinuxGetKernelSize (
+  IN VOID        *KernelSetup,
+  IN UINTN       KernelSize
+  );
+
+
+/**
+  Loads and boots UEFI Linux.
+
+  Note: If successful, then this routine will not return
+
+  @param[in]     Kernel - The main kernel image
+  @param[in,out] KernelSetup - The kernel setup image
+
+  @retval    EFI_NOT_FOUND - The Linux kernel was not found
+  @retval    EFI_INVALID_PARAMETER - Kernel or KernelSetup was NULL
+  @retval    EFI_UNSUPPORTED - The Linux kernel version is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinux (
+  IN VOID      *Kernel,
+  IN OUT VOID  *KernelSetup
+  );
+
+
+/**
+  Allocates pages for the kernel setup image.
+
+  @param[in]     Pages - The number of pages
+
+  @retval    NULL - Unable to allocate pages
+  @retval    !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelSetupPages (
+  IN UINTN                  Pages
+  );
+
+
+/**
+  Clears the uninitialised space before and after the struct setup_header
+  in the kernel setup image. The kernel requires that these be zeroed
+  unless explicitly initialised, so this function should be called after
+  the setup_header has been copied in from a bzImage, before setting up
+  anything else.
+
+  @param[in]     KernelSetup - The kernel setup image
+
+  @retval    EFI_SUCCESS - The Linux kernel setup was successfully initialized
+  @retval    EFI_INVALID_PARAMETER - KernelSetup was NULL
+  @retval    EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxInitializeKernelSetup (
+  IN VOID        *KernelSetup
+  );
+
+/**
+  Allocates pages for the kernel.
+
+  @param[in]     KernelSetup - The kernel setup image
+  @param[in]     Pages - The number of pages. (It is recommended to use the
+                         size returned from LoadLinuxGetKernelSize.)
+
+  @retval    NULL - Unable to allocate pages
+  @retval    !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelPages (
+  IN VOID                   *KernelSetup,
+  IN UINTN                  Pages
+  );
+
+
+/**
+  Allocates pages for the kernel command line.
+
+  @param[in]     Pages - The number of pages.
+
+  @retval    NULL - Unable to allocate pages
+  @retval    !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateCommandLinePages (
+  IN UINTN                  Pages
+  );
+
+
+/**
+  Allocates pages for the initrd image.
+
+  @param[in,out] KernelSetup - The kernel setup image
+  @param[in]     Pages - The number of pages.
+
+  @retval    NULL - Unable to allocate pages
+  @retval    !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateInitrdPages (
+  IN VOID                   *KernelSetup,
+  IN UINTN                  Pages
+  );
+
+
+/**
+  Sets the kernel command line parameter within the setup image.
+
+  @param[in,out] KernelSetup - The kernel setup image
+  @param[in]     CommandLine - The kernel command line
+
+  @retval    EFI_SUCCESS - The Linux kernel setup is valid and supported
+  @retval    EFI_INVALID_PARAMETER - KernelSetup was NULL
+  @retval    EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxSetCommandLine (
+  IN OUT VOID    *KernelSetup,
+  IN CHAR8       *CommandLine
+  );
+
+
+/**
+  Sets the kernel initial ram disk pointer within the setup image.
+
+  @param[in,out] KernelSetup - The kernel setup image
+  @param[in]     Initrd - Pointer to the initial ram disk
+  @param[in]     InitrdSize - The initial ram disk image size
+
+  @retval    EFI_SUCCESS - The Linux kernel setup is valid and supported
+  @retval    EFI_INVALID_PARAMETER - KernelSetup was NULL
+  @retval    EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxSetInitrd (
+  IN OUT VOID    *KernelSetup,
+  IN VOID        *Initrd,
+  IN UINTN       InitrdSize
+  );
+
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
new file mode 100644
index 0000000000..c32f97d787
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
@@ -0,0 +1,224 @@
+/** @file
+  Serialize & Deserialize UEFI Variables
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __SERIALIZE_VARIABLES_LIB__
+#define __SERIALIZE_VARIABLES_LIB__
+
+
+/**
+  Callback function for each variable
+
+  @param[in] Context - Context as sent to the iteration function
+  @param[in] VariableName - Refer to RuntimeServices GetNextVariableName
+  @param[in] VendorGuid - Refer to RuntimeServices GetNextVariableName
+  @param[in] Attributes - Refer to RuntimeServices GetVariable
+  @param[in] DataSize - Refer to RuntimeServices GetVariable
+  @param[in] Data - Refer to RuntimeServices GetVariable
+
+  @retval RETURN_SUCCESS         Continue iterating through the variables
+  @return Any RETURN_ERROR       Stop iterating through the variables
+
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *VARIABLE_SERIALIZATION_ITERATION_CALLBACK)(
+  IN  VOID                         *Context,
+  IN  CHAR16                       *VariableName,
+  IN  EFI_GUID                     *VendorGuid,
+  IN  UINT32                       Attributes,
+  IN  UINTN                        DataSize,
+  IN  VOID                         *Data
+  );
+
+
+/**
+  Creates a new variable serialization instance
+
+  @param[out]  Handle - Handle for a variable serialization instance
+
+  @retval      RETURN_SUCCESS - The variable serialization instance was
+                 successfully created.
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 create the variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstance (
+  OUT EFI_HANDLE                      *Handle
+  );
+
+
+/**
+  Free memory associated with a variable serialization instance
+
+  @param[in]  Handle - Handle for a variable serialization instance
+
+  @retval      RETURN_SUCCESS - The variable serialization instance was
+                 successfully freed.
+  @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
+                 variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesFreeInstance (
+  IN EFI_HANDLE Handle
+  );
+
+
+/**
+  Creates a new variable serialization instance using the given
+  binary representation of the variables to fill the new instance
+
+  @param[out] Handle - Handle for a variable serialization instance
+  @param[in]  Buffer - A buffer with the serialized representation
+                of the variables.  Must be the same format as produced
+                by SerializeVariablesToBuffer.
+  @param[in]  Size - This is the size of the binary representation
+                of the variables.
+
+  @retval      RETURN_SUCCESS - The binary representation was successfully
+                 imported into a new variable serialization instance
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 create the new variable serialization instance
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstanceFromBuffer (
+  OUT EFI_HANDLE                          *Handle,
+  IN  VOID                                *Buffer,
+  IN  UINTN                               Size
+  );
+
+
+/**
+  Iterates all variables found with RuntimeServices GetNextVariableName
+
+  @param[in]   CallbackFunction - Function called for each variable instance
+  @param[in]   Context - Passed to each call of CallbackFunction
+
+  @retval      RETURN_SUCCESS - All variables were iterated without the
+                 CallbackFunction returning an error
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 iterate through the variables
+  @return      Any of RETURN_ERROR indicates an error reading the variable
+                 or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateSystemVariables (
+  IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+  IN VOID                                      *Context
+  );
+
+
+/**
+  Iterates all variables found in the variable serialization instance
+
+  @param[in]   Handle - Handle for a variable serialization instance
+  @param[in]   CallbackFunction - Function called for each variable instance
+  @param[in]   Context - Passed to each call of CallbackFunction
+
+  @retval      RETURN_SUCCESS - All variables were iterated without the
+                 CallbackFunction returning an error
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 iterate through the variables
+  @return      Any of RETURN_ERROR indicates an error reading the variable
+                 or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateInstanceVariables (
+  IN EFI_HANDLE                                Handle,
+  IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+  IN VOID                                      *Context
+  );
+
+
+/**
+  Sets all variables found in the variable serialization instance
+
+  @param[in]   Handle - Handle for a variable serialization instance
+
+  @retval      RETURN_SUCCESS - All variables were set successfully
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 set all the variables
+  @return      Any of RETURN_ERROR indicates an error reading the variables
+                 or in attempting to set a variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesSetSerializedVariables (
+  IN EFI_HANDLE                       Handle
+  );
+
+
+/**
+  Adds a variable to the variable serialization instance
+
+  @param[in] Handle - Handle for a variable serialization instance
+  @param[in] VariableName - Refer to RuntimeServices GetVariable
+  @param[in] VendorGuid - Refer to RuntimeServices GetVariable
+  @param[in] Attributes - Refer to RuntimeServices GetVariable
+  @param[in] DataSize - Refer to RuntimeServices GetVariable
+  @param[in] Data - Refer to RuntimeServices GetVariable
+
+  @retval      RETURN_SUCCESS - All variables were set successfully
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 add the variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesAddVariable (
+  IN EFI_HANDLE                   Handle,
+  IN CHAR16                       *VariableName,
+  IN EFI_GUID                     *VendorGuid,
+  IN UINT32                       Attributes,
+  IN UINTN                        DataSize,
+  IN VOID                         *Data
+  );
+
+
+/**
+  Serializes the variables known to this instance into the
+  provided buffer.
+
+  @param[in]     Handle - Handle for a variable serialization instance
+  @param[out]    Buffer - A buffer to store the binary representation
+                   of the variables.
+  @param[in,out] Size - On input this is the size of the buffer.
+                   On output this is the size of the binary representation
+                   of the variables.
+
+  @retval      RETURN_SUCCESS - The binary representation was successfully
+                 completed and returned in the buffer.
+  @retval      RETURN_OUT_OF_RESOURCES - There we not enough resources to
+                 save the variables to the buffer.
+  @retval      RETURN_INVALID_PARAMETER - Handle was not a valid
+                 variable serialization instance or
+                 Size or Buffer were NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesToBuffer (
+  IN     EFI_HANDLE                       Handle,
+  OUT    VOID                             *Buffer,
+  IN OUT UINTN                            *Size
+  );
+
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h b/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
new file mode 100644
index 0000000000..67bb3af584
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
@@ -0,0 +1,55 @@
+/** @file
+  Simics Platform definitions
+
+  Copyright (C) 2015, Red Hat, Inc.
+  Copyright (c) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SIMICS_PLATFORMS_H__
+#define __SIMICS_PLATFORMS_H__
+
+#include <Library/PciLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <Register/X58Ich10.h>
+#include <IndustryStandard/I440FxPiix4.h>
+
+//
+// Simics Host Bridge DID Address
+//
+#define SIMICS_HOSTBRIDGE_DID \
+  PCI_LIB_ADDRESS (0, 0, 0, PCI_DEVICE_ID_OFFSET)
+
+//
+// Simics SideBand PCI device registers
+//
+#define SIMICS_SIDEBANDPCI_DEV  0
+#define SIMICS_SIDEBANDPCI_FUNC 7
+#define SIMICS_SIDEBANDPCI_SVID \
+  PCI_LIB_ADDRESS (0, 0, 7, PCI_SVID_OFFSET)
+#define SIMICS_SIDEBANDPCI_SDID \
+  PCI_LIB_ADDRESS (0, 0, 7, PCI_SID_OFFSET)
+#define SIMICS_SIDEBANDPCI_CAP \
+  PCI_LIB_ADDRESS (0, 0, 7, PCI_CAPBILITY_POINTER_OFFSET)
+#define SIMICS_SIDEBANDPCI_CAP_Offset 0x40
+#define SIMICS_SIDEBANDPCI_CAP_ID     0xFF
+
+//
+// Values we program into the PM base address registers
+//
+#define PIIX4_PMBA_VALUE  0xB000
+#define ICH10_PMBASE_VALUE 0x0400
+
+//
+// Common bits in same-purpose registers
+//
+#define PMBA_RTE BIT0
+
+//
+// Common IO ports relative to the Power Management Base Address
+//
+#define ACPI_TIMER_OFFSET 0x8
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
new file mode 100644
index 0000000000..ff08c385b3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
@@ -0,0 +1,55 @@
+### @file
+# Module that show progress bar and title above it.
+#
+# General BDS defines and produce general interfaces for platform BDS driver including:
+# 1) BDS boot policy interface;
+# 2) BDS boot device connect interface;
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.
+#
+# Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = DxeLogoLib
+  FILE_GUID                      = F5AE5B5C-42E8-4A9B-829D-5B631CD5367A
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = DXE_DRIVER
+  LIBRARY_CLASS                  = LogoLib|DXE_DRIVER UEFI_APPLICATION
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+  BaseLib
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  UefiLib
+  BaseMemoryLib
+  DebugLib
+  PrintLib
+  PcdLib
+  DxeServicesLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+
+[FeaturePcd]
+  gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
+
+[Sources]
+  Logo.c
+
+[Protocols]
+  gEfiGraphicsOutputProtocolGuid                ## SOMETIMES_CONSUMES
+  gEfiUgaDrawProtocolGuid                       ## SOMETIMES_CONSUMES
+  gEfiBootLogoProtocolGuid                      ## SOMETIMES_CONSUMES
+  gEfiUserManagerProtocolGuid                   ## CONSUMES
+  gEfiOemBadgingProtocolGuid                    ## CONSUMES
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
new file mode 100644
index 0000000000..d2c39c3dfc
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
@@ -0,0 +1,83 @@
+/** @file
+  The OEM Badging Protocol defines the interface to get the OEM badging
+  image with the display attribute. This protocol can be produced based on OEM badging images.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EFI_OEM_BADGING_H__
+#define __EFI_OEM_BADGING_H__
+
+//
+// GUID for EFI OEM Badging Protocol
+//
+#define EFI_OEM_BADGING_PROTOCOL_GUID \
+  { 0x170e13c0, 0xbf1b, 0x4218, {0x87, 0x1d, 0x2a, 0xbd, 0xc6, 0xf8, 0x87, 0xbc } }
+
+
+typedef struct _EFI_OEM_BADGING_PROTOCOL EFI_OEM_BADGING_PROTOCOL;
+
+typedef enum {
+  EfiBadgingFormatBMP,
+  EfiBadgingFormatJPEG,
+  EfiBadgingFormatTIFF,
+  EfiBadgingFormatGIF,
+  EfiBadgingFormatUnknown
+} EFI_BADGING_FORMAT;
+
+typedef enum {
+  EfiBadgingDisplayAttributeLeftTop,
+  EfiBadgingDisplayAttributeCenterTop,
+  EfiBadgingDisplayAttributeRightTop,
+  EfiBadgingDisplayAttributeCenterRight,
+  EfiBadgingDisplayAttributeRightBottom,
+  EfiBadgingDisplayAttributeCenterBottom,
+  EfiBadgingDisplayAttributeLeftBottom,
+  EfiBadgingDisplayAttributeCenterLeft,
+  EfiBadgingDisplayAttributeCenter,
+  EfiBadgingDisplayAttributeCustomized
+} EFI_BADGING_DISPLAY_ATTRIBUTE;
+
+/**
+
+  Load an OEM badge image and return its data and attributes.
+
+  @param This              The pointer to this protocol instance.
+  @param Instance          The visible image instance is found.
+  @param Format            The format of the image. Examples: BMP, JPEG.
+  @param ImageData         The image data for the badge file. Currently only
+                           supports the .bmp file format.
+  @param ImageSize         The size of the image returned.
+  @param Attribute         The display attributes of the image returned.
+  @param CoordinateX       The X coordinate of the image.
+  @param CoordinateY       The Y coordinate of the image.
+
+  @retval EFI_SUCCESS      The image was fetched successfully.
+  @retval EFI_NOT_FOUND    The specified image could not be found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BADGING_GET_IMAGE)(
+  IN     EFI_OEM_BADGING_PROTOCOL          *This,
+  IN OUT UINT32                            *Instance,
+     OUT EFI_BADGING_FORMAT                *Format,
+     OUT UINT8                             **ImageData,
+     OUT UINTN                             *ImageSize,
+     OUT EFI_BADGING_DISPLAY_ATTRIBUTE     *Attribute,
+     OUT UINTN                             *CoordinateX,
+     OUT UINTN                             *CoordinateY
+);
+
+
+struct _EFI_OEM_BADGING_PROTOCOL {
+  EFI_BADGING_GET_IMAGE       GetImage;
+};
+
+
+extern EFI_GUID gEfiOemBadgingProtocolGuid;
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
new file mode 100644
index 0000000000..cdefeebbdd
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
@@ -0,0 +1,42 @@
+## @file
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeLoadLinuxLib
+  FILE_GUID                      = 63CC8497-C9D0-46A8-AC08-49DF92A2FF62
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = DxeLoadLinuxLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.common]
+  Linux.c
+  LinuxGdt.c
+
+[Sources.IA32]
+  Ia32/JumpToKernel.nasm
+
+[Sources.X64]
+  X64/JumpToKernel.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  MemoryAllocationLib
+  BaseMemoryLib
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
new file mode 100644
index 0000000000..c6f1c31a59
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
@@ -0,0 +1,41 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+  SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToKernel (
+;   VOID *KernelStart,
+;   VOID *KernelBootParams
+;   );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToKernel)
+ASM_PFX(JumpToKernel):
+
+    mov     esi, [esp + 8]
+    call    DWORD [esp + 4]
+    ret
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToUefiKernel (
+;   EFI_HANDLE ImageHandle,
+;   EFI_SYSTEM_TABLE *SystemTable,
+;   VOID *KernelBootParams,
+;   VOID *KernelStart
+;   );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToUefiKernel)
+ASM_PFX(JumpToUefiKernel):
+
+    mov     eax, [esp + 12]
+    mov     eax, [eax + 0x264]
+    add     eax, [esp + 16]
+    jmp     eax
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
new file mode 100644
index 0000000000..9c0ab80904
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
@@ -0,0 +1,52 @@
+/** @file
+  Boot UEFI Linux.
+
+  Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _LOAD_LINUX_LIB_INCLUDED_
+#define _LOAD_LINUX_LIB_INCLUDED_
+
+#include <Uefi.h>
+#include <Library/LoadLinuxLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <IndustryStandard/LinuxBzImage.h>
+
+#include <Protocol/GraphicsOutput.h>
+
+VOID
+EFIAPI
+JumpToKernel (
+  VOID *KernelStart,
+  VOID *KernelBootParams
+  );
+
+VOID
+EFIAPI
+JumpToUefiKernel (
+  EFI_HANDLE ImageHandle,
+  EFI_SYSTEM_TABLE *SystemTable,
+  VOID *KernelBootParams,
+  VOID *KernelStart
+  );
+
+VOID
+InitLinuxDescriptorTables (
+  VOID
+  );
+
+VOID
+SetLinuxDescriptorTables (
+  VOID
+  );
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
new file mode 100644
index 0000000000..2b5395f6f8
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
@@ -0,0 +1,85 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+  DEFAULT REL
+  SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToKernel (
+;   VOID *KernelStart,         // rcx
+;   VOID *KernelBootParams     // rdx
+;   );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToKernel)
+ASM_PFX(JumpToKernel):
+
+    ; Set up for executing kernel. BP in %esi, entry point on the stack
+    ; (64-bit when the 'ret' will use it as 32-bit, but we're little-endian)
+    mov    rsi, rdx
+    push   rcx
+
+    ; Jump into the compatibility mode CS
+    push    0x10
+    lea     rax, [.0]
+    push    rax
+    DB 0x48, 0xcb                      ; retfq
+
+.0:
+    ; Now in compatibility mode.
+
+    DB 0xb8, 0x18, 0x0, 0x0, 0x0    ; movl    $0x18, %eax
+    DB 0x8e, 0xd8                      ; movl    %eax, %ds
+    DB 0x8e, 0xc0                      ; movl    %eax, %es
+    DB 0x8e, 0xe0                      ; movl    %eax, %fs
+    DB 0x8e, 0xe8                      ; movl    %eax, %gs
+    DB 0x8e, 0xd0                      ; movl    %eax, %ss
+
+    ; Disable paging
+    DB 0xf, 0x20, 0xc0                ; movl    %cr0, %eax
+    DB 0xf, 0xba, 0xf8, 0x1f          ; btcl    $31, %eax
+    DB 0xf, 0x22, 0xc0                ; movl    %eax, %cr0
+
+    ; Disable long mode in EFER
+    DB 0xb9, 0x80, 0x0, 0x0, 0xc0    ; movl    $0x0c0000080, %ecx
+    DB 0xf, 0x32                      ; rdmsr
+    DB 0xf, 0xba, 0xf8, 0x8          ; btcl    $8, %eax
+    DB 0xf, 0x30                      ; wrmsr
+
+    ; Disable PAE
+    DB 0xf, 0x20, 0xe0                ; movl    %cr4, %eax
+    DB 0xf, 0xba, 0xf8, 0x5          ; btcl    $5, %eax
+    DB 0xf, 0x22, 0xe0                ; movl    %eax, %cr4
+
+    DB 0x31, 0xed                      ; xor     %ebp, %ebp
+    DB 0x31, 0xff                      ; xor     %edi, %edi
+    DB 0x31, 0xdb                      ; xor     %ebx, %ebx
+    DB 0xc3                            ; ret
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToUefiKernel (
+;   EFI_HANDLE ImageHandle,        // rcx
+;   EFI_SYSTEM_TABLE *SystemTable, // rdx
+;   VOID *KernelBootParams         // r8
+;   VOID *KernelStart,             // r9
+;   );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToUefiKernel)
+ASM_PFX(JumpToUefiKernel):
+
+    mov     rdi, rcx
+    mov     rsi, rdx
+    mov     rdx, r8
+    xor     rax, rax
+    mov     eax, [r8 + 0x264]
+    add     r9, rax
+    add     r9, 0x200
+    call    r9
+    ret
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
new file mode 100644
index 0000000000..80776fd003
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
@@ -0,0 +1,55 @@
+/** @file
+  Save Non-Volatile Variables to a file system.
+
+  Copyright (c) 2009 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __NV_VARS_FILE_LIB_INSTANCE__
+#define __NV_VARS_FILE_LIB_INSTANCE__
+
+#include <Uefi.h>
+
+#include <Guid/FileInfo.h>
+
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Library/BaseLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/SerializeVariablesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+/**
+  Loads the non-volatile variables from the NvVars file on the
+  given file system.
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+  @return     EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+LoadNvVarsFromFs (
+  EFI_HANDLE                            FsHandle
+  );
+
+
+/**
+  Saves the non-volatile variables into the NvVars file on the
+  given file system.
+
+  @param[in]  FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+  @return     EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+SaveNvVarsToFs (
+  EFI_HANDLE                            FsHandle
+  );
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
new file mode 100644
index 0000000000..4731e77865
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
@@ -0,0 +1,53 @@
+## @file
+#  NvVarsFileLib
+#
+#  This library saves and restores non-volatile variables in a
+#  file within a file system.
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = NvVarsFileLib
+  FILE_GUID                      = 8ECD4CC0-1772-4583-8A74-83633A15FAA0
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NvVarsFileLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  FsAccess.c
+  NvVarsFileLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ShellPkg/ShellPkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  FileHandleLib
+  MemoryAllocationLib
+  SerializeVariablesLib
+
+[Protocols]
+  gEfiSimpleFileSystemProtocolGuid              ## CONSUMES
+
+[Guids]
+  gEfiFileInfoGuid
+
+[Depex]
+  gEfiVariableWriteArchProtocolGuid
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
new file mode 100644
index 0000000000..0c75430260
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
@@ -0,0 +1,68 @@
+/** @file
+  Header file of OVMF instance of PciHostBridgeLib.
+
+  Copyright (c) 2019 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/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 0000000000..e1920bd2ff
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,51 @@
+## @file
+#  Simics's instance of the PCI Host Bridge Library.
+#
+#  Copyright (C) 2016, Red Hat, Inc.
+#  Copyright (c) 2016 - 2019 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/OpenBoardPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  PciLib
+
+[Pcd]
+  gBoardModuleTokenSpaceGuid.PcdPciIoBase
+  gBoardModuleTokenSpaceGuid.PcdPciIoSize
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Base
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Size
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Base
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Size
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
new file mode 100644
index 0000000000..bc85420f97
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
@@ -0,0 +1,56 @@
+### @file
+# Component information file for the Report Firmware Volume (FV) library.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = PeiReportFvLib
+  FILE_GUID                      = 44328FA5-E4DD-4A15-ABDF-C6584AC363D9
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = PEIM
+  LIBRARY_CLASS                  = ReportFvLib
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  HobLib
+  PeiServicesLib
+  PcdLib
+  IoLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  SimicsX58SktPkg/SktPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[Sources]
+  PeiReportFvLib.c
+  Fv.c
+
+[Pcd]
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress     ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize            ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPostMemoryBase    ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPostMemorySize    ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvUefiBootBase      ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvUefiBootSize      ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvOsBootBase        ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvOsBootSize        ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvSecurityBase      ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvSecuritySize      ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvAdvancedBase      ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvAdvancedSize      ## CONSUMES
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000000..01ba20d2da
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,172 @@
+/** @file
+  Platform BDS customizations include file.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/PeImage.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/NvVarsFileLib.h>
+
+#include <Protocol/Decompress.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/S3SaveState.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Guid/Acpi.h>
+#include <Guid/SmBios.h>
+#include <Guid/Mps.h>
+#include <Guid/HobList.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+
+#include <SimicsPlatforms.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];
+extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH           gUartDeviceNode;
+extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+  { \
+    { \
+      HARDWARE_DEVICE_PATH, \
+      HW_PCI_DP, \
+      { \
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    (Func), \
+    (Dev) \
+  }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    EISA_PNP_ID((PnpId)), \
+    0 \
+  }
+
+#define gPciIsaBridge \
+  PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+  PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+  PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+  PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_UART_DP, \
+      { \
+        (UINT8) (sizeof (UART_DEVICE_PATH)), \
+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    0, \
+    115200, \
+    8, \
+    1, \
+    1 \
+  }
+
+#define gPcAnsiTerminal \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_VENDOR_DP, \
+      { \
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    DEVICE_PATH_MESSAGING_PC_ANSI \
+  }
+
+#define PCI_CLASS_SCC          0x07
+#define PCI_SUBCLASS_SERIAL    0x00
+#define PCI_IF_16550           0x02
+#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN  BIT1
+#define STD_ERROR   BIT2
+extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformInitializeConsole (
+  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
+  );
+
+/**
+  Use SystemTable ConOut to stop video based Simple Text Out consoles from going
+  to the video device. Put up LogoFile on every video device that is a console.
+
+  @param[in]  LogoFile   The file name of logo to display on the center of the screen.
+
+  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and logo displayed.
+  @retval EFI_UNSUPPORTED Logo not found.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableBootLogo(
+  IN  EFI_GUID  *LogoFile
+);
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100644
index 0000000000..cdb6e242e8
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,72 @@
+## @file
+#  Platform BDS customizations library.
+#
+# Copyright (c) 2007 - 2019 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/OpenBoardPkg.dec
+  OvmfPkg/OvmfPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  BaseLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  UefiBootManagerLib
+  BootLogoLib
+  DevicePathLib
+  PciLib
+  NvVarsFileLib
+  DxeLoadLinuxLib
+  UefiLib
+  LogoLib
+
+[Pcd]
+  gBoardModuleTokenSpaceGuid.PcdEmuVariableEvent
+  gBoardModuleTokenSpaceGuid.PcdOvmfFlashVariablesEnable
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+  gBoardModuleTokenSpaceGuid.PcdShellFile
+  gBoardModuleTokenSpaceGuid.PcdLogoFile
+
+[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/Library/SerializeVariablesLib/SerializeVariablesLib.h b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
new file mode 100644
index 0000000000..9b4c2a629a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
@@ -0,0 +1,33 @@
+/** @file
+  Serialize Variables Library implementation
+
+  Copyright (c) 2009 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SERIALIZE_VARIABLES_LIB_INSTANCE__
+#define __SERIALIZE_VARIABLES_LIB_INSTANCE__
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SerializeVariablesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#define SV_FROM_HANDLE(a)       CR (a, SV_INSTANCE, Signature, SV_SIGNATURE)
+#define SV_SIGNATURE            SIGNATURE_32 ('S', 'V', 'A', 'R')
+
+typedef struct {
+  UINT32                              Signature;
+  VOID                                *BufferPtr;
+  UINTN                               BufferSize;
+  UINTN                               DataSize;
+} SV_INSTANCE;
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
new file mode 100644
index 0000000000..08c561f586
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  Serialize Variables Library implementation
+#
+#  This library serializes and deserializes UEFI variables
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeSerializeVariablesLib
+  FILE_GUID                      = 266A1434-6B22-441F-A8D2-D54AA8FDF95C
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SerializeVariablesLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER
+
+[Sources]
+  SerializeVariablesLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ShellPkg/ShellPkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..6be3b301ad
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
@@ -0,0 +1,38 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION          = 0x00010005
+  BASE_NAME            = SiliconPolicyInitLib
+  FILE_GUID            = B494DF39-A5F8-48A1-B2D0-EF523AD91C55
+  MODULE_TYPE          = PEIM
+  VERSION_STRING       = 1.0
+  LIBRARY_CLASS        = SiliconPolicyInitLib
+
+[Sources]
+  SiliconPolicyInitLib.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  BaseLib
+  DebugLib
+  DebugPrintErrorLevelLib
+  HobLib
+  IoLib
+  MemoryAllocationLib
+  PeiServicesLib
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
new file mode 100644
index 0000000000..4fde3c75a6
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
@@ -0,0 +1,35 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SiliconPolicyUpdateLib
+  FILE_GUID                      = 6EA9585C-3C15-47da-9FFC-25E9E4EA4D0C
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SiliconPolicyUpdateLib
+
+[Sources]
+  SiliconPolicyUpdateLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  HobLib
+  IoLib
+  PcdLib
+
+[Pcd]
+
+[FixedPcd]
+
+[Ppis]
+
+[Guids]
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm b/Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
new file mode 100644
index 0000000000..adb87de943
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
@@ -0,0 +1,45 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+#include <Base.h>
+
+    SECTION .text
+
+extern ASM_PFX(SecCoreStartupWithStack)
+
+;
+; SecCore Entry Point
+;
+; Processor is in flat protected mode
+;
+; @param[in]  EAX   Initial value of the EAX register (BIST: Built-in Self Test)
+; @param[in]  DI    'BP': boot-strap processor, or 'AP': application processor
+; @param[in]  EBP   Pointer to the start of the Boot Firmware Volume
+;
+; @return     None  This routine does not return
+;
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+    ;
+    ; Load temporary RAM stack based on PCDs
+    ;
+    %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdSimicsSecPeiTempRamBase) + \
+                          FixedPcdGet32 (PcdSimicsSecPeiTempRamSize))
+    mov     eax, SEC_TOP_OF_STACK
+    mov     esp, eax
+    nop
+
+    ;
+    ; Setup parameters and call SecCoreStartupWithStack
+    ;   [esp]   return address for call
+    ;   [esp+4] BootFirmwareVolumePtr
+    ;   [esp+8] TopOfCurrentStack
+    ;
+    push    eax
+    push    ebp
+    call    ASM_PFX(SecCoreStartupWithStack)
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
new file mode 100644
index 0000000000..b1d319c5ea
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
@@ -0,0 +1,73 @@
+## @file
+#  SEC Driver
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SecMain
+  FILE_GUID                      = e67f156f-54c5-47f3-a35d-07c045881e14
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SecMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  SecMain.c
+
+[Sources.IA32]
+  Ia32/SecEntry.nasm
+
+[Sources.X64]
+  X64/SecEntry.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  SimicsX58SktPkg/SktPkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  BaseMemoryLib
+  PeiServicesLib
+  PcdLib
+  UefiCpuLib
+  DebugAgentLib
+  IoLib
+  PeCoffLib
+  PeCoffGetEntryPointLib
+  PeCoffExtraActionLib
+  ExtractGuidedSectionLib
+  LocalApicLib
+  PciCf8Lib
+
+[Ppis]
+  gEfiTemporaryRamSupportPpiGuid                # PPI ALWAYS_PRODUCED
+
+[Pcd]
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize
+  gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
+  gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
+
+[FeaturePcd]
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm b/Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
new file mode 100644
index 0000000000..2e6d8f618c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
@@ -0,0 +1,45 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+#include <Base.h>
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(SecCoreStartupWithStack)
+
+;
+; SecCore Entry Point
+;
+; Processor is in flat protected mode
+;
+; @param[in]  RAX   Initial value of the EAX register (BIST: Built-in Self Test)
+; @param[in]  DI    'BP': boot-strap processor, or 'AP': application processor
+; @param[in]  RBP   Pointer to the start of the Boot Firmware Volume
+;
+; @return     None  This routine does not return
+;
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+    ;
+    ; Load temporary RAM stack based on PCDs
+    ;
+    %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdSimicsSecPeiTempRamBase) + \
+                          FixedPcdGet32 (PcdSimicsSecPeiTempRamSize))
+    mov     rsp, SEC_TOP_OF_STACK
+    nop
+
+    ;
+    ; Setup parameters and call SecCoreStartupWithStack
+    ;   rcx: BootFirmwareVolumePtr
+    ;   rdx: TopOfCurrentStack
+    ;
+    mov     rcx, rbp
+    mov     rdx, rsp
+    sub     rsp, 0x20
+    call    ASM_PFX(SecCoreStartupWithStack)
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
new file mode 100644
index 0000000000..623d8ad2a9
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
@@ -0,0 +1,38 @@
+/** @file
+  This driver effectuates QSP platform configuration settings and exposes
+  them via HII.
+
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_H_
+#define _PLATFORM_H_
+
+//
+// Macro and type definitions that connect the form with the HII driver code.
+//
+#define FORMSTATEID_MAIN_FORM  1
+#define FORMID_MAIN_FORM       1
+
+#define QUESTION_RES_CUR       1
+#define MAXSIZE_RES_CUR       16
+
+#define LABEL_RES_NEXT         1
+#define QUESTION_RES_NEXT      2
+
+#define QUESTION_SAVE_EXIT     3
+#define QUESTION_DISCARD_EXIT  4
+
+//
+// This structure describes the form state. Its fields relate strictly to the
+// visual widgets on the form.
+//
+typedef struct {
+  UINT16 CurrentPreferredResolution[MAXSIZE_RES_CUR];
+  UINT32 NextPreferredResolution;
+} MAIN_FORM_STATE;
+
+#endif // _PLATFORM_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
new file mode 100644
index 0000000000..3d9af148ec
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
@@ -0,0 +1,31 @@
+// *++
+//
+// Copyright (C) 2014, Red Hat, Inc.
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+//   Platform.uni
+//
+// Abstract:
+//
+//   String definitions for PlatformForms.vfr
+//
+// --*/
+
+/=#
+
+#langdef en-US "English"
+
+#string STR_FORMSET_TITLE        #language en-US "QSP Platform Configuration"
+#string STR_FORMSET_HELP         #language en-US "Change various QSP platform settings."
+#string STR_MAIN_FORM_TITLE      #language en-US "QSP Settings"
+#string STR_RES_CUR              #language en-US "Preferred Resolution at Next Boot"
+#string STR_RES_CUR_HELP         #language en-US "The preferred resolution of the Graphics Console at next boot. It might be unset, or even invalid (hence ignored) wrt. the video RAM size."
+#string STR_RES_NEXT             #language en-US "Change Preferred Resolution for Next Boot"
+#string STR_RES_NEXT_HELP        #language en-US "You can specify a new preference for the Graphics Console here. The list is filtered against the video RAM size."
+#string STR_SAVE_EXIT            #language en-US "Commit Changes and Exit"
+#string STR_DISCARD_EXIT         #language en-US "Discard Changes and Exit"
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
new file mode 100644
index 0000000000..c2063c427b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
@@ -0,0 +1,52 @@
+/** @file
+  Utility functions for serializing (persistently storing) and deserializing
+  Simics's platform configuration.
+
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_CONFIG_H_
+#define _PLATFORM_CONFIG_H_
+
+#include <Base.h>
+
+//
+// This structure participates in driver configuration. It does not
+// (necessarily) reflect the wire format in the persistent store.
+//
+#pragma pack(1)
+typedef struct {
+  //
+  // preferred graphics console resolution when booting
+  //
+  UINT32 HorizontalResolution;
+  UINT32 VerticalResolution;
+} PLATFORM_CONFIG;
+#pragma pack()
+
+//
+// Please see the API documentation near the function definitions.
+//
+EFI_STATUS
+EFIAPI
+PlatformConfigSave (
+  IN PLATFORM_CONFIG *PlatformConfig
+  );
+
+EFI_STATUS
+EFIAPI
+PlatformConfigLoad (
+  OUT PLATFORM_CONFIG *PlatformConfig,
+  OUT UINT64          *OptionalElements
+  );
+
+//
+// Feature flags for OptionalElements.
+//
+#define PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION BIT0
+#define PLATFORM_CONFIG_F_DOWNGRADE           BIT63
+
+#endif // _PLATFORM_CONFIG_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
new file mode 100644
index 0000000000..a38521e8d3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
@@ -0,0 +1,67 @@
+// *++
+//
+// Copyright (C) 2014, Red Hat, Inc.
+// Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+//   PlatformForms.vfr
+//
+// Abstract:
+//
+//   Form definitions for exposing some of OVMF's platform knobs via HII.
+//
+// --*/
+
+#include <Guid/SimicsBoardConfig.h>
+#include "Platform.h"
+
+formset
+  guid  = SIMICS_BOARD_CONFIG_GUID,
+  title = STRING_TOKEN(STR_FORMSET_TITLE),
+  help  = STRING_TOKEN(STR_FORMSET_HELP),
+
+  varstore MAIN_FORM_STATE,
+    varid = FORMSTATEID_MAIN_FORM,
+    name  = MainFormState,
+    guid  = SIMICS_BOARD_CONFIG_GUID;
+
+  form
+    formid = FORMID_MAIN_FORM,
+    title  = STRING_TOKEN(STR_MAIN_FORM_TITLE);
+
+    //
+    // Display the current preference in a read-only string field.
+    //
+    string
+      varid      = MainFormState.CurrentPreferredResolution,
+      questionid = QUESTION_RES_CUR,
+      prompt     = STRING_TOKEN(STR_RES_CUR),
+      help       = STRING_TOKEN(STR_RES_CUR_HELP),
+      flags      = READ_ONLY,
+      minsize    = 0,
+      maxsize    = MAXSIZE_RES_CUR,
+    endstring;
+
+    //
+    // We'll dynamically generate a one-of-many selection at this label.
+    //
+    label LABEL_RES_NEXT;
+
+    text
+      help  = STRING_TOKEN(STR_SAVE_EXIT),
+      text  = STRING_TOKEN(STR_SAVE_EXIT),
+      flags = INTERACTIVE,
+      key   = QUESTION_SAVE_EXIT;
+
+    text
+      help  = STRING_TOKEN(STR_DISCARD_EXIT),
+      text  = STRING_TOKEN(STR_DISCARD_EXIT),
+      flags = INTERACTIVE,
+      key   = QUESTION_DISCARD_EXIT;
+
+  endform;
+
+endformset;
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
new file mode 100644
index 0000000000..eef187d2a7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
@@ -0,0 +1,65 @@
+## @file
+#  This driver effectuates Simics X58 platform configuration settings and exposes
+#  them via HII.
+#
+#  Copyright (C) 2014, Red Hat, Inc.
+#  Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SimicsDxe
+  FILE_GUID                      = 74B64DC1-B0B6-4853-A6BD-C6426059AB1E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PlatformInit
+  UNLOAD_IMAGE                   = PlatformUnload
+
+[Sources]
+  Platform.c
+  Platform.uni
+  PlatformConfig.c
+  PlatformForms.vfr
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  HiiLib
+  MemoryAllocationLib
+  PrintLib
+  UefiBootServicesTableLib
+  UefiHiiServicesLib
+  UefiLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DxeServicesTableLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+
+[Protocols]
+  gEfiDevicePathProtocolGuid      ## PRODUCES
+  gEfiGraphicsOutputProtocolGuid  ## CONSUMES
+  gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+
+[Guids]
+  gEfiIfrTianoGuid
+  gSimicsBoardConfigGuid
+
+[Depex]
+  gEfiHiiConfigRoutingProtocolGuid  AND
+  gEfiHiiDatabaseProtocolGuid       AND
+  gEfiVariableArchProtocolGuid      AND
+  gEfiVariableWriteArchProtocolGuid
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
new file mode 100644
index 0000000000..07fa2e2d11
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
@@ -0,0 +1,50 @@
+/** @file
+  PC/AT CMOS access routines
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __CMOS_H__
+#define __CMOS_H__
+
+/**
+  Reads 8-bits of CMOS data.
+
+  Reads the 8-bits of CMOS data at the location specified by Index.
+  The 8-bit read value is returned.
+
+  @param  Index  The CMOS location to read.
+
+  @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+  IN      UINTN                     Index
+  );
+
+/**
+  Writes 8-bits of CMOS data.
+
+  Writes 8-bits of CMOS data to the location specified by Index
+  with the value specified by Value and returns Value.
+
+  @param  Index  The CMOS location to write.
+  @param  Value  The value to write to CMOS.
+
+  @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+  IN      UINTN                     Index,
+  IN      UINT8                     Value
+  );
+
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
new file mode 100644
index 0000000000..102d21cd64
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
@@ -0,0 +1,88 @@
+/** @file
+  Platform PEI module include file.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_PEI_H_INCLUDED_
+#define _PLATFORM_PEI_H_INCLUDED_
+
+VOID
+AddIoMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  );
+
+VOID
+AddIoMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  );
+
+VOID
+AddMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  );
+
+VOID
+AddMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  );
+
+VOID
+AddUntestedMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  );
+
+VOID
+AddReservedMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize,
+  BOOLEAN                     Cacheable
+  );
+
+VOID
+AddressWidthInitialization (
+  VOID
+  );
+
+VOID
+X58TsegMbytesInitialization (
+  VOID
+  );
+
+EFI_STATUS
+PublishPeiMemory (
+  VOID
+  );
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+  VOID
+  );
+
+VOID
+InitializeRamRegions (
+  VOID
+  );
+
+VOID
+InstallFeatureControlCallback (
+  VOID
+  );
+
+extern EFI_BOOT_MODE mBootMode;
+
+extern BOOLEAN mS3Supported;
+
+extern UINT8 mPhysMemAddressWidth;
+
+extern UINT32 mMaxCpuCount;
+
+extern UINT16 mHostBridgeDevId;
+#endif // _PLATFORM_PEI_H_INCLUDED_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
new file mode 100644
index 0000000000..ccc7037d75
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
@@ -0,0 +1,104 @@
+## @file
+#  Platform PEI driver
+#
+#  This module provides platform specific function to detect boot mode.
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SimicsPei
+  FILE_GUID                      = 05116218-f9f1-41f8-8d17-c2207006ffff
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializePlatform
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  Cmos.c
+  FeatureControl.c
+  MemDetect.c
+  Platform.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  MinPlatformPkg/MinPlatformPkg.dec
+  SimicsX58SktPkg/SktPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[Guids]
+  gEfiMemoryTypeInformationGuid
+  gEfiSmmPeiSmramMemoryReserveGuid              ## CONSUMES
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  HobLib
+  IoLib
+  PciLib
+  PeiResourcePublicationLib
+  PeiServicesLib
+  PeiServicesTablePointerLib
+  PeimEntryPoint
+  MtrrLib
+  PcdLib
+
+[Pcd]
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize
+  gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
+  gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+  gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+  gBoardModuleTokenSpaceGuid.PcdPciIoBase
+  gBoardModuleTokenSpaceGuid.PcdPciIoSize
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Base
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Size
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Base
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Size
+  gSimicsX58PkgTokenSpaceGuid.PcdX58TsegMbytes
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress  ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize         ## CONSUMES
+  gMinPlatformPkgTokenSpaceGuid.PcdIoApicId
+
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+
+[Ppis]
+  gEfiPeiMasterBootModePpiGuid
+  gEfiPeiMpServicesPpiGuid
+
+[Depex]
+  TRUE
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
new file mode 100644
index 0000000000..f9c641845c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
@@ -0,0 +1,38 @@
+/** @file
+  This driver installs SMBIOS information for QSP
+
+  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SMBIOS_PLATFORM_DXE_H_
+#define _SMBIOS_PLATFORM_DXE_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+
+/**
+  Validates the SMBIOS entry point structure
+
+  @param  EntryPointStructure  SMBIOS entry point structure
+
+  @retval TRUE   The entry point structure is valid
+  @retval FALSE  The entry point structure is not valid
+
+**/
+BOOLEAN
+IsEntryPointStructureValid (
+  IN SMBIOS_TABLE_ENTRY_POINT  *EntryPointStructure
+  );
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
new file mode 100644
index 0000000000..1420a315cf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
@@ -0,0 +1,51 @@
+## @file
+#  This driver installs SMBIOS information for QSP
+#
+#  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+#  Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmbiosPlatformDxe
+  FILE_GUID                      = 4b18323d-2d42-4afa-b9e5-91516a6fe505
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = SmbiosTablePublishEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC ARM AARCH64
+#
+
+[Sources]
+  SmbiosPlatformDxe.h
+  SmbiosPlatformDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  AdvancedFeaturePkg/AdvancedFeaturePkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  BaseLib
+  UefiDriverEntryPoint
+  DebugLib
+  HobLib
+  MemoryAllocationLib
+  IoLib
+
+[Protocols]
+  gEfiSmbiosProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+  gEfiSmbiosProtocolGuid
+
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (2 preceding siblings ...)
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add DXE driver for Legacy Sio support

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 .../LegacySioDxe/ComponentName.c                   | 173 ++++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioChip.c      | 272 ++++++++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c    | 600 +++++++++++++++++++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioService.c   | 249 +++++++++
 .../LegacySioDxe/ComponentName.h                   |  87 +++
 .../LegacySioDxe/LegacySioDxe.inf                  |  54 ++
 .../SimicsOpenBoardPkg/LegacySioDxe/Register.h     |  15 +
 .../SimicsOpenBoardPkg/LegacySioDxe/SioChip.h      | 195 +++++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h    | 134 +++++
 .../SimicsOpenBoardPkg/LegacySioDxe/SioService.h   | 143 +++++
 10 files changed, 1922 insertions(+)
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/LegacySioDxe.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/Register.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.h

diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.c b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.c
new file mode 100644
index 0000000000..4ba02f92c0
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.c
@@ -0,0 +1,173 @@
+/** @file
+  Install Base and Size Info Ppi for Firmware Volume Recovery.
+
+  Copyright (c) 2013 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SioDriver.h"
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  mSioComponentName = {
+  SioComponentNameGetDriverName,
+  SioComponentNameGetControllerName,
+  "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mSioComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)    SioComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)SioComponentNameGetControllerName,
+  "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSioDriverNameTable[] = {
+  {
+    "eng;en",
+    L"Super I/O Driver"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+///
+/// Table of Controller names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSioControllerNameTable[] = {
+  {
+    "eng;en",
+    L"Super I/O Controller"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that 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.
+  @param  DriverName 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
+SioComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mSioDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &mSioComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle 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      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         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller 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.
+  @param  ControllerName   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 NULL.
+  @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
+SioComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL   *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS                        Status;
+
+  //
+  // Make sure this driver is currently managing ControllHandle
+  //
+  Status = EfiTestManagedDevice (
+             ControllerHandle,
+             mSioDriver.DriverBindingHandle,
+             &gEfiPciIoProtocolGuid
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // ChildHandle must be NULL for a Device Driver
+  //
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mSioControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This == &mSioComponentName)
+           );
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.c b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.c
new file mode 100644
index 0000000000..b9a7b9cd24
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.c
@@ -0,0 +1,272 @@
+/** @file
+  Super I/O specific implementation.
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SioDriver.h"
+#include <Library/S3IoLib.h>
+
+LOCAL_IO_WRITE8    mIoWrite8         = IoWrite8;
+//
+// System configuration (setup) information
+//
+// SYSTEM_CONFIGURATION                mSystemConfiguration;
+
+//
+// COM 1 UART Controller
+//
+ACPI_SIO_RESOURCES_IO_IRQ      mCom1Resources = {
+  {
+    { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR },
+    0x3f8,
+    8
+  },
+  {
+    { ACPI_IRQ_NOFLAG_DESCRIPTOR },
+    BIT4    // IRQ4
+  },
+  {
+    ACPI_END_TAG_DESCRIPTOR,
+    0
+  }
+};
+
+//
+// PS/2 Keyboard Controller
+//
+ACPI_SIO_RESOURCES_IO_IRQ      mKeyboardResources = {
+  {
+    { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR },
+    0x60,
+    5
+  },
+  {
+    { ACPI_IRQ_NOFLAG_DESCRIPTOR },
+    BIT1
+  },
+  {
+    ACPI_END_TAG_DESCRIPTOR,
+    0
+  }
+};
+
+//
+// PS/2 Mouse Controller
+//
+ACPI_SIO_RESOURCES_IO_IRQ      mMouseResources = {
+  {
+    { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR },
+    0x60,
+    5
+  },
+  {
+    { ACPI_IRQ_NOFLAG_DESCRIPTOR },
+    BIT12
+  },
+  {
+    ACPI_END_TAG_DESCRIPTOR,
+    0
+  }
+};
+
+//
+// Table of SIO Controllers
+//
+DEVICE_INFO    mDeviceInfo[] = {
+  {
+    {
+      EISA_PNP_ID(0x501),
+      0
+    },
+    0,
+    RESOURCE_IO | RESOURCE_IRQ,
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mCom1Resources },
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mCom1Resources }
+  },  // COM 1 UART Controller
+  {
+    {
+      EISA_PNP_ID(0x303),
+      0
+    },
+    0,
+    0,  // Cannot change resource
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mKeyboardResources },
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mKeyboardResources }
+  },  // PS/2 Keyboard Controller
+  {
+    {
+      EISA_PNP_ID(0xF03),
+      0
+    },
+    0,
+    0,  // Cannot change resource
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mMouseResources },
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mMouseResources }
+  }  // PS/2 Mouse Controller
+};
+
+
+/**
+  Return the supported devices.
+
+  @param[out] Devices         Pointer to pointer of EFI_SIO_ACPI_DEVICE_ID.
+                              Caller is responsible to free the buffer.
+  @param[out] Count           Pointer to UINTN holding the device count.
+**/
+VOID
+DeviceGetList (
+  OUT EFI_SIO_ACPI_DEVICE_ID **Devices,
+  OUT UINTN                  *Count
+  )
+{
+  EFI_SIO_ACPI_DEVICE_ID   *LocalDevices;
+  UINTN                    LocalCount;
+  UINTN                    DeviceCount;
+  UINTN                    Index;
+
+  //
+  // Allocate enough memory for simplicity
+  //
+  DeviceCount =  sizeof (mDeviceInfo) / sizeof (mDeviceInfo[0]);
+  LocalDevices = AllocatePool (sizeof (EFI_SIO_ACPI_DEVICE_ID) * DeviceCount);
+  ASSERT (LocalDevices != NULL);
+  if (LocalDevices == NULL) {
+    return;
+  }
+  LocalCount = 0;
+
+  for (Index = 0; Index < DeviceCount; Index++) {
+    CopyMem (&LocalDevices[LocalCount], &mDeviceInfo[Index].Device, sizeof (EFI_SIO_ACPI_DEVICE_ID));
+    LocalCount++;
+  }
+
+  *Devices = LocalDevices;
+  *Count   = LocalCount;
+}
+
+
+/**
+  Super I/O controller initialization.
+
+  @retval     EFI_SUCCESS       The super I/O controller is found and initialized.
+  @retval     EFI_UNSUPPORTED   The super I/O controller is not found.
+**/
+EFI_STATUS
+SioInit (
+  VOID
+  )
+{
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Find the DEVICE_INFO for specified Device.
+
+  @param[in]  Device        Pointer to the EFI_SIO_ACPI_DEVICE_ID.
+
+  @retval     DEVICE_INFO*  Pointer to the DEVICE_INFO.
+**/
+DEVICE_INFO *
+DeviceSearch (
+  IN EFI_SIO_ACPI_DEVICE_ID *Device
+  )
+{
+  UINTN       Index;
+
+  for (Index = 0; Index < sizeof (mDeviceInfo) / sizeof (mDeviceInfo[0]); Index++) {
+    if (CompareMem (Device, &mDeviceInfo[Index].Device, sizeof (*Device)) == 0) {
+      return &mDeviceInfo[Index];
+    }
+  }
+
+  ASSERT (FALSE);
+  return NULL;
+}
+
+
+/**
+  Program the SIO chip to enable the specified device using the default resource.
+
+  @param[in] Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+**/
+VOID
+DeviceEnable (
+  IN EFI_SIO_ACPI_DEVICE_ID   *Device
+  )
+{
+}
+
+
+/**
+  Get the ACPI resources for specified device.
+
+  @param[in]  Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[out] Resources       Pointer to ACPI_RESOURCE_HEADER_PTR.
+
+  @retval     EFI_SUCCESS     The resources are returned successfully.
+**/
+EFI_STATUS
+DeviceGetResources (
+  IN  EFI_SIO_ACPI_DEVICE_ID   *Device,
+  OUT ACPI_RESOURCE_HEADER_PTR *Resources
+  )
+{
+  DEVICE_INFO               *DeviceInfo;
+
+  DeviceInfo = DeviceSearch (Device);
+
+  *Resources = DeviceInfo->Resources;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Set the ACPI resources for specified device.
+
+  The SIO chip is programmed to use the new resources and the
+  resources setting are saved. The function assumes the resources
+  are valid.
+
+  @param[in] Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[in] Resources       ACPI_RESOURCE_HEADER_PTR.
+
+  @retval    EFI_UNSUPPORTED
+**/
+EFI_STATUS
+DeviceSetResources (
+  IN EFI_SIO_ACPI_DEVICE_ID   *Device,
+  IN ACPI_RESOURCE_HEADER_PTR Resources
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+
+/**
+  Get the possible ACPI resources for specified device.
+
+  @param[in]  Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[out] Resources       Pointer to ACPI_RESOURCE_HEADER_PTR.
+
+  @retval     EFI_SUCCESS     The resources are returned successfully.
+**/
+EFI_STATUS
+DevicePossibleResources (
+  IN  EFI_SIO_ACPI_DEVICE_ID   *Device,
+  OUT ACPI_RESOURCE_HEADER_PTR *Resources
+  )
+{
+  DEVICE_INFO               *DeviceInfo;
+
+  DeviceInfo = DeviceSearch (Device);
+
+  *Resources = DeviceInfo->PossibleResources;
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c
new file mode 100644
index 0000000000..408c6ff301
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.c
@@ -0,0 +1,600 @@
+/** @file
+  EFI Driver following Driver Binding Protocol.
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SioDriver.h"
+
+
+//
+// This driver is for ACPI(PNP0A03,0)/PCI(0x1f,0)
+//
+//
+//  Sio Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL mSioDriver = {
+  SioDriverSupported,
+  SioDriverStart,
+  SioDriverStop,
+  1,
+  NULL,
+  NULL
+};
+
+//
+// The list of the created SIO_DEV
+//
+LIST_ENTRY                  mSioDevPool = INITIALIZE_LIST_HEAD_VARIABLE (mSioDevPool);
+
+//
+// Template structure to create SIO_DEV
+//
+SIO_DEV                     mSioDevTemplate = {
+  SIO_DEV_SIGNATURE,        // Signature
+  NULL,                     // PciHandle
+  {
+    0x00000000,             // HID
+    0x00000000              // UID
+  },
+  NULL,                     // Handle
+  {                         // Sio Instance
+    SioRegisterAccess,
+    SioGetResources,
+    SioSetResources,
+    SioPossibleResources,
+    SioModify
+  },
+  NULL,                     // DevicePath
+  {
+    NULL,                   // ForwardLink
+    NULL,                   // BackLink
+  }
+};
+
+//
+// Template ACPI_HID_DEVICE_PATH structure to create device path
+//
+ACPI_HID_DEVICE_PATH        mAcpiNodeTemplate = {
+  {
+    ACPI_DEVICE_PATH,       // Type
+    ACPI_DP,                // SubType
+    {
+      sizeof (ACPI_HID_DEVICE_PATH),  // Length[0]
+      0                               // Length[1]
+    }
+  },
+  0x00000000,               // HID
+  0x00000000                // UID
+};
+
+
+/**
+  The user Entry Point for module Lpc47m17x. The user code starts with this function.
+
+  @param[in]  ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in]  SystemTable    A pointer to the EFI System Table.
+
+  @retval     EFI_SUCCESS    The entry point is executed successfully.
+  @retval     other          Some error occurs when executing this entry point.
+**/
+EFI_STATUS
+EFIAPI
+SioDriverEntryPoint (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  if (EFI_ERROR (SioInit())) {
+    return EFI_UNSUPPORTED;
+  } else {
+
+    //
+    // Install protocols
+    //
+    return EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &mSioDriver,
+             ImageHandle,
+             &mSioComponentName,
+             &mSioComponentName2
+             );
+  }
+}
+
+
+/**
+  Test to see if this driver supports Controller Handle.
+
+  @param[in]  This                Protocol instance pointer.
+  @param[in]  Controller          Handle of device to test
+  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
+                                  device to start.
+
+  @retval     EFI_SUCCESS         This driver supports this device
+  @retval     EFI_ALREADY_STARTED This driver is already running on this device
+  @retval     other               This driver does not support this device
+**/
+EFI_STATUS
+EFIAPI
+SioDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
+  ACPI_HID_DEVICE_PATH      *AcpiNode;
+  PCI_TYPE00                Pci;
+  UINTN                     Index;
+  EFI_SIO_ACPI_DEVICE_ID    *Devices;
+  UINTN                     Count;
+  UINTN                     SegmentNumber;
+  UINTN                     BusNumber;
+  UINTN                     DeviceNumber;
+  UINTN                     FunctionNumber;
+
+  //
+  // If RemainingDevicePath is not NULL, it should verify that the first device
+  // path node in RemainingDevicePath is an ACPI Device path node which is a
+  // legal Device Path Node for this bus driver's children.
+  //
+  if (RemainingDevicePath != NULL) {
+    if (!IsDevicePathEnd (RemainingDevicePath)) {
+      if ((RemainingDevicePath->Type != ACPI_DEVICE_PATH) ||
+          (((RemainingDevicePath->SubType != ACPI_DP) || (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH))) &&
+          ((RemainingDevicePath->SubType != ACPI_EXTENDED_DP) || (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH))))
+          ) {
+        return EFI_UNSUPPORTED;
+      }
+
+      DeviceGetList (&Devices, &Count);
+      if (Devices == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      AcpiNode = (ACPI_HID_DEVICE_PATH *) RemainingDevicePath;
+      for (Index = 0; Index < Count; Index++) {
+        if ((AcpiNode->HID == Devices[Index].HID) &&
+            (AcpiNode->UID == Devices[Index].UID)) {
+          break;
+        }
+      }
+      FreePool (Devices);
+      if (Index == Count) {
+        return EFI_UNSUPPORTED;
+      }
+    }
+  }
+
+  //
+  // See if the parent device path can be opened BY_DRIVER
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiDevicePathProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  //
+  // Get PciIo protocol instance
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (!EFI_ERROR (Status)) {
+    Status = PciIo->Pci.Read (
+                          PciIo,
+                          EfiPciIoWidthUint32,
+                          0,
+                          sizeof (Pci) / sizeof (UINT32),
+                          &Pci
+                          );
+    ASSERT_EFI_ERROR (Status);
+
+    Status = EFI_UNSUPPORTED;
+    if ((Pci.Hdr.Command & (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE))
+                        == (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)
+       ) {
+      if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
+        //
+        // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code
+        //
+        if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {
+          Status = EFI_SUCCESS;
+        }
+
+        //
+        // See if this is an Intel PCI to ISA Bridge in Positive Decode Mode
+        //
+        if ((Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) &&
+            (Pci.Hdr.VendorId == 0x8086)) {
+          //
+          // See if this is on Function #0 to avoid false positive on
+          // PCI_CLASS_BRIDGE_OTHER that has the same value as
+          // PCI_CLASS_BRIDGE_ISA_PDECODE
+          //
+          Status = PciIo->GetLocation (
+                            PciIo,
+                            &SegmentNumber,
+                            &BusNumber,
+                            &DeviceNumber,
+                            &FunctionNumber
+                            );
+          if (!EFI_ERROR (Status) && (FunctionNumber == 0)) {
+            Status = EFI_SUCCESS;
+          } else {
+            Status = EFI_UNSUPPORTED;
+          }
+        }
+      }
+    }
+
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiPciIoProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+  }
+  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Destroy the SIO controller handle.
+
+  @param[in]  ChildHandle     The SIO controller handle.
+
+  @retval     EFI_SUCCESS     The SIO controller handle is destroyed successfully.
+**/
+EFI_STATUS
+SioDestroyDevice (
+  IN EFI_HANDLE                ChildHandle
+  )
+{
+  EFI_STATUS                Status;
+  SIO_DEV                   *SioDev;
+  EFI_SIO_PROTOCOL          *Sio;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+
+  Status = gBS->HandleProtocol (
+                  ChildHandle,
+                  &gEfiSioProtocolGuid,
+                  (VOID **) &Sio
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  SioDev = SIO_DEV_FROM_THIS (Sio);
+
+  Status = gBS->CloseProtocol (
+                  SioDev->PciHandle,
+                  &gEfiPciIoProtocolGuid,
+                  mSioDriver.DriverBindingHandle,
+                  ChildHandle
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  ChildHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  SioDev->DevicePath,
+                  &gEfiSioProtocolGuid,
+                  &SioDev->Sio,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    gBS->OpenProtocol (
+           SioDev->PciHandle,
+           &gEfiPciIoProtocolGuid,
+           (VOID **) &PciIo,
+           mSioDriver.DriverBindingHandle,
+           ChildHandle,
+           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+           );
+    return Status;
+  }
+
+  RemoveEntryList (&SioDev->Link);
+  FreePool (SioDev->DevicePath);
+  FreePool (SioDev);
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Create the SIO controller handle.
+
+  @param[in]  Controller       The parent PCI controller handle.
+  @param[in]  Device           Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[in]  ParentDevicePath The device path of the parent controller.
+  @param[out] PciIo            The PciIo instance of the parent controller.
+**/
+VOID
+SioCreateDevice (
+  IN  EFI_HANDLE                Controller,
+  IN  EFI_SIO_ACPI_DEVICE_ID    *Device,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath,
+  OUT EFI_PCI_IO_PROTOCOL       *PciIo
+  )
+{
+  EFI_STATUS                Status;
+  SIO_DEV                   *SioDev;
+
+  DeviceEnable (Device);
+  SioDev = AllocateCopyPool (sizeof (SIO_DEV), &mSioDevTemplate);
+  ASSERT (SioDev != NULL);
+  if (SioDev == NULL) {
+    return;
+  }
+  InsertHeadList (&mSioDevPool, &SioDev->Link);
+
+  SioDev->PciHandle       = Controller;
+
+  CopyMem (&SioDev->Device, Device, sizeof (*Device));
+
+  mAcpiNodeTemplate.HID = Device->HID;
+  mAcpiNodeTemplate.UID = Device->UID;
+  SioDev->DevicePath = AppendDevicePathNode (ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mAcpiNodeTemplate);
+  ASSERT (SioDev->DevicePath != NULL);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &SioDev->Handle,
+                  &gEfiSioProtocolGuid,        &SioDev->Sio,
+                  &gEfiDevicePathProtocolGuid, SioDev->DevicePath,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  mSioDriver.DriverBindingHandle,
+                  SioDev->Handle,
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                  );
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+  Start this driver on ControllerHandle.
+
+  @param[in]  This                 Protocol instance pointer.
+  @param[in]  Controller           Handle of device to bind driver to
+  @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
+                                   device to start.
+
+  @retval     EFI_SUCCESS          This driver is added to ControllerHandle
+  @retval     EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
+  @retval     other                This driver does not support this device
+**/
+EFI_STATUS
+EFIAPI
+SioDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_PCI_IO_PROTOCOL                 *PciIo;
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
+  EFI_SIO_ACPI_DEVICE_ID              *Devices;
+  SIO_DEV                             *SioDev;
+  UINTN                               Count;
+  UINTN                               Index;
+  ACPI_HID_DEVICE_PATH                *AcpiNode;
+  BOOLEAN                             *HasCreated;
+  BOOLEAN                             *RequestCreate;
+  LIST_ENTRY                          *Node;
+
+  HasCreated    = NULL;
+  RequestCreate = NULL;
+  //
+  // Get the ISA bridge's Device Path
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+    return Status;
+  }
+
+  //
+  // Get Pci IO
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiDevicePathProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+    return Status;
+  }
+
+  if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
+    return EFI_SUCCESS;
+  }
+
+  DeviceGetList (&Devices, &Count);
+  if (Devices == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit_Start;
+  }
+  HasCreated    = AllocatePool (sizeof (BOOLEAN) * Count);
+  ASSERT (HasCreated != NULL);
+  if (HasCreated == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit_Start;
+  }
+  RequestCreate = AllocatePool (sizeof (BOOLEAN) * Count);
+  ASSERT (RequestCreate != NULL);
+  if (RequestCreate == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit_Start;
+  }
+
+  //
+  // Assume no children has been created.
+  // Assume the SIO interface hasn't been initialized.
+  //
+  ZeroMem (HasCreated, sizeof (BOOLEAN) * Count);
+
+  if (Status == EFI_ALREADY_STARTED) {
+    for (Node = GetFirstNode (&mSioDevPool);
+         !IsNull (&mSioDevPool, Node);
+         Node = GetNextNode (&mSioDevPool, Node)
+        ) {
+      SioDev = CR (Node, SIO_DEV, Link, SIO_DEV_SIGNATURE);
+      Status = gBS->HandleProtocol (
+                      SioDev->PciHandle,
+                      &gEfiDevicePathProtocolGuid,
+                      (VOID **) &DevicePath
+                      );
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // See if they are under the same PCI to ISA Bridge
+      //
+      if (CompareMem (DevicePath, ParentDevicePath, GetDevicePathSize (DevicePath)) == 0) {
+        for (Index = 0; Index < Count; Index++) {
+          if (CompareMem (&SioDev->Device, &Devices[Index], sizeof (EFI_SIO_ACPI_DEVICE_ID)) == 0) {
+            HasCreated[Index] = TRUE;
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  AcpiNode = (ACPI_HID_DEVICE_PATH *) RemainingDevicePath;
+  for (Index = 0; Index < Count; Index++) {
+    if ((AcpiNode == NULL) ||
+        ((AcpiNode->HID == Devices[Index].HID) && (AcpiNode->UID == Devices[Index].UID))
+       ) {
+      RequestCreate[Index] = TRUE;
+    } else {
+      RequestCreate[Index] = FALSE;
+    }
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    if (RequestCreate[Index] && !HasCreated[Index]) {
+      SioCreateDevice (Controller, &Devices[Index], ParentDevicePath, PciIo);
+    }
+  }
+Exit_Start:
+  if (Devices != NULL) {
+    FreePool (Devices);
+  }
+  if (HasCreated != NULL) {
+    FreePool (HasCreated);
+  }
+  if (RequestCreate != NULL) {
+    FreePool (RequestCreate);
+  }
+
+  return Status;
+}
+
+
+/**
+  Stop this driver on ControllerHandle.
+
+  @param[in]  This              Protocol instance pointer.
+  @param[in]  Controller        Handle of device to stop driver on
+  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
+                                children is zero stop the entire bus driver.
+  @param[in]  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval     EFI_SUCCESS       This driver is removed ControllerHandle
+  @retval     other             This driver was not removed from this device
+**/
+EFI_STATUS
+EFIAPI
+SioDriverStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN  EFI_HANDLE                     Controller,
+  IN  UINTN                          NumberOfChildren,
+  IN  EFI_HANDLE                     *ChildHandleBuffer
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+  BOOLEAN     AllChildrenStopped;
+
+  if (NumberOfChildren == 0) {
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiDevicePathProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+    gBS->CloseProtocol (
+           Controller,
+           &gEfiPciIoProtocolGuid,
+           This->DriverBindingHandle,
+           Controller
+           );
+    return EFI_SUCCESS;
+  }
+
+  AllChildrenStopped = TRUE;
+  for (Index = 0; Index < NumberOfChildren; Index++) {
+    Status = SioDestroyDevice (ChildHandleBuffer[Index]);
+    if (EFI_ERROR (Status)) {
+      AllChildrenStopped = FALSE;
+    }
+  }
+
+  if (AllChildrenStopped) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_DEVICE_ERROR;
+  }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.c b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.c
new file mode 100644
index 0000000000..379002b833
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.c
@@ -0,0 +1,249 @@
+/** @file
+  Super I/O Interface implementation.
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SioDriver.h"
+
+
+/**
+  Provides an interface to get a list of the current resources consumed by the device in the ACPI
+  Resource Descriptor format.
+
+  GetResources() returns a list of resources currently consumed by the device. The
+  ResourceList is a pointer to the buffer containing resource descriptors for the device. The
+  descriptors are in the format of Small or Large ACPI resource descriptor as defined by ACPI
+  specification (2.0 & 3.0). The buffer of resource descriptors is terminated with the 'End tag'
+  resource descriptor.
+
+  @param[in]  This                  Indicates a pointer to the calling context.
+  @param[out] ResourceList          A pointer to an ACPI resource descriptor list that defines the current resources
+                                    used by the device. Type ACPI_RESOURCE_HEADER_PTR is defined in the "Related
+                                    Definitions" below.
+
+  @retval     EFI_SUCCESS           The operation completed successfully
+  @retval     EFI_INVALID_PARAMETER ResourceList is NULL
+**/
+EFI_STATUS
+EFIAPI
+SioGetResources (
+  IN  CONST EFI_SIO_PROTOCOL    *This,
+  OUT ACPI_RESOURCE_HEADER_PTR  *ResourceList
+  )
+{
+  SIO_DEV                *SioDev;
+
+  if (ResourceList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SioDev = SIO_DEV_FROM_THIS (This);
+
+  return DeviceGetResources (&SioDev->Device, ResourceList);
+}
+
+
+/**
+  Provides a collection of resource descriptor lists. Each resource descriptor list in the collection
+  defines a combination of resources that can potentially be used by the device.
+
+  @param[in]  This                      Indicates a pointer to the calling context.
+  @param[out] ResourceCollection        Collection of the resource descriptor lists.
+
+  @retval     EFI_SUCCESS               The operation completed successfully
+  @retval     EFI_INVALID_PARAMETER     ResourceCollection is NULL
+**/
+EFI_STATUS
+EFIAPI
+SioPossibleResources (
+  IN  CONST EFI_SIO_PROTOCOL    *This,
+  OUT ACPI_RESOURCE_HEADER_PTR  *ResourceCollection
+  )
+{
+  SIO_DEV                *SioDev;
+
+  if (ResourceCollection == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SioDev = SIO_DEV_FROM_THIS (This);
+
+  return DevicePossibleResources (&SioDev->Device, ResourceCollection);
+}
+
+
+/**
+  Sets the resources for the device.
+
+  @param[in]  This                  Indicates a pointer to the calling context.
+  @param[in]  ResourceList          Pointer to the ACPI resource descriptor list. Type ACPI_RESOURCE_HEADER_PTR
+                                    is defined in the "Related Definitions" section of
+                                    EFI_SIO_PROTOCOL.GetResources().
+
+  @retval     EFI_SUCCESS           The operation completed successfully
+  @retval     EFI_INVALID_PARAMETER ResourceList is invalid
+  @retval     EFI_ACCESS_DENIED     Some of the resources in ResourceList are in use
+**/
+EFI_STATUS
+EFIAPI
+SioSetResources (
+  IN  CONST EFI_SIO_PROTOCOL    *This,
+  IN  ACPI_RESOURCE_HEADER_PTR  ResourceList
+  )
+{
+  SIO_DEV                   *SioDev;
+  ACPI_RESOURCE_HEADER_PTR  ResourcePtr;
+  ACPI_RESOURCE_HEADER_PTR  ResourceCollection;
+  ACPI_RESOURCE_HEADER_PTR  ResourcePtr2;
+  BOOLEAN                   Found;
+
+  ResourcePtr = ResourceList;
+  SioDev      = SIO_DEV_FROM_THIS (This);
+
+  //
+  // Check whether the resource is in the possible resource collection
+  //
+  DevicePossibleResources (&SioDev->Device, &ResourceCollection);
+
+  while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
+
+    Found        = FALSE;
+    ResourcePtr2 = ResourceCollection;
+    while (ResourcePtr2.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
+      if (ResourcePtr2.SmallHeader->Bits.Type == 0) {
+        //
+        // Small Header
+        //
+        if (CompareMem (
+              ResourcePtr2.SmallHeader,
+              ResourcePtr.SmallHeader,
+              ResourcePtr2.SmallHeader->Bits.Length + sizeof (*ResourcePtr2.SmallHeader)
+              ) == 0) {
+         Found = TRUE;
+         break;
+        }
+
+        ResourcePtr2.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr2.SmallHeader
+                                 + ResourcePtr2.SmallHeader->Bits.Length
+                                 + sizeof (*ResourcePtr2.SmallHeader));
+
+      } else {
+        //
+        // Large Header
+        //
+        if (CompareMem (
+              ResourcePtr2.LargeHeader,
+              ResourcePtr.LargeHeader,
+              ResourcePtr2.LargeHeader->Length + sizeof (*ResourcePtr2.LargeHeader)
+              ) == 0) {
+          Found = TRUE;
+          break;
+        }
+
+        ResourcePtr2.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr2.LargeHeader
+                                 + ResourcePtr2.LargeHeader->Length
+                                 + sizeof (*ResourcePtr2.LargeHeader));
+      }
+    }
+
+    if (!Found) {
+      return EFI_ACCESS_DENIED;
+    }
+
+    if (ResourcePtr.SmallHeader->Bits.Type == 0) {
+      ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader
+                              + ResourcePtr.SmallHeader->Bits.Length
+                              + sizeof (*ResourcePtr.SmallHeader));
+    } else {
+      ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader
+                              + ResourcePtr.LargeHeader->Length
+                              + sizeof (*ResourcePtr.LargeHeader));
+    }
+  }
+
+  //
+  // ResourceList can be set
+  //
+  return DeviceSetResources (&SioDev->Device, ResourceList);
+}
+
+
+/**
+  Provides a low level access to the registers for the Super I/O.
+
+  @param[in]        This                  Indicates a pointer to the calling context.
+  @param[in]        Write                 Specifies the type of the register operation. If this parameter is TRUE,
+                                          Value is interpreted as an input parameter and the operation is a register write.
+                                          If this parameter is FALSE, Value is interpreted as an output parameter and the
+                                          operation is a register read.
+  @param[in]        ExitCfgMode           Exit Configuration Mode Indicator. If this parameter is set to TRUE, the
+                                          Super I/O driver will turn off configuration mode of the Super I/O prior to returning
+                                          from this function. If this parameter is set to FALSE, the Super I/O driver will
+                                          leave Super I/O in the configuration mode.
+                                          The Super I/O driver must track the current state of the Super I/O and enable the
+                                          configuration mode of Super I/O if necessary prior to register access.
+  @param[in]        Register              Register number.
+  @param[in, out]   Value                 If Write is TRUE, Value is a pointer to the buffer containing the byte of data to be
+                                          written to the Super I/O register. If Write is FALSE, Value is a pointer to the
+                                          destination buffer for the byte of data to be read from the Super I/O register.
+
+  @retval           EFI_SUCCESS           The operation completed successfully
+  @retval           EFI_INVALID_PARAMETER The Value is NULL
+  @retval           EFI_INVALID_PARAMETER Invalid Register number
+**/
+EFI_STATUS
+EFIAPI
+SioRegisterAccess (
+  IN CONST EFI_SIO_PROTOCOL    *This,
+  IN BOOLEAN                   Write,
+  IN BOOLEAN                   ExitCfgMode,
+  IN UINT8                     Register,
+  IN OUT UINT8                 *Value
+  )
+{
+  if (Value == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Provides an interface for a table based programming of the Super I/O registers.
+
+  The Modify() function provides an interface for table based programming of the Super I/O
+  registers. This function can be used to perform programming of multiple Super I/O registers with a
+  single function call. For each table entry, the Register is read, its content is bitwise ANDed with
+  AndMask, and then ORed with OrMask before being written back to the Register. The Super
+  I/O driver must track the current state of the Super I/O and enable the configuration mode of Super I/
+  O if necessary prior to table processing. Once the table is processed, the Super I/O device has to be
+  returned to the original state.
+
+  @param[in] This                  Indicates a pointer to the calling context.
+  @param[in] Command               A pointer to an array of NumberOfCommands EFI_SIO_REGISTER_MODIFY
+                                   structures. Each structure specifies a single Super I/O register modify operation.
+                                   Type EFI_SIO_REGISTER_MODIFY is defined in the "Related Definitions" below.
+  @param[in] NumberOfCommands      Number of elements in the Command array.
+
+  @retval    EFI_SUCCESS           The operation completed successfully
+  @retval    EFI_INVALID_PARAMETER Command is NULL
+**/
+EFI_STATUS
+EFIAPI
+SioModify (
+  IN CONST EFI_SIO_PROTOCOL        *This,
+  IN CONST EFI_SIO_REGISTER_MODIFY *Command,
+  IN UINTN                         NumberOfCommands
+  )
+{
+
+  if (Command == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.h b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.h
new file mode 100644
index 0000000000..5368f94bcd
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/ComponentName.h
@@ -0,0 +1,87 @@
+/** @file
+  Install Base and Size Info Ppi for Firmware Volume Recovery.
+
+  Copyright (c) 2013 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that 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.
+  @param  DriverName 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
+SioComponentNameGetDriverName (
+  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 an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle 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      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         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller 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.
+  @param  ControllerName   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 NULL.
+  @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
+SioComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL   *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  );
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/LegacySioDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/LegacySioDxe.inf
new file mode 100644
index 0000000000..275f36ca47
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/LegacySioDxe.inf
@@ -0,0 +1,54 @@
+## @file
+# Module information that produces the
+# EFI_SIO_PROTOCOL.
+#
+# Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = HitachiH8s2113Dxe
+  FILE_GUID                      = 7807E404-8281-4FF1-8457-0B54BABE263F
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = UEFI_DRIVER
+  ENTRY_POINT                    = SioDriverEntryPoint
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  DebugLib
+  MemoryAllocationLib
+  PcdLib
+  DevicePathLib
+  IoLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  S3BootScriptLib
+  S3IoLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+  SioChip.c
+  SioChip.h
+  SioService.c
+  SioService.h
+  SioDriver.c
+  SioDriver.h
+  ComponentName.c
+
+[Protocols]
+  gEfiPciIoProtocolGuid                         ## CONSUMES
+  gEfiDevicePathProtocolGuid                    ## PRODUCES
+  gEfiSioProtocolGuid                           ## PRODUCES
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/Register.h b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/Register.h
new file mode 100644
index 0000000000..f61f713cf2
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/Register.h
@@ -0,0 +1,15 @@
+/** @file
+  Super I/O register definitions
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _REGISTER_H_
+#define _REGISTER_H_
+
+#define EC_COMMAND_PORT 0x66
+#define EC_DATA_PORT    0x62
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.h b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.h
new file mode 100644
index 0000000000..48e28c44b0
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioChip.h
@@ -0,0 +1,195 @@
+/** @file
+  Super I/O specific header.
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SIO_H_
+#define _SIO_H_
+
+
+#include "Register.h"
+
+typedef
+UINT8
+(EFIAPI *LOCAL_IO_WRITE8) (
+  IN      UINTN                     Port,
+  IN      UINT8                     Value
+  );
+
+#define RESOURCE_IO    BIT0
+#define RESOURCE_IRQ   BIT1
+#define RESOURCE_DMA   BIT2
+#define RESOURCE_MEM   BIT3
+
+#pragma pack(1)
+
+typedef struct {
+  EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR  Io;
+  EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR              Irq;
+  EFI_ACPI_END_TAG_DESCRIPTOR                 End;
+} ACPI_SIO_RESOURCES_IO_IRQ;
+#pragma pack()
+
+typedef struct {
+  UINT32                      HID;
+  UINT32                      UID;
+} EFI_SIO_ACPI_DEVICE_ID;
+
+typedef struct {
+  EFI_SIO_ACPI_DEVICE_ID      Device;
+  UINT8                       DeviceId;
+  UINT8                       ResourceMask;
+  ACPI_RESOURCE_HEADER_PTR    Resources;
+  ACPI_RESOURCE_HEADER_PTR    PossibleResources;
+} DEVICE_INFO;
+
+
+/**
+  Initialize the SIO chip for S3.
+**/
+VOID
+SioInitForS3 (
+  VOID
+  );
+
+
+/**
+  Return the supported devices.
+
+  @param[out] Devices         Pointer to pointer of EFI_SIO_ACPI_DEVICE_ID.
+                              Caller is responsible to free the buffer.
+  @param[out] Count           Pointer to UINTN holding the device count.
+**/
+VOID
+DeviceGetList (
+  OUT EFI_SIO_ACPI_DEVICE_ID **Devices,
+  OUT UINTN                  *Count
+  );
+
+
+/**
+  Program the SIO chip to enable the specified device using the default resource.
+
+  @param[in]  Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+**/
+VOID
+DeviceEnable (
+  IN EFI_SIO_ACPI_DEVICE_ID   *Device
+  );
+
+
+/**
+  Get the possible ACPI resources for specified device.
+
+  @param[in]  Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[out] Resources       Pointer to ACPI_RESOURCE_HEADER_PTR.
+
+  @retval     EFI_SUCCESS     The resources are returned successfully.
+**/
+EFI_STATUS
+DevicePossibleResources (
+  IN  EFI_SIO_ACPI_DEVICE_ID   *Device,
+  OUT ACPI_RESOURCE_HEADER_PTR *Resources
+  );
+
+
+/**
+  Set the ACPI resources for specified device.
+
+  The SIO chip is programmed to use the new resources and the
+  resources setting are saved. The function assumes the resources
+  are valid.
+
+  @param[in]  Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[in]  Resources       ACPI_RESOURCE_HEADER_PTR.
+
+  @retval     EFI_SUCCESS     The resources are set successfully.
+**/
+EFI_STATUS
+DeviceSetResources (
+  IN EFI_SIO_ACPI_DEVICE_ID   *Device,
+  IN ACPI_RESOURCE_HEADER_PTR Resources
+  );
+
+
+/**
+  Get the ACPI resources for specified device.
+
+  @param[in]  Device          Pointer to EFI_SIO_ACPI_DEVICE_ID.
+  @param[out] Resources       Pointer to ACPI_RESOURCE_HEADER_PTR.
+
+  @retval     EFI_SUCCESS     The resources are returned successfully.
+**/
+EFI_STATUS
+DeviceGetResources (
+  IN  EFI_SIO_ACPI_DEVICE_ID   *Device,
+  OUT ACPI_RESOURCE_HEADER_PTR *Resources
+  );
+
+
+/**
+  Program the SIO chip to enter the configure mode.
+**/
+VOID
+EnterConfigMode (
+  VOID
+  );
+
+
+/**
+  Program the SIO chip to exit the configure mode.
+**/
+VOID
+ExitConfigMode (
+  VOID
+  );
+
+
+/**
+  Perform a 8-bit I/O write to SIO register.
+
+  @param[in]  Index  The register index.
+  @param[in]  Data   The value to write to register.
+**/
+VOID
+WriteRegister (
+  IN  UINT8            Index,
+  IN  UINT8            Data
+  );
+
+
+/**
+  Perform a 8-bit I/O read from SIO register.
+
+  @param[in]  Index  The register index.
+
+  @retval     Value  The value written to the register.
+**/
+UINT8
+ReadRegister (
+  IN  UINT8            Index
+  );
+
+//
+// Prototypes for the sio internal function
+//
+//
+// Internal function
+//
+
+
+/**
+  Find Super I/O controller.
+
+  @retval     EFI_SUCCESS       Super I/O controller exists.
+  @retval     EFI_UNSUPPORTED   Super I/O controller does not exist.
+**/
+EFI_STATUS
+SioInit (
+  VOID
+  );
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h
new file mode 100644
index 0000000000..2e75871f7f
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioDriver.h
@@ -0,0 +1,134 @@
+/** @file
+  Header file for Driver Binding Protocol.
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SIO_DRIVER_H_
+#define _SIO_DRIVER_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/DriverBinding.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DevicePath.h>
+
+//
+// Driver Produced Protocol Prototypes
+//
+#include <Protocol/SuperIo.h>
+
+
+#include "SioChip.h"
+#include "SioService.h"
+#include "ComponentName.h"
+
+//
+// Global Variables definitions
+//
+extern EFI_DRIVER_BINDING_PROTOCOL   mSioDriver;
+extern EFI_COMPONENT_NAME_PROTOCOL   mSioComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL  mSioComponentName2;
+
+//
+// SIO device private data structure
+//
+#define SIO_DEV_SIGNATURE SIGNATURE_32 ('_', 'S', 'I', 'O')
+
+typedef struct _SIO_DEV {
+  UINT32                   Signature;
+  EFI_HANDLE               PciHandle;
+  EFI_SIO_ACPI_DEVICE_ID   Device;
+  EFI_HANDLE               Handle;
+  EFI_SIO_PROTOCOL         Sio;
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+  LIST_ENTRY               Link;
+} SIO_DEV;
+
+#define SIO_DEV_FROM_THIS(a) CR (a, SIO_DEV, Sio, SIO_DEV_SIGNATURE)
+
+//
+// Prototypes for Driver model protocol interface
+//
+
+
+/**
+  Test to see if this driver supports Controller Handle.
+
+  @param[in]  This                Protocol instance pointer.
+  @param[in]  Controller          Handle of device to test
+  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
+                                  device to start.
+
+  @retval     EFI_SUCCESS         This driver supports this device
+  @retval     EFI_ALREADY_STARTED This driver is already running on this device
+  @retval     other               This driver does not support this device
+**/
+EFI_STATUS
+EFIAPI
+SioDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+
+/**
+  Start this driver on ControllerHandle.
+
+  @param[in]  This                 Protocol instance pointer.
+  @param[in]  Controller           Handle of device to bind driver to
+  @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
+                                   device to start.
+
+  @retval     EFI_SUCCESS          This driver is added to ControllerHandle
+  @retval     EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
+  @retval     other                This driver does not support this device
+**/
+EFI_STATUS
+EFIAPI
+SioDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+
+/**
+  Stop this driver on ControllerHandle.
+
+  @param[in]  This              Protocol instance pointer.
+  @param[in]  Controller        Handle of device to stop driver on
+  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
+                                children is zero stop the entire bus driver.
+  @param[in]  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval     EFI_SUCCESS       This driver is removed ControllerHandle
+  @retval     other             This driver was not removed from this device
+**/
+EFI_STATUS
+EFIAPI
+SioDriverStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN  EFI_HANDLE                     Controller,
+  IN  UINTN                          NumberOfChildren,
+  IN  EFI_HANDLE                     *ChildHandleBuffer
+  );
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.h b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.h
new file mode 100644
index 0000000000..6a8081dc6e
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/LegacySioDxe/SioService.h
@@ -0,0 +1,143 @@
+/** @file
+  Super I/O Interface function declarations.
+
+  Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SIO_ACPI_H_
+#define _SIO_ACPI_H_
+
+//
+// Prototypes for the SIO protocol interface
+//
+
+
+/**
+  Provides an interface to get a list of the current resources consumed by the device in the ACPI
+  Resource Descriptor format.
+
+  GetResources() returns a list of resources currently consumed by the device. The
+  ResourceList is a pointer to the buffer containing resource descriptors for the device. The
+  descriptors are in the format of Small or Large ACPI resource descriptor as defined by ACPI
+  specification (2.0 & 3.0). The buffer of resource descriptors is terminated with the 'End tag'
+  resource descriptor.
+
+  @param[in]    This                  Indicates a pointer to the calling context.
+  @param[out]   ResourceList          A pointer to an ACPI resource descriptor list that defines the current resources
+                                      used by the device. Type ACPI_RESOURCE_HEADER_PTR is defined in the "Related
+                                      Definitions" below.
+
+  @retval       EFI_SUCCESS           The operation completed successfully
+  @retval       EFI_INVALID_PARAMETER ResourceList is NULL
+**/
+EFI_STATUS
+EFIAPI
+SioGetResources (
+  IN  CONST EFI_SIO_PROTOCOL    *This,
+  OUT ACPI_RESOURCE_HEADER_PTR  *ResourceList
+  );
+
+
+/**
+  Sets the resources for the device.
+
+  @param[in]  This                  Indicates a pointer to the calling context.
+  @param[in]  ResourceList          Pointer to the ACPI resource descriptor list. Type ACPI_RESOURCE_HEADER_PTR
+                                    is defined in the "Related Definitions" section of
+                                    EFI_SIO_PROTOCOL.GetResources().
+
+  @retval     EFI_SUCCESS           The operation completed successfully
+  @retval     EFI_INVALID_PARAMETER ResourceList is invalid
+  @retval     EFI_ACCESS_DENIED     Some of the resources in ResourceList are in use
+**/
+EFI_STATUS
+EFIAPI
+SioSetResources (
+  IN  CONST EFI_SIO_PROTOCOL    *This,
+  IN  ACPI_RESOURCE_HEADER_PTR  ResourceList
+  );
+
+
+/**
+  Provides a collection of resource descriptor lists. Each resource descriptor list in the collection
+  defines a combination of resources that can potentially be used by the device.
+
+  @param[in]  This                      Indicates a pointer to the calling context.
+  @param[out] ResourceCollection        Collection of the resource descriptor lists.
+
+  @retval     EFI_SUCCESS               The operation completed successfully
+  @retval     EFI_INVALID_PARAMETER     ResourceCollection is NULL
+**/
+EFI_STATUS
+EFIAPI
+SioPossibleResources (
+  IN  CONST EFI_SIO_PROTOCOL    *This,
+  OUT ACPI_RESOURCE_HEADER_PTR  *ResourceCollection
+  );
+
+
+/**
+  Provides a low level access to the registers for the Super I/O.
+
+  @param[in]        This                  Indicates a pointer to the calling context.
+  @param[in]        Write                 Specifies the type of the register operation. If this parameter is TRUE,
+                                          Value is interpreted as an input parameter and the operation is a register write.
+                                          If this parameter is FALSE, Value is interpreted as an output parameter and the
+                                          operation is a register read.
+  @param[in]        ExitCfgMode           Exit Configuration Mode Indicator. If this parameter is set to TRUE, the 
+                                          Super I/O driver will turn off configuration mode of the Super I/O prior to returning
+                                          from this function. If this parameter is set to FALSE, the Super I/O driver will
+                                          leave Super I/O in the configuration mode.
+                                          The Super I/O driver must track the current state of the Super I/O and enable the
+                                          configuration mode of Super I/O if necessary prior to register access.
+  @param[in]        Register              Register number.
+  @param[in, out]   Value                 If Write is TRUE, Value is a pointer to the buffer containing the byte of data to be
+                                          written to the Super I/O register. If Write is FALSE, Value is a pointer to the
+                                          destination buffer for the byte of data to be read from the Super I/O register.
+
+  @retval           EFI_SUCCESS           The operation completed successfully
+  @retval           EFI_INVALID_PARAMETER The Value is NULL
+  @retval           EFI_INVALID_PARAMETER Invalid Register number
+**/
+EFI_STATUS
+EFIAPI
+SioRegisterAccess (
+  IN CONST EFI_SIO_PROTOCOL    *This,
+  IN BOOLEAN                   Write,
+  IN BOOLEAN                   ExitCfgMode,
+  IN UINT8                     Register,
+  IN OUT UINT8                 *Value
+  );
+
+
+/**
+  Provides an interface for a table based programming of the Super I/O registers.
+
+  The Modify() function provides an interface for table based programming of the Super I/O
+  registers. This function can be used to perform programming of multiple Super I/O registers with a
+  single function call. For each table entry, the Register is read, its content is bitwise ANDed with
+  AndMask, and then ORed with OrMask before being written back to the Register. The Super
+  I/O driver must track the current state of the Super I/O and enable the configuration mode of Super I/
+  O if necessary prior to table processing. Once the table is processed, the Super I/O device has to be
+  returned to the original state.
+
+  @param[in] This                  Indicates a pointer to the calling context.
+  @param[in] Command               A pointer to an array of NumberOfCommands EFI_SIO_REGISTER_MODIFY
+                                   structures. Each structure specifies a single Super I/O register modify operation.
+                                   Type EFI_SIO_REGISTER_MODIFY is defined in the "Related Definitions" below.
+  @param[in] NumberOfCommands      Number of elements in the Command array.
+
+  @retval    EFI_SUCCESS           The operation completed successfully
+  @retval    EFI_INVALID_PARAMETER Command is NULL
+**/
+EFI_STATUS
+EFIAPI
+SioModify (
+  IN CONST EFI_SIO_PROTOCOL        *This,
+  IN CONST EFI_SIO_REGISTER_MODIFY *Command,
+  IN UINTN                         NumberOfCommands
+  );
+
+#endif
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (3 preceding siblings ...)
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 6/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
  6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add AcpiTable, Logo image, dec file and GOP driver

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 .../MinPlatformAcpiTables/AcpiPlatform.c           | 1579 ++++++++++++++++++++
 .../AcpiTables/MinPlatformAcpiTables/Facs/Facs.c   |   84 ++
 .../AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c   |  359 +++++
 .../AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c   |   78 +
 .../AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c   |   46 +
 .../SimicsVideoDxe/ComponentName.c                 |  205 +++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c     | 1011 +++++++++++++
 .../SimicsVideoDxe/DriverSupportedEfiVersion.c     |   15 +
 .../Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c  |  416 ++++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c |  341 +++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c    |  302 ++++
 .../SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf   |   31 +
 .../Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl   |  821 ++++++++++
 .../MinPlatformAcpiTables/AcpiPlatform.h           |   45 +
 .../MinPlatformAcpiTables/AcpiPlatform.inf         |  105 ++
 .../Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h |   75 +
 Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp    |  Bin 0 -> 141078 bytes
 Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec |  152 ++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h     |  507 +++++++
 .../SimicsVideoDxe/SimicsVideoDxe.inf              |   74 +
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm  |  279 ++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h    |  701 +++++++++
 .../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh   |   79 +
 23 files changed, 7305 insertions(+)
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh

diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
new file mode 100644
index 0000000000..1edac89240
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
@@ -0,0 +1,1579 @@
+/** @file
+  ACPI Platform Driver
+
+  Copyright (c) 2019 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_HEADER                        *McfgTable;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_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_BASE_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_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+    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_HEADER) + 
+                                      sizeof (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_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_BASE_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/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
new file mode 100644
index 0000000000..e649b5b89c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/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) 2019 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/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
new file mode 100644
index 0000000000..d1fe98e24b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/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) 2019 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/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
new file mode 100644
index 0000000000..e9528b0ec3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/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) 2019 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/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
new file mode 100644
index 0000000000..625b7560bb
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
@@ -0,0 +1,46 @@
+/** @file
+  ACPI WSMT table
+
+  Copyright (c) 2019 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/SimicsVideoDxe/ComponentName.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
new file mode 100644
index 0000000000..b1286b0b64
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
@@ -0,0 +1,205 @@
+/** @file
+  Component name for the QEMU video controller.
+
+  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.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/SimicsVideoDxe/Driver.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
new file mode 100644
index 0000000000..15f03812bf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.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 "Simics.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/SimicsVideoDxe/DriverSupportedEfiVersion.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
new file mode 100644
index 0000000000..a743056382
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
@@ -0,0 +1,15 @@
+/** @file
+  Driver supported version protocol for the QEMU video driver.
+
+  Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.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/SimicsVideoDxe/Gop.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
new file mode 100644
index 0000000000..bbb82fe867
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
@@ -0,0 +1,416 @@
+/** @file
+  Graphics Output Protocol functions for the QEMU video controller.
+
+  Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.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/SimicsVideoDxe/Initialize.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
new file mode 100644
index 0000000000..c8a76636af
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
@@ -0,0 +1,341 @@
+/** @file
+  Graphics Output Protocol functions for the QEMU video controller.
+
+  Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.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/SimicsVideoDxe/VbeShim.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
new file mode 100644
index 0000000000..ba13e3d8e5
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.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 "Simics.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/AcpiTables/AcpiTables.inf b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
new file mode 100644
index 0000000000..b8d326cdb6
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
@@ -0,0 +1,31 @@
+## @file
+#  Component description file for PlatformAcpiTables module.
+#
+#  ACPI table data and ASL sources required to boot the platform.
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformAcpiTables
+  FILE_GUID                      = 7E374E25-8E01-4FEE-87F2-390C23C606CD
+  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
+#
+
+[Sources]
+  Platform.h
+  Dsdt.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
new file mode 100644
index 0000000000..8a6c3792ba
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
@@ -0,0 +1,821 @@
+/** @file
+  Contains root level name space objects for the platform
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+DefinitionBlock ("Dsdt.aml", "DSDT", 1, "INTEL ", "SIMICS  ", 4) {
+  //
+  // System Sleep States
+  //
+  Name (\_S3, Package () {5, 5, 0, 0})
+  Name (\_S4, Package () {6, 6, 0, 0})
+  Name (\_S5, Package () {7, 7, 0, 0})
+
+  Name (GPIC, Zero)
+  Method (_PIC, 1, NotSerialized)  // _PIC: Interrupt Model
+  {
+      GPIC = Arg0
+  }
+  //
+  //  System Bus
+  //
+  Scope (\_SB) {
+    //
+    // PCI Root Bridge
+    //
+    Device (PCI0) {
+      Name (_HID, EISAID ("PNP0A03"))
+      Name (_ADR, 0x00000000)
+      Name (_BBN, 0x00)
+      Name (_UID, 0x00)
+
+
+      // Current resource settings
+      Name (_CRS, ResourceTemplate () {
+        WORDBusNumber (          // Bus number resource (0); the bridge produces bus numbers for its subsequent buses
+          ResourceProducer,      // bit 0 of general flags is 1
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is fixed
+          PosDecode,             // PosDecode
+          0x0000,                // Granularity
+          0x0000,                // Min
+          0x00FF,                // Max
+          0x0000,                // Translation
+          0x0100                 // Range Length = Max-Min+1
+          )
+
+        IO (Decode16, 0xCF8, 0xCF8, 0x01, 0x08)       //Consumed resource (0xCF8-0xCFF)
+
+        WORDIO (                 // Consumed-and-produced resource (all I/O below CF8)
+          ResourceProducer,      // bit 0 of general flags is 0
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is fixed
+          PosDecode,
+          EntireRange,
+          0x0000,                // Granularity
+          0x0000,                // Min
+          0x0CF7,                // Max
+          0x0000,                // Translation
+          0x0CF8                 // Range Length
+          )
+
+        WORDIO (                 // Consumed-and-produced resource (all I/O above CFF)
+          ResourceProducer,      // bit 0 of general flags is 0
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is fixed
+          PosDecode,
+          EntireRange,
+          0x0000,                // Granularity
+          0x0D00,                // Min
+          0xFFFF,                // Max
+          0x0000,                // Translation
+          0xF300                 // Range Length
+          )
+
+        DWORDMEMORY (            // Descriptor for legacy VGA video RAM
+          ResourceProducer,      // bit 0 of general flags is 0
+          PosDecode,
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is Fixed
+          Cacheable,
+          ReadWrite,
+          0x00000000,            // Granularity
+          0x000A0000,            // Min
+          0x000BFFFF,            // Max
+          0x00000000,            // Translation
+          0x00020000             // Range Length
+          )
+
+        DWORDMEMORY (            // Descriptor for 32-bit MMIO
+          ResourceProducer,      // bit 0 of general flags is 0
+          PosDecode,
+          MinFixed,              // Range is fixed
+          MaxFixed,              // Range is Fixed
+          NonCacheable,
+          ReadWrite,
+          0x00000000,            // Granularity
+          0xF0000000,            // Min
+          0xFBFFFFFF,            // Max
+          0x00000000,            // Translation
+          0x0C000000,            // Range Length
+          ,                      // ResourceSourceIndex
+          ,                      // ResourceSource
+          PW32                   // DescriptorName
+          )
+      })
+
+      //
+      // PCI Interrupt Routing Table - PIC Mode Only
+      //
+      // If you change the IRQ mapping here you also need
+      // to change the mapping in the south bridge
+      // (pci-conf.py) and in the BIOS.
+      // INTA -> 0xa (10)
+      // INTB -> 0xb (11)
+      // INTC -> 0xa (10)
+      // INTD -> 0xb (11)
+
+       Method (_PRT, 0, NotSerialized) {
+           If (GPIC) {
+             Return (AR00) // APIC Mode
+           }
+           Return (PR00) // PIC Mode
+      }
+
+      Name (PR00, Package(){
+            Package () {0x000FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            //
+            // Bus 0, Device 1
+            //
+            Package () {0x0001FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0002FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0002FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0002FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0002FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+            //
+            // Bus 0, Device 3
+            //
+            Package () {0x0003FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0003FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0003FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0003FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0004FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0004FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0004FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0004FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0005FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0005FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0005FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0005FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0006FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0006FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0006FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0006FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0007FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0007FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0007FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0007FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0008FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0008FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0008FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0008FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0009FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0009FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0009FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0009FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000AFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000AFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000AFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000AFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000BFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000BFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000BFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000BFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000CFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000CFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000CFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000CFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000DFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000DFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000DFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000DFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000EFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000EFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000EFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000EFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x000FFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x000FFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x000FFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x000FFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00010FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00010FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00010FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00010FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00011FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00011FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00011FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00011FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00012FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00012FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00012FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00012FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00013FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00013FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00013FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00013FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00014FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00014FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00014FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00014FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00015FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00015FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00015FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00015FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00016FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00016FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00016FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00016FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00017FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00017FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00017FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00017FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00018FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00018FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00018FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00018FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001EFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001EFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001EFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001EFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x00019FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x00019FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x00019FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x00019FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001AFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001AFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001AFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001AFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001BFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001BFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001BFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001BFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001CFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001CFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001CFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001CFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001DFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001DFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001DFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001DFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+            Package () {0x0001FFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+            Package () {0x0001FFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+            Package () {0x0001FFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+            Package () {0x0001FFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+          }
+        )
+
+      Name(AR00, Package(){
+
+            Package () {0x000FFFF, 0x00, 0, 16},
+            Package () {0x000FFFF, 0x01, 0, 17},
+            Package () {0x000FFFF, 0x02, 0, 18},
+            Package () {0x000FFFF, 0x03, 0, 19},
+
+            //
+            // Bus 0, Device 1
+            //
+            Package () {0x0001FFFF, 0x00, 0, 16},
+            Package () {0x0001FFFF, 0x01, 0, 17},
+            Package () {0x0001FFFF, 0x02, 0, 18},
+            Package () {0x0001FFFF, 0x03, 0, 19},
+
+            Package () {0x0002FFFF, 0x00, 0, 16},
+            Package () {0x0002FFFF, 0x01, 0, 17},
+            Package () {0x0002FFFF, 0x02, 0, 18},
+            Package () {0x0002FFFF, 0x03, 0, 19},
+            //
+            // Bus 0, Device 3
+            //
+            Package () {0x0003FFFF, 0x00, 0, 16},
+            Package () {0x0003FFFF, 0x01, 0, 17},
+            Package () {0x0003FFFF, 0x02, 0, 18},
+            Package () {0x0003FFFF, 0x03, 0, 19},
+
+            Package () {0x0004FFFF, 0x00, 0, 16},
+            Package () {0x0004FFFF, 0x01, 0, 17},
+            Package () {0x0004FFFF, 0x02, 0, 18},
+            Package () {0x0004FFFF, 0x03, 0, 19},
+
+            Package () {0x0005FFFF, 0x00, 0, 16},
+            Package () {0x0005FFFF, 0x01, 0, 17},
+            Package () {0x0005FFFF, 0x02, 0, 18},
+            Package () {0x0005FFFF, 0x03, 0, 19},
+
+            Package () {0x0006FFFF, 0x00, 0, 16},
+            Package () {0x0006FFFF, 0x01, 0, 17},
+            Package () {0x0006FFFF, 0x02, 0, 18},
+            Package () {0x0006FFFF, 0x03, 0, 19},
+
+            Package () {0x0007FFFF, 0x00, 0, 16},
+            Package () {0x0007FFFF, 0x01, 0, 17},
+            Package () {0x0007FFFF, 0x02, 0, 18},
+            Package () {0x0007FFFF, 0x03, 0, 19},
+
+            Package () {0x0008FFFF, 0x00, 0, 16},
+            Package () {0x0008FFFF, 0x01, 0, 17},
+            Package () {0x0008FFFF, 0x02, 0, 18},
+            Package () {0x0008FFFF, 0x03, 0, 19},
+
+            Package () {0x0009FFFF, 0x00, 0, 16},
+            Package () {0x0009FFFF, 0x01, 0, 17},
+            Package () {0x0009FFFF, 0x02, 0, 18},
+            Package () {0x0009FFFF, 0x03, 0, 19},
+
+            Package () {0x000AFFFF, 0x00, 0, 16},
+            Package () {0x000AFFFF, 0x01, 0, 17},
+            Package () {0x000AFFFF, 0x02, 0, 18},
+            Package () {0x000AFFFF, 0x03, 0, 19},
+
+            Package () {0x000BFFFF, 0x00, 0, 16},
+            Package () {0x000BFFFF, 0x01, 0, 17},
+            Package () {0x000BFFFF, 0x02, 0, 18},
+            Package () {0x000BFFFF, 0x03, 0, 19},
+
+            Package () {0x000CFFFF, 0x00, 0, 16},
+            Package () {0x000CFFFF, 0x01, 0, 17},
+            Package () {0x000CFFFF, 0x02, 0, 18},
+            Package () {0x000CFFFF, 0x03, 0, 19},
+
+            Package () {0x000DFFFF, 0x00, 0, 16},
+            Package () {0x000DFFFF, 0x01, 0, 17},
+            Package () {0x000DFFFF, 0x02, 0, 18},
+            Package () {0x000DFFFF, 0x03, 0, 19},
+
+            Package () {0x000EFFFF, 0x00, 0, 16},
+            Package () {0x000EFFFF, 0x01, 0, 17},
+            Package () {0x000EFFFF, 0x02, 0C, 18},
+            Package () {0x000EFFFF, 0x03, 0, 19},
+
+            Package () {0x000FFFFF, 0x00, 0, 16},
+            Package () {0x000FFFFF, 0x01, 0, 17},
+            Package () {0x000FFFFF, 0x02, 0, 18},
+            Package () {0x000FFFFF, 0x03, 0, 19},
+
+            Package () {0x00010FFFF, 0x00, 0, 16},
+            Package () {0x00010FFFF, 0x01, 0, 17},
+            Package () {0x00010FFFF, 0x02, 0, 18},
+            Package () {0x00010FFFF, 0x03, 0, 19},
+
+            Package () {0x00011FFFF, 0x00, 0, 16},
+            Package () {0x00011FFFF, 0x01, 0, 17},
+            Package () {0x00011FFFF, 0x02, 0, 18},
+            Package () {0x00011FFFF, 0x03, 0, 19},
+
+            Package () {0x00012FFFF, 0x00, 0, 16},
+            Package () {0x00012FFFF, 0x01, 0, 17},
+            Package () {0x00012FFFF, 0x02, 0, 18},
+            Package () {0x00012FFFF, 0x03, 0, 19},
+
+            Package () {0x00013FFFF, 0x00, 0, 16},
+            Package () {0x00013FFFF, 0x01, 0, 17},
+            Package () {0x00013FFFF, 0x02, 0, 18},
+            Package () {0x00013FFFF, 0x03, 0, 19},
+
+            Package () {0x00014FFFF, 0x00, 0, 16},
+            Package () {0x00014FFFF, 0x01, 0, 17},
+            Package () {0x00014FFFF, 0x02, 0, 18},
+            Package () {0x00014FFFF, 0x03, 0, 19},
+
+            Package () {0x00015FFFF, 0x00, 0, 16},
+            Package () {0x00015FFFF, 0x01, 0, 17},
+            Package () {0x00015FFFF, 0x02, 0, 18},
+            Package () {0x00015FFFF, 0x03, 0, 19},
+
+            Package () {0x00016FFFF, 0x00, 0, 16},
+            Package () {0x00016FFFF, 0x01, 0, 17},
+            Package () {0x00016FFFF, 0x02, 0, 18},
+            Package () {0x00016FFFF, 0x03, 0, 19},
+
+            Package () {0x00017FFFF, 0x00, 0, 16},
+            Package () {0x00017FFFF, 0x01, 0, 17},
+            Package () {0x00017FFFF, 0x02, 0, 18},
+            Package () {0x00017FFFF, 0x03, 0, 19},
+
+            Package () {0x00018FFFF, 0x00, 0, 16},
+            Package () {0x00018FFFF, 0x01, 0, 17},
+            Package () {0x00018FFFF, 0x02, 0, 18},
+            Package () {0x00018FFFF, 0x03, 0, 19},
+
+            Package () {0x0001EFFFF, 0x00, 0, 16},
+            Package () {0x0001EFFFF, 0x01, 0, 17},
+            Package () {0x0001EFFFF, 0x02, 0, 18},
+            Package () {0x0001EFFFF, 0x03, 0, 19},
+
+            Package () {0x00019FFFF, 0x00, 0, 16},
+            Package () {0x00019FFFF, 0x01, 0, 17},
+            Package () {0x00019FFFF, 0x02, 0, 18},
+            Package () {0x00019FFFF, 0x03, 0, 19},
+
+            Package () {0x0001AFFFF, 0x00, 0, 16},
+            Package () {0x0001AFFFF, 0x01, 0, 17},
+            Package () {0x0001AFFFF, 0x02, 0, 18},
+            Package () {0x0001AFFFF, 0x03, 0, 19},
+
+            Package () {0x0001BFFFF, 0x00, 0, 16},
+            Package () {0x0001BFFFF, 0x01, 0, 17},
+            Package () {0x0001BFFFF, 0x02, 0, 18},
+            Package () {0x0001BFFFF, 0x03, 0, 19},
+
+            Package () {0x0001CFFFF, 0x00, 0, 16},
+            Package () {0x0001CFFFF, 0x01, 0, 17},
+            Package () {0x0001CFFFF, 0x02, 0, 18},
+            Package () {0x0001CFFFF, 0x03, 0, 19},
+
+            Package () {0x0001DFFFF, 0x00, 0, 16},
+            Package () {0x0001DFFFF, 0x01, 0, 17},
+            Package () {0x0001DFFFF, 0x02, 0, 18},
+            Package () {0x0001DFFFF, 0x03, 0, 19},
+
+            Package () {0x0001FFFFF, 0x00, 0, 16},
+            Package () {0x0001FFFFF, 0x01, 0, 17},
+            Package () {0x0001FFFFF, 0x02, 0, 18},
+            Package () {0x0001FFFFF, 0x03, 0, 19},
+          }
+        )
+
+      //
+      // PCI to ISA Bridge (Bus 0, Device 7, Function 0)
+      //
+      Device (LPC) {
+        Name (_ADR, 0x001F0000)
+
+        //
+        // PCI Interrupt Routing Configuration Registers
+        //
+        OperationRegion (PRR0, PCI_Config, 0x60, 0x0C)
+        Field (PRR0, ANYACC, NOLOCK, PRESERVE) {
+          PIRA, 8,
+          PIRB, 8,
+          PIRC, 8,
+          PIRD, 8,
+          Offset (0x04),
+          PIRE, 8,
+          PIRF, 8,
+          PIRG, 8,
+          PIRH, 8
+        }
+
+        //
+        // _STA method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PSTA, 1, NotSerialized) {
+          If (And (Arg0, 0x80)) {
+            Return (0x9)
+          } Else {
+            Return (0xB)
+          }
+        }
+
+        //
+        // _DIS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PDIS, 1, NotSerialized) {
+          Or (Arg0, 0x80, Arg0)
+        }
+
+        //
+        // _CRS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PCRS, 1, NotSerialized) {
+          Name (BUF0, ResourceTemplate () {IRQ (Level, ActiveLow, Shared){0}})
+          //
+          // Define references to buffer elements
+          //
+          CreateWordField (BUF0, 0x01, IRQW)  // IRQ low
+          //
+          // Write current settings into IRQ descriptor
+          //
+          If (And (Arg0, 0x80)) {
+            Store (Zero, Local0)
+          } Else {
+            Store (One, Local0)
+          }
+          //
+          // Shift 1 by value in register 70
+          //
+          ShiftLeft (Local0, And (Arg0, 0x0F), IRQW)   // Save in buffer
+          Return (BUF0)                                // Return Buf0
+        }
+
+        //
+        // _PRS resource for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Name (PPRS, ResourceTemplate () {
+          IRQ (Level, ActiveLow, Shared) {3, 4, 5, 7, 9, 10, 11, 12, 14, 15}
+        })
+
+        //
+        // _SRS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+        //
+        Method (PSRS, 2, NotSerialized) {
+          CreateWordField (Arg1, 0x01, IRQW)      // IRQ low
+          FindSetRightBit (IRQW, Local0)          // Set IRQ
+          If (LNotEqual (IRQW, Zero)) {
+            And (Local0, 0x7F, Local0)
+            Decrement (Local0)
+          } Else {
+            Or (Local0, 0x80, Local0)
+          }
+          Store (Local0, Arg0)
+        }
+
+        //
+        // PCI IRQ Link A
+        //
+        Device (LNKA) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 1)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRA)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRA)  }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRA)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRA, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link B
+        //
+        Device (LNKB) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 2)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRB)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRB) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRB)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRB, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link C
+        //
+        Device (LNKC) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 3)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRC)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRC) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRC)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRC, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link D
+        //
+        Device (LNKD) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 4)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRD)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRD) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRD)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRD, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link E
+        //
+        Device (LNKE) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 5)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRE)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRE) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRE)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRE, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link F
+        //
+        Device (LNKF) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 6)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRF)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRF) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRF)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRF, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link G
+        //
+        Device (LNKG) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 7)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRG)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRG) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRG)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRG, Arg0) }
+        }
+
+        //
+        // PCI IRQ Link H
+        //
+        Device (LNKH) {
+          Name (_HID, EISAID("PNP0C0F"))
+          Name (_UID, 8)
+
+          Method (_STA, 0, NotSerialized) { Return (PSTA (PIRH)) }
+          Method (_DIS, 0, NotSerialized) { PDIS (PIRH) }
+          Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRH)) }
+          Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+          Method (_SRS, 1, NotSerialized) { PSRS (PIRH, Arg0) }
+        }
+
+        //
+        // Programmable Interrupt Controller (PIC)
+        //
+        Device(PIC) {
+          Name (_HID, EISAID ("PNP0000"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x020, 0x020, 0x00, 0x02)
+            IO (Decode16, 0x0A0, 0x0A0, 0x00, 0x02)
+            IO (Decode16, 0x4D0, 0x4D0, 0x00, 0x02)
+            IRQNoFlags () {2}
+          })
+        }
+
+        //
+        // ISA DMA
+        //
+        Device (DMAC) {
+          Name (_HID, EISAID ("PNP0200"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x00, 0x00, 0, 0x10)
+            IO (Decode16, 0x81, 0x81, 0, 0x03)
+            IO (Decode16, 0x87, 0x87, 0, 0x01)
+            IO (Decode16, 0x89, 0x89, 0, 0x03)
+            IO (Decode16, 0x8f, 0x8f, 0, 0x01)
+            IO (Decode16, 0xc0, 0xc0, 0, 0x20)
+            DMA (Compatibility, NotBusMaster, Transfer8) {4}
+          })
+        }
+
+        //
+        // 8254 Timer
+        //
+        Device(TMR) {
+          Name(_HID,EISAID("PNP0100"))
+          Name(_CRS, ResourceTemplate () {
+            IO (Decode16, 0x40, 0x40, 0x00, 0x04)
+            IRQNoFlags () {0}
+          })
+        }
+
+        //
+        // Real Time Clock
+        //
+        Device (RTC) {
+          Name (_HID, EISAID ("PNP0B00"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x70, 0x70, 0x00, 0x02)
+            IRQNoFlags () {8}
+          })
+        }
+
+        //
+        // PCAT Speaker
+        //
+        Device(SPKR) {
+          Name (_HID, EISAID("PNP0800"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x61, 0x61, 0x01, 0x01)
+          })
+        }
+
+        //
+        // Floating Point Coprocessor
+        //
+        Device(FPU) {
+          Name (_HID, EISAID("PNP0C04"))
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0xF0, 0xF0, 0x00, 0x10)
+            IRQNoFlags () {13}
+          })
+        }
+
+        //
+        // Generic motherboard devices and pieces that don't fit anywhere else
+        //
+        Device(XTRA) {
+          Name (_HID, EISAID ("PNP0C02"))
+          Name (_UID, 0x01)
+          Name (_CRS, ResourceTemplate () {
+            IO (Decode16, 0x010, 0x010, 0x00, 0x10)
+            IO (Decode16, 0x022, 0x022, 0x00, 0x1E)
+            IO (Decode16, 0x044, 0x044, 0x00, 0x1C)
+            IO (Decode16, 0x062, 0x062, 0x00, 0x02)
+            IO (Decode16, 0x065, 0x065, 0x00, 0x0B)
+            IO (Decode16, 0x072, 0x072, 0x00, 0x0E)
+            IO (Decode16, 0x080, 0x080, 0x00, 0x01)
+            IO (Decode16, 0x084, 0x084, 0x00, 0x03)
+            IO (Decode16, 0x088, 0x088, 0x00, 0x01)
+            IO (Decode16, 0x08c, 0x08c, 0x00, 0x03)
+            IO (Decode16, 0x090, 0x090, 0x00, 0x10)
+            IO (Decode16, 0x0A2, 0x0A2, 0x00, 0x1E)
+            IO (Decode16, 0x0E0, 0x0E0, 0x00, 0x10)
+            IO (Decode16, 0x1E0, 0x1E0, 0x00, 0x10)
+            IO (Decode16, 0x160, 0x160, 0x00, 0x10)
+            IO (Decode16, 0x278, 0x278, 0x00, 0x08)
+            IO (Decode16, 0x370, 0x370, 0x00, 0x02)
+            IO (Decode16, 0x378, 0x378, 0x00, 0x08)
+            IO (Decode16, 0x400, 0x400, 0x00, 0x40)       // PMBLK1
+            IO (Decode16, 0x440, 0x440, 0x00, 0x10)
+            IO (Decode16, 0x678, 0x678, 0x00, 0x08)
+            IO (Decode16, 0x778, 0x778, 0x00, 0x08)
+            Memory32Fixed (ReadOnly, 0xFEC00000, 0x1000)  // IO APIC
+            Memory32Fixed (ReadOnly, 0xFEE00000, 0x100000) // LAPIC
+          })
+        }
+
+        //
+        // PS/2 Keyboard and PC/AT Enhanced Keyboard 101/102
+        //
+        Device (PS2K) {
+          Name (_HID, EISAID ("PNP0303"))
+          Name (_CID, EISAID ("PNP030B"))
+          Name(_CRS,ResourceTemplate() {
+            IO (Decode16, 0x60, 0x60, 0x00, 0x01)
+            IO (Decode16, 0x64, 0x64, 0x00, 0x01)
+            IRQNoFlags () {1}
+          })
+        }
+
+        //
+        // PS/2 Mouse and Microsoft Mouse
+        //
+        Device (PS2M) {  // PS/2 stype mouse port
+          Name (_HID, EISAID ("PNP0F03"))
+          Name (_CID, EISAID ("PNP0F13"))
+          Name (_CRS, ResourceTemplate() {
+            IRQNoFlags () {12}
+          })
+        }
+
+        //
+        // UART Serial Port - COM1
+        //
+        Device (UAR1) {
+          Name (_HID, EISAID ("PNP0501"))
+          Name (_DDN, "COM1")
+          Name (_UID, 0x01)
+          Name(_CRS,ResourceTemplate() {
+            IO (Decode16, 0x3F8, 0x3F8, 0x00, 0x08)
+            IRQ (Edge, ActiveHigh, Exclusive, ) {4}
+          })
+        }
+
+        //
+        // UART Serial Port - COM2
+        //
+        Device (UAR2) {
+          Name (_HID, EISAID ("PNP0501"))
+          Name (_DDN, "COM2")
+          Name (_UID, 0x02)
+          Name(_CRS,ResourceTemplate() {
+            IO (Decode16, 0x2F8, 0x2F8, 0x00, 0x08)
+            IRQ (Edge, ActiveHigh, Exclusive, ) {3}
+          })
+        }
+      }
+	}
+  }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
new file mode 100644
index 0000000000..e98aac4676
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
@@ -0,0 +1,45 @@
+/** @file
+  This is an implementation of the ACPI platform driver.
+
+  Copyright (c) 2019 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/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
new file mode 100644
index 0000000000..7dfd0832a3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
@@ -0,0 +1,105 @@
+## @file
+#  Component information file for AcpiPlatform module
+#
+# Copyright (c) 2019 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/AcpiTables/Platform.h b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
new file mode 100644
index 0000000000..6a4fcb172b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
@@ -0,0 +1,75 @@
+/** @file
+  Platform specific defines for constructing ACPI tables
+
+  Copyright (c) 2013 - 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID           'S','I','M','I','C','S'   // OEMID 6 bytes long
+#define EFI_ACPI_OEM_TABLE_ID     SIGNATURE_64('S','I','M','I','C','S','T','B') // OEM table id 8 bytes long
+#define EFI_ACPI_OEM_REVISION     0x02000820
+#define EFI_ACPI_CREATOR_ID       SIGNATURE_32('Q','S','P',' ')
+#define EFI_ACPI_CREATOR_REVISION 0x00000097
+
+#define INT_MODEL       0x01
+#define SCI_INT_VECTOR  0x0009
+#define SMI_CMD_IO_PORT 0xB2
+#define ACPI_ENABLE     0x0E1
+#define ACPI_DISABLE    0x01E
+#define S4BIOS_REQ      0x00
+#define PM1a_EVT_BLK    0x00000400
+#define PM1b_EVT_BLK    0x00000000
+#define PM1a_CNT_BLK    0x00000404
+#define PM1b_CNT_BLK    0x00000000
+#define PM2_CNT_BLK     0x00000450
+#define PM_TMR_BLK      0x00000408
+#define GPE0_BLK        0x00000420
+#define GPE1_BLK        0x00000000
+#define PM1_EVT_LEN     0x04
+#define PM1_CNT_LEN     0x04
+#define PM2_CNT_LEN     0x01
+#define PM_TM_LEN       0x04
+#define GPE0_BLK_LEN    0x10
+#define GPE1_BLK_LEN    0x00
+#define GPE1_BASE       0x00
+#define RESERVED        0x00
+#define P_LVL2_LAT      0x0065
+#define P_LVL3_LAT      0x03E9
+#define FLUSH_SIZE      0x0400
+#define FLUSH_STRIDE    0x0010
+#define DUTY_OFFSET     0x00
+#define DUTY_WIDTH      0x00
+#define DAY_ALRM        0x0D
+#define MON_ALRM        0x00
+#define CENTURY         0x00
+#define FLAG            (EFI_ACPI_2_0_WBINVD | \
+                         EFI_ACPI_2_0_PROC_C1 | \
+                         EFI_ACPI_2_0_SLP_BUTTON | \
+                         EFI_ACPI_2_0_RTC_S4 | \
+                         EFI_ACPI_2_0_RESET_REG_SUP)
+#define RESET_REG       0xCF9
+#define RESET_VALUE     (BIT2 | BIT1) // PIIX3 Reset CPU + System Reset
+
+//
+// Byte-aligned IO port register block initializer for
+// EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE
+//
+#define GAS2_IO(Base, Size) {                             \
+          EFI_ACPI_2_0_SYSTEM_IO, /* AddressSpaceId    */ \
+          (Size) * 8,             /* RegisterBitWidth  */ \
+          0,                      /* RegisterBitOffset */ \
+          0,                      /* Reserved          */ \
+          (Base)                  /* Address           */ \
+          }
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp b/Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..86d7030833a096f545393735d931d9f4f2fbf8c0
GIT binary patch
literal 141078
zcmeHwJ9Hz-kzh@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@BjWNN&Xl7`zYzU`~UYcP5w_masS+n@=v#$bm8A8pL~*ZKm9cM6#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@QFr|2+Bf=f6mP@rz$1Z-4R2<d?tv
zW%A`Oeg)^hN`Cb#`2FRtlefS6b@J<9|2p~dSHDSq^PAr!Z-4zC$qfGe$A7@@Z+@Hn
z_P4)H-u~uyaQ?gGcfW(*-~K-N{qKLDtbX^0<PU%NLo)l_AL0Cu$shj+zrX)e@~1!j
zDf#vfe@_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@JfMK3cOO_l>)C6c%=ZLK$`j}9J%#+
z`g{~f-@JKc$n%k3)||b2c=-M+LnK+A>$>;;@$vEfKfY?L=VAb__wxr}$K&JI&mkaS
zw~kS*1G~9@9j0;vimRVfxy_Y(?c(tf7y|!~-77nSYEzvqlcpIQf^ZIl@W;O*3M7fT
z!9kZ0_+7Z-@1+@3FK$(@q_Qx*CNCLHfLrh%DN_M$JaLeE@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@Z%%a^j$>b;a#Vy<Dc-|$FJd0z%bzRz4!P4
z{sCjp0*YfS>J9)L?rr`_zY37>O@Q{_-78}U2meqcS?f20ZdoD)$&5I7LUsP#5!2mA
zEIv!W^NqXXbtyvT1i?FFELrj6Q@p|h8in*2V;#tu|Ax1|Dk=1pD}m+Uwxe4Bj5U1+
zJNV<fsLOyKaN}*L9!@<z9mh8h<ni$wkx9P7lK%h4Z%*B<7Jsrp4EO5e<5xcS!ohMF
zJ_0O6y=;Bij258V7V**nn0p+qQDwP~>Dq?`cmO&E`M9W{0!H{GGAQ{1E-QX`E<5s}
zixRkn@-arZCEI?0@4(@!dEW!@f%90CZ#9t*CtDBKkZs|re|+@#d>x=TP>&8u37Fif
zP;WRXRfWgu@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@O1P=5WkZCa0l!MTn7vs`QQIzf_!;+1fA~c0XAemf*X$MP!igY&BDW#
zd-rkbYJv*{4EhQVuCL$*Dm%m{luAOUt{}bp7>!hUi69=~R-0q&3OmUD4Bta0ky`-E
zBMCQ&c4z~>MVXJ@dBmalpL?R*f<qBnTQ#X(J_tX?h<1tLTfD%Bj#$v8##j&Vqk}Yl
z@AY!xHNnH@N%pU<a<nu~HUmE#yNG;vNkH|7S}oL&{>V4s^ECYzID`MbpMsHs!vn@!
z&V+3w2Pj#D`tZXJ_M-sGAqlrXPlBcONaEABVz;s4SiqS=@9#jn@OTgGC#?-dgT$2G
z--!^SMEK$C2MRMB*}oyW&Rm32W4K0r<wWA0cjG*hKmZaaM^HJ~Vp3Cse}#_#BI4uv
z?}PKYf)sz2zQKnMuroQOk$1S&{|Qw)?8fju9MHeU6|8@9k`j?5-ef({?Vfmz{NTul
z6~lkvK)7~A<pUsHuchXjkS)~s1>zt017ZiRi1VxPE@+rB{(^ty{I0;Y<X_;P2a4d3
zzTPsx848;6ue=%x{w`7+O9gX_Fu@+d-G_0CQt1Jgj02h4c>L1?!h9HEL8Lugef_t;
zp{PGRq8g8|BDz@ifQQ!rNT?+7E-FwFyj#SjQa(^$Ab&|ne*?-yfnolYlQqW=01AB<
z`2nRtKFVKgL(mTh)C&}X`>xkSc+-}ThiiC5@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{s5Us
z{jxvCJA`Zj-WP~}DDcsbfH{urt^(i(j^2?UIN(APg@+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*AdsRkDKJvp4
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+^Qppxxuh6E6KR
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@xE}kwK;20D^trTk6uDd-;H-I6}j3nY4jg4Jiqz_FYR+BAt^PLs>wQ%xgJd
zuaCaq3@Yg#m6nMlC-M;iZzf34d`@{+@&UT97RiyDq}mL)eTmB7g~n9&qa1%k>X+@0
zcN~L|v{hZf8oJ;_91jwI*R>1&c*9b?=T1I#{CK$doA3Fa^Iix*K76-7`y2AZhl_)F
zV)bLZ7vzHj#VZ61{a}RWn-1Rs@HzmhX9EppR<NKCVs~(WK^wdqVOaV=2iI4w0|Ppt
zIwy`^BB_8n5%nFE+Vim|sk0j(?EnkM=Z?wf@8XTm(ykMU(x6w32r*QA!#fI&(Y}s%
z8JG`j{I%nUleUr|jvrWW&@vUk@+4?~he~;`_IK<^?429bS8y4eJNHTn%Lg#9*7CTH
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=&53jF0
zKcc=W-=nYsIgn-8;)nM=tM>BEEq+lx0HzyEMf>5ZgNm>&-%{+g{t9lO2Z{q^IHbM`
z*G@jd_yb-H_8bRQuKSk*!hmQg9d48mnp*l-*hR;_(GTAb;}3X^lo~rkeG_=gQvmFd
zRszWjhAU^!12IrO0P{*dI4txuT(wvTk9HN9wX&Oa@)6pBRUs9z{jO#B2apT|0W}|?
zx!x77g?xYoeuJO@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@sD97h`1Bft&$8hRQV5CTJh>=)ChU0VV%=M_?sZo7pB8il!
zkfcqrAh*6}+mGPgx`sl}189H}BH)j}54=Q-!r@vIu8DjAsi=Ioj$OGsp%+4tO2xaH
zJa;@A@7_U0@B0`S{^0}GNyq2N54<P+-O@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@4=uv}xH
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`9gt
z@pgFNCD>bGZqHp3qyX$2@~O)q!gn7Ovs_On_5%t5KYXrA)Kw*tfR=0h7;!`leFgjd
z4HR)*!k?qKx;|PdpMU`Nmq`9nK4SH*HHaGG<}M)F)eo&fP{!^FfI#fO3U8GJ@RyE}
zUJ`v%LnnY2z<Wud!}_DLA6|mT?yegpIXKuI+&!Qy1?<kDTYNMA2RQxi7(~crlK3+C
zx3V8_j+PB71bzT4#G1kKt@qI)Yy=cIkbFR$0PF&pTggh$&V>5<j-wS*X-?W5y?t*+
z^5G@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`2ZaJpbbx>
zG*rE|M7_Kb{9C;3I=gES_)5-k0$}byaR^Uc4Q02CNerd@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@w>v4lgFvl2l*)@{h-^Kc&-G{LsOg@mB&YlAy@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@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_@a3NS)OsT*S>AAjW3rn4dy!oEY|>IkRG
zuo&<jWi7}@1&b2M^#PcXs=(}X0tf|}K<@(&CLhofJx@Y+!5LhiVFef=_acLKz`~D#
z(T6EBrvRL*$#XuOmcxYdGVr66U`Iv&LZID+2^b-Jeth$<Ujy!V4n9KZd*c<hC@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@UM^)Fcd)z^VV^tYCz~8;YIktG7U%~*Re4CZ8sxa)l_#<
z8bf>@&p{lqqVhk)-%a3`Hy~Rt6xoj-*darET&u!J5351Izz;k{r^p@OaY+?UUxi1m
z`p}O`P&kOO0GHZn3=RTjZ^OF)1*@zMH{>i4!e4}M!3x!55npYEV+Cus6Q{32Kq;O>
zb@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@fe`T+quhrV_^#*u<B*@DVju_F4}ND@-k{Cf1(%Qh8R|g}!~Y&usLAoe
zRf;-19NvI9et3LB_1{DN6QBeNYrqKOpC2D0?I4AxjBJ(_B=I#EqLelv-V{h8jUL{O
zOZ!$q`H)Y(`vns7@yGkM>XWyQK@^G!7$nTke{{y6lNCFFkl*`fr>tq54T5S1LGnXp
z)3I>>)M+HAlfq^($ExWSZaWHiQL^UG+r9r<>Xibo6nLe;D+OLD@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@B#^sEBl<H}Fi>$3JH`eP9l^?w}!e1;d53|}v(s#S--u1$8
zZjBBEw{AYrAxLj!w@2J97FYf4h<EVPozZNg6^~fEJy;Ho!|?&Ok`HWVKEHZa85vGi
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`E9sQVu@
zH-HZ5@NTxs^Ss#9?jRz?-RaXcxqH#9tBNHE#7mBS)^@ap2i@W5>iXv9_I@&*v8kOJ
zb259X37@oo)ugNP<@EMq@PUr}8u;NK!FB>L^?81IGnp-6KBVbbUiP0Newv=#*85e(
zYJPX|Bxr1;+>r}(PR?&&3bctK#qG)Qbyhm453Uuf+11HY^ob+Wx-Iz5>D81@N-O3}
zj&4NK;Y`&UZWQ_S#l$$<QgrWf+3<GJptt77o)bN*4Rz+TW7oYm@s0za*W?Q?jvJIX
ztDWeWyA9Kh)8dy7H9N2OH&>TO#QwaF9m~tVSBI({H5)jxx;~mktz$=i_XLhaJHk9y
zskD1p*H@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@2z@@`}zTB+QTr<-DEnSFP6(C#@!*${qp>@
z_u;5FNPxY#gb3nnzVL0BO?~QaEmN|ydsAmE&kx$_-i=jDep?qE>71NhL58~?xk4EJ
z{_1@20XP6@_w?fWex}ori+nM?y*#UNDIxLN)LDx|PEmC(tq|hs+D=f&`e#>@hAg0B
zIlVqVdD#P&&fwy9Y7*A#iDGeoHMD1SdRM07GlMUv9_Yv}tQwYArU-TiqkF43*LSPQ
z<!P<Z9|-N8!KA(6b&EWv#ofh;CFq@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@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+iWLO
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@_0VI^E9%<Hs#r}fnz(_r!!)y2hK?`?o3&}x$aJV%>Cjl*
z3eBv+bw@Q?E5BtvkCiAjVI?$deJ4Fv{U+xlkB;HX!8=8}HSsWsrsWS`7violJLDb1
z{lRAE(^k3R{TsUtIiESru5?Q|DO)tDukw3}J2oMhT_Wb{$nQ6HtWbOZPFp$vS3Kb^
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@Od0{Jz`Cc(lvm)!JnE{(`t1i=l
zNeXVUQ`NoKqisz3iSh!MEb3y;sju&tMzctu?sZL-G251}3T}%Vh64$*dAXe)!FueO
zQ65;*8!#@m@OeARR_C|Wm}euc5Z7xxBh!W|*5c{iLp&{N3`J5aabdZoTKBN}cTAJ`
zi=4$8Qtdfxk!_-rr{}E4+EbC+2w<dJ$6`o+9Sa=k%&JxeuUppLvludG0&t=<R(k=-
zE@k)U3G>#tytvt3S^3s>tz^`F=QTGH(wItE@5&CG&XN=ZKkbIv^z>SJ#;pb9MET3i
zP+Qr&`A*8pQ>|yjk=F}muQrl*+X9v?U&;BsEr41KSuy3;Q+b<hCqi_t2v4^%LOywu
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@oze&$yBJnU@-wizkUNb!40@v
z3MbP@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*HPy8DTq3t7-H
zh>8tN<<OW`-BaR3&9x%-QfxWUS0yC*)io?Lpa@t?Sfou?eGHWJq^VV*f>R?+b!j`)
z6s0ZC)1g%A#VrA$I@7XAw$<>03V=>2;d8`EM@g3=zrIo2vZ=?ev4o|Vup;R>_pcCU
zaYL*oX+Ama8^$T8?IUIPIn}}A1wlW%5Xk40Te4mmN~bA_sfshwdH_<YM?;?cun1%}
zt6lve!e4!f1Hcd&nA(6q5gJ91&BANbmQ(9!y|l}{^i&E+ensF6qzanVi*{F)B@-V#
zS<RZKMJD!!e#H_tSb|R+3}FW*V+0P=UhvGWQzO>GZMqo^mcBC~0iLGTxcoRPfI4bJ
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@uUh`p_8n*&Jiu&AP%i<g_aa+?WC%v*G1I%p5P1$`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+o1gzeJ6B%-a
z0`*Z>^XqY9NnI+3O#o5Y^u${EuHu`3oa#%69p^u7%R$c7B2J?E(^G5=ISTIZmk11n
zBeo{euhu>j*@5>@q&8cxx%`xMxL=*F4ajkTNouWz<0@Z!d_ZTR_^>{+voM4Xf6<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;Yf7uPTcSGHdcx
zrwC~7^K5+szx{8iusa=ED`U(CSE2H*5V3+pgp|L-I+)f!o95ii-T9@vYQ<mpd`V_a
zXz+kBG)|$nA+)kTGXO$Y&U;VE5Tqw9196AT+S8#>NkwFu^50h1<!kt>Qx-Qaa8eMl
z@+Ehm%$+p(eqPq{D%i}BBBzI{hDzfv9OO#Iy6N~psUkXl54EfH%L}5eq=&|)SoCVC
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-@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@mNC>tyPdKD%bF?m2%6o7qW9{9)TfC5};_n;E0c8Dl|19DjGzy
z))6N;{kM!UU==K3Tlz{PU`6!m8$GmgqIm2zRsI`Ldqs21z{<!0FBI80CauTnFi+GX
zUfR)QxRlWp+$$L{BnCz%WwZ1ZHEqt)RW~<GXUs!fox7`gyb09i@yd>xv4$el;opqN
z;Y+9xHAP6SJP=twGR8wkgHrBT{-){#)M~Y8qiNH{2AoDhB8=r(Otd4X{(&EBdw#M7
zQU@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@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@Sf&Erd&{iE=MO!>!>MzvH)0iU*`SDhdB+>v~6_9bXWPXup?tOzz;Fg
z(UU<TD3b5cKiZ<bxttseP|GXh@oWnv+5M<{C4sVlhICi;^3KgzgS|G0y%rvMSItNx
zwc`{&)MF(Q$=G`vbPiTVuBD`LSUJZ{!@nv8gV<B0msvbRMwfO=;7_e}YH~lBfiZOC
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@pcEzabu
z7NQ~clj$1N7W=&q3@fvuRM-Zm{maUz2z8?5WCK+#(zp;$QifOAeho6zw?_=m*r^7_
z;M~cwQn3ZKr3pp0+WT|uPwmYRq>81!kQ_<Vw#p@MBw0xA06{?}a`ui-6m7<rmgpM^
zi84igXq4egWX*52vpz)YJodTt_-F)6@`}>#ObiD}?xyrvm^PL&$MZS2Y^{u2x~?q@
zlC^}K@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@X`LF<B|y#r=Dz9Jo7I+rcizmgsD<?IKUagwXfX^b+F8UJ+s
z=PoTUZMsN>v9cFv|ABf3BA*}Gx@Oy{?}FSe@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@U_lnq!M>X95%(XBz`
z06k6~NFgA@NI7a@!*eN(2hj*}428tz3H6ZtZKRX%&pRY)!5DxM0m?%Wy#bDlHqq`Z
zRdXCn%N#=zzLNZ4={$0y5thc;fMw$&bB{PWkb<{U8Bjo`@sGQii9}*B(}>4G9!kp6
z8A2KPh`m{MH^N1k@Xx{}GL`x;fmAyL#UsaNM&g96YUxV<1z5(vS#uDIHv>_cCk`?a
zN!mEkr}z;A5cMwsBFEuJ(v_ADdp`+rA_=VJRqNOyEYc=97|R{=kfT>(nG<R2<J_v8
zog-F93Ka`qDT{QV)fLkJMt;c8x0%@sm(1&xx)z}<c%IWSd4aH%=Sp06iC#1XiXU-Y
zS8sHnHYp!;N@cH>TI2LWY*%G&PsylVGnk3%RQJNM)ywizcw{7@(l4SED1O9l*2oVz
zQfAa>g>OwE>l@YUl?Xve(Z%l1!@(UH48<a`*)^3P^0t(8nr$w9ujsnU<X$qalOn)O
zwuqPP8%`vINaai?QgY6hbfm^sq+<1n@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@kYL95`sT{L9hVV6`wES-8{g{cwx60m4
zKAQL;LR4HnAcR#$F4}yXYP-hDBnwB$xUA6uvurx`@y*?@z!DwEF%J!5tAW^7R9o?*
z8uB*qL)mjKA4%G~m@HSz*(F!)+flxzw5%H$BEHXJd?5&ij&V2(kj(%k{pLVT?d@-i
z^aHkzb~k%2<}t|Ls*V1xLpkg8dOhh^v~Ns9N#omkFjvlXjqHHPGclhoV@Oy;PC7PV
zvH6kM`h_GvCr#sz2LGy5I*2M9gdb8N2#dNI*?mfM#gr!ECO;%S5c#ZFhEfC<^N8-|
zitL$sL7OEOlhdsfn#Skt`9TC;W^M5h5yk2l=T_HVaR(~3GZHB_nH77NAFrY>Y<VvC
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>nILXnDZcl-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{EARWbyDMHhU<^sX&P
z2ee)gylI5g)Sc_6mKwYO*|EsfdaU)RXQu|S`FE3(RHh9efyC#!?ZHg!$-B2f?l(>S
zD>>&x^Gl@b8Y6Ei3K>ViGDO7kuXb<47H`&k4TnK6qar+eA(iP)$TKmRVK7@?$i>NY
zF|3@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@p5^6g6Q>*a`t(d%J1j$$1PlwM
z!w4k`qMx@$Qts?c=Fio4C8&=sXO^h)l@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@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@4VUFp#%pE(kH_$`zvSm0Y{O<bediEn<{p
zOiV6Rk_aC6+Wf*DSs#J5%O2#Y9cO#6i0pq@B<J5s!eX0`RDL^}*a*4JIotb1dhdKM
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@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_@t)5+XLs|(ayh>jskSlz
ziu{1@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@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?NDGSQXu
zbWoxoX1R_TxW5)cqX&)b$#nXHdK(?Fs(;PnJ+98apgGOdm7|w}<WSTjyyp}7!2`Kn
zjro0+DW6vAT2s87+SXvE%}03kYHYfDgxtD&O=grpwgs)%9BW6oOlne+G^#vaGC#5>
z)oWkZi=C;1g0FRq5R~}l8f*wAn=U=5R1UAO#}^`;WMC=%CoXu(A*XX6Y8WY^J+3yn
zQ~P=qM<B|*Bnb}&s)x8`d@zR_2dJbk)i6*p7k1yW>HKruH5*<>^JzAxC++o`?eD8*
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#cQupq
zX;_GnC+Wz^2rMGCBWtF$UmA6w<hrOeQ&&TTPY!7rLsim&oW&@G3a8Nc7Q^%~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(?uRGaGM
zD$Cfl!4DC8UeE=(v?e)-Uy~Fq^{rwWS*Ab^aV}SYA$8V7T4^0B#0o{p3O-k~#quhn
z!>{RZf>vopGwJ@osY*$uo6D<EVKJi6<9W6eY$qcyHC$XXmPa55I5YQuS=DW@Wx1<7
zd8X!b-OL=N#(a9gqrqj%%oKUHS)o!UYZ}kUu3Z0$e{}FFR3&}&oCHj@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_@a+of$!6?rWrS?i)sz
z#06Kzg)C60Xy8wJ!qBXV!b)U3WrIg3K)1iNGSmzDogW3t_&&=ry6V2TwHts42g?N+
zPNC$}t3ia-J-aO@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@65_qtITme9nZE%2bZ^T$i)DKMx068#p*}FK3hc
zyZh-}1}X3%90mI>km~>ZV`J%1u#`?TNvu_(C0W>+WU7bJrxMg|*Xfx^B*yk`{vNOl
zLGd2xQ8B~8lejh+rW~x%J|eK;-~oJ@C=Jq0tcM<*Hmw)X3X4wOXuHYeeK!v9x8#Ct
zq{NB}DKB1KiE%nhttkt2WKIXb=HcMXnl9PEjCH~DXLU4yrR}QEr1C&~iEH_*5+>;K
z|E`Jxh#l@rC_Ddlb(9YFzi$%>$Y?+{zok90!lpkFssc#OZMyBtHgjY#sw#jJ{bdFo
zEl_dN!p1eg>`QgApm9UFcLt<DQqO_nwbMDBFE5EuOycH&O+b5**g2nYif@_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@MgOx?mz!&8c(oP?0$qYGdfag<R9a
z$Cg?^ng-4i_J(V1p1|Hx@!aq}JkEMuHSl0>nV;*PkXQ#UcN0;(T2%$Za_a6tMMfBa
z4yl1(${xf7Q-)}Dq0%i_{-hqPiP@hD&ekWXG5IRKn6@=c{eqRfAo{2oFEp8=;*Bcc
zwC3WGs!#9ozM%0<RJfEaVpoI91MLY3h{)L&q(EK7+rYc+E!94#CLgi4&Ch=t3{iGU
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@akU7cjWWC(ZJw_nVTn;>nibBwVGnp
z-%e&0glC<*9;1>1+tUV1c2v|1pt9u>+risd+O+9QYaH3>4==9oCbRisv6#>9Z?Dcz
zd(v*W>a55cANeQR+_!Wel}pG2{9R)y4Bw@2BSBb!j`ARY9V;=?VsGqyp}QPZIah0x
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@_2dC|g~qgY
z18UkAJ1Mxn$+D~QEuFHuRWL{{P=hfB3-M%fMWM&ycDpfyJw2M!k7O7WIMglkbKS6f
zM31~1YD}%cB~VMGQ>J?EeygcfHE#kvhj~0YUD0u5dYZCg4J}F16Dz_F0b>zMYJ#!X
zGc!no^YyKpkYw_EfWBX<Z(R@6%)Ll4-qaA4^9WNz3{9OL=TPA(W{tI|;i_*-%Ry2j
z=#~%FK+9vWDcvhVw*?%sR$>u%rq_e4TRT@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_@_P&vUQ?^LvbFTtF<JPjIn8Cv>bd>kZDX?q;^#z;}w7ib?AERxy@Sgs;1y
zv#nH+Dm%Ab4Bwt&HJ`$q!R6&>ba{1iKbhAz1YT%kL+eo8=YChMvhdi4HZ13pyBlo7
z<>mG5{d7?)-B7-mO6jn^2F_z0TcB>t6Uj+}?5ts$IkYHWt@6CafXAk99jVx&A<acQ
z)|!)u7@p;>4Yo@dOBVOic0l-A&-wCLU^8y)srA9K30dQbh0~$Ape`cW@@)2`jxK8^
zY#wPvHCrMci{)~$AyCH{a^@pm`xaM5P`XfQ1}C@m3OFL$e3r9?F<W4Gn4+)@Xj9*B
z#vh+9Z}hn9M6E=J0rMVCi=kTiiV37g?@G($X7p)^l}hzH44vCU8SE|Pi%ah7VBOY4
z(Y$TKzJ<J=gNJ^gBA_sfu}}9Z=354HEKK*k*S!&$B(%S5KF_V06KimjU+smdwE?Gg
zgdpm?(O%cKDWC4sWA<tteL1ZS8q{JQAFM=bj{|J2N93s?wEmXoYT6f&Frpd|c-T!u
ziY5O_c}uj8QS9VyM?+Yct5nP{S?!(6X?_!#tzrwL>F*>WhR1#kQn!PdHjbvEG>Eg6
za&cUBIx7Ui7Nd5UG?cPdOsvfXtY_O>k;TDR=r**Z#iOn{fh_3HFQG@7fUP~|*Nyv3
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@i<V6jSX~=AvXB5dkPaAu0PcM$!Ax?7t0Oo3y|4f
zJKYo-wVK#@?yf6Ydzq`?_#U0kPHI`!4dXif)4Hv2U@CNSb=I$u@;y*I@T+O}<m`G<
z6OYD42dBN-u!rgB?((s)+BT)uun@ero7#M<PVe;m@)jcOc{wa8^5uMb2MPQAj+n8j
zt@e2zq%dIviwz*cUbdkqR<P9%%<2r9q`PKPNbF?3U)$2583E1jPa9NXr+0EXJcp@|
z>+9>Q%hCDS=}GSc;YCTUw9_A)o?VQt$~Fv7s~NVkjQH)^(R(>jA>P{d(sr`!9R@k<
zG|f7lEUQ~N!3)38t2A?MXp!p&{<7(vEo<E3og190wYuK0Ev{;H*3NZ(xG!d>#tub5
zsDrsyku<3hdq<Y!cf(rC7T^B=<E&c~aLKP4)cUTZN$aLLU|{!QSm<3_-txV)Uqd1J
zz2lbfHWf>4)d(UoIn#47o1p#OJ@1^^`QebEeFW)1^3_TR?9hGkK^yG-J4aSy$f36$
ziygp_`taxKx_0sD{*8U{5Ympd4AOZ#Ir#$j;oD(5*REpVNDGJX@F=|ih%jC*hrNyz
z<j)bM!!`WO*dMp7KEES-IlllhJrN2u(F;eFV=vrJlA+p?u4D(~=jGGO|KElqo%34R
zfS7B;zVip_E$Kj~&qt1|^X25yNTfbc<u46PI=GsZ(JexR@^o?NQMuKA2njSMlN77P
z^ycE^1B+ByE!}Vr6Wtrq!(r*c4y&g()M-Ah37M6>0)F%5Vs>{kIv);TC;D!gA8rEs
zFmI-P*!ySRoKvH-d5_iBY&apruQ@I9)nYN5&8E}I-AJw(Iu>R}hnse~C&P;?48zyC
zRGuEIYmw=EOw`hW@gdS0zQAo<Z1jPLR62tTSaEQ5eS0^Vl3AVFHZMj`JLd*#0Bdov
z9*EC09<#F?1NQ07bcxF*ie{lGTV71mx}0NRMPa6=w`QcjL`nXx)KV1+?PZ^DoBzJN
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@clN#&
zKi&K0*ITPru@lHFYu*as39#;5wB!i;?9~$>cBm@UX8;)s$VIWZc@g8R>}=8y#HkSG
zn`a-2TE~aeYv)H6>f@2eN3E`gba1;_YduA9tq#F`?ziK|>REi;`gV0Lrj237_3GI*
zYd!LfPr5CFLoYC=BhC7a1CmyoV>c4!nI2}NO6A%o`Q6#ejAmz@{`pPKUP^~p8uUyI
zX;fH{=>C#3k~7#|`{H`C5GxMaeAMxosJ*$`^sFXoRV?l<26bydHp6|Y62Oy_!TIP4
zwqJ2O(J!Xg#`iLw3Y!DelNp=!uI6`Far>eJRB~hxu)$Kd-#<ASz|sHE)8(?^UDz%F
zXLVrB!PUiwm#lwehCeO%9!x@A!K#T1ST+HZo_~i^o=;29{cD3o2Os#diT!Et3gMLk
TuM~Ktz$*n_Dey{xHWc`O(cS1K

literal 0
HcmV?d00001

diff --git a/Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec b/Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
new file mode 100644
index 0000000000..40487820fa
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
@@ -0,0 +1,152 @@
+## @file
+#  EFI/Framework Simics platform
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = SimicsOpenBoardPkg
+  PACKAGE_GUID                   = E6A03E0D-5944-4dc6-9292-090D609EDD3A
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+
+[Guids]
+  gBoardModuleTokenSpaceGuid  = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
+  gSimicsBoardConfigGuid  = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
+
+[PcdsFixedAtBuild]
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase|0x0|UINT32|0
+  gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize|0x0|UINT32|1
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase|0x0|UINT32|0x15
+  gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize|0x0|UINT32|0x16
+
+  #TODO: Remove these two when we integrate new PlatformPei
+  gBoardModuleTokenSpaceGuid.PcdSimicsMemFvBase|0x00800000|UINT32|2
+  gBoardModuleTokenSpaceGuid.PcdSimicsMemFvSize|0x00500000|UINT32|3
+
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogBase|0x0|UINT32|0x8
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize|0x0|UINT32|0x9
+  gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareFdSize|0x0|UINT32|0xa
+  gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareBlockSize|0|UINT32|0xb
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase|0x0|UINT32|0xc
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwSpareBase|0x0|UINT32|0xd
+  gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase|0x0|UINT32|0xe
+  gBoardModuleTokenSpaceGuid.PcdSimicsFdBaseAddress|0x0|UINT32|0xf
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase|0x0|UINT32|0x11
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesSize|0x0|UINT32|0x12
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|0x0|UINT32|0x13
+  gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize|0x0|UINT32|0x14
+  gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase|0x0|UINT32|0x18
+  gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize|0x0|UINT32|0x19
+  gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32|0x1a
+  gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd|0x0|UINT32|0x1f
+
+[PcdsDynamic, PcdsDynamicEx]
+
+  # TODO: investigate whether next two Pcds are needed
+  gBoardModuleTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|0x28
+  gBoardModuleTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId|0|UINT16|0x1b
+
+  ## The IO port aperture shared by all PCI root bridges.
+  #
+  gBoardModuleTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22
+  gBoardModuleTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x23
+
+  ## The 32-bit MMIO aperture shared by all PCI root bridges.
+  #
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT64|0x24
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT64|0x25
+
+  ## The 64-bit MMIO aperture shared by all PCI root bridges.
+  #
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x26
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x27
+
+[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule]
+  ## Pcd8259LegacyModeMask defines the default mask value for platform. This value is determined<BR><BR>
+  #  1) If platform only support pure UEFI, value should be set to 0xFFFF or 0xFFFE;
+  #     Because only clock interrupt is allowed in legacy mode in pure UEFI platform.<BR>
+  #  2) If platform install CSM and use thunk module:<BR>
+  #     a) If thunk call provided by CSM binary requires some legacy interrupt support, the corresponding bit
+  #        should be opened as 0.<BR>
+  #        For example, if keyboard interfaces provided CSM binary use legacy keyboard interrupt in 8259 bit 1, then
+  #        the value should be set to 0xFFFC.<BR>
+  #     b) If all thunk call provied by CSM binary do not require legacy interrupt support, value should be set
+  #        to 0xFFFF or 0xFFFE.<BR>
+  #
+  #  The default value of legacy mode mask could be changed by EFI_LEGACY_8259_PROTOCOL->SetMask(). But it is rarely
+  #  need change it except some special cases such as when initializing the CSM binary, it should be set to 0xFFFF to
+  #  mask all legacy interrupt. Please restore the original legacy mask value if changing is made for these special case.<BR>
+  # @Prompt 8259 Legacy Mode mask.
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFF|UINT16|0x00000001
+
+  ## Pcd8259LegacyModeEdgeLevel defines the default edge level for legacy mode's interrrupt controller.
+  #  For the corresponding bits, 0 = Edge triggered and 1 = Level triggered.
+  # @Prompt 8259 Legacy Mode edge level.
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000|UINT16|0x00000002
+
+  ## Indicates if we need enable IsaAcpiCom1 device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiCom1 device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiCom1 device.<BR>
+  # @Prompt Enable IsaAcpiCom1 device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiCom1Enable|TRUE|BOOLEAN|0x00000003
+
+  ## Indicates if we need enable IsaAcpiCom2 device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiCom2 device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiCom2 device.<BR>
+  # @Prompt Enable IsaAcpiCom12 device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiCom2Enable|TRUE|BOOLEAN|0x00000004
+
+  ## Indicates if we need enable IsaAcpiPs2Keyboard device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiPs2Keyboard device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiPs2Keyboard device.<BR>
+  # @Prompt Enable IsaAcpiPs2Keyboard device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiPs2KeyboardEnable|TRUE|BOOLEAN|0x00000005
+
+  ## Indicates if we need enable IsaAcpiPs2Mouse device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiPs2Mouse device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiPs2Mouse device.<BR>
+  # @Prompt Enable IsaAcpiPs2Mouse device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiPs2MouseEnable|TRUE|BOOLEAN|0x00000006
+
+  ## Indicates if we need enable IsaAcpiFloppyA device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiFloppyA device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiFloppyA device.<BR>
+  # @Prompt Enable IsaAcpiFloppyA device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiFloppyAEnable|TRUE|BOOLEAN|0x00000007
+
+  ## Indicates if we need enable IsaAcpiFloppyB device.<BR><BR>
+  #   TRUE  - Enables IsaAcpiFloppyB device.<BR>
+  #   FALSE - Doesn't enable IsaAcpiFloppyB device.<BR>
+  # @Prompt Enable IsaAcpiFloppyB device.
+  gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiFloppyBEnable|TRUE|BOOLEAN|0x00000008
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+  ## FFS filename to find the shell application.
+  # @Prompt FFS Name of Shell Application
+  gBoardModuleTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }|VOID*|0x40000004
+
+  ## ISA Bus features to support DMA, SlaveDMA and ISA Memory. <BR><BR>
+  #  BIT0 indicates if DMA is supported<BR>
+  #  BIT1 indicates if only slave DMA is supported<BR>
+  #  BIT2 indicates if ISA memory is supported<BR>
+  #  Other BITs are reseved and must be zero.
+  #  If more than one features are supported, the different BIT will be enabled at the same time.
+  # @Prompt ISA Bus Features
+  # @Expression 0x80000002 | (gBoardModuleTokenSpaceGuid.PcdIsaBusSupportedFeatures & 0xF8) == 0
+  gBoardModuleTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x00010040
+
+  gBoardModuleTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x00010037
+
+[Protocols]
+  ##
+  ## IntelFrameworkModulePkg
+  ##
+  gEfiOemBadgingProtocolGuid                       = { 0x170E13C0, 0xBF1B, 0x4218, { 0x87, 0x1D, 0x2A, 0xBD, 0xC6, 0xF8, 0x87, 0xBC }}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
new file mode 100644
index 0000000000..f6ef44a14f
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.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/SimicsVideoDxe/SimicsVideoDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
new file mode 100644
index 0000000000..002cb56826
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
@@ -0,0 +1,74 @@
+## @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
+  Simics.h
+
+[Sources.Ia32, Sources.X64]
+  VbeShim.c
+  VbeShim.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OptionRomPkg/OptionRomPkg.dec
+  OvmfPkg/OvmfPkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.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
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
new file mode 100644
index 0000000000..a82077e2d9
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
@@ -0,0 +1,279 @@
+; @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/SimicsVideoDxe/VbeShim.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
new file mode 100644
index 0000000000..cc9b6e14cd
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.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/SimicsVideoDxe/VbeShim.sh b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh
new file mode 100644
index 0000000000..7669f8a219
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.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
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 6/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (4 preceding siblings ...)
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
  6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add BoardX58ICH10 modules for QSP(Quick Start Platform) Build tip

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 .../Library/BoardInitLib/PeiBoardInitPostMemLib.c  |  44 +++
 .../Library/BoardInitLib/PeiBoardInitPreMemLib.c   | 110 ++++++++
 .../Library/BoardInitLib/PeiX58Ich10Detect.c       |  26 ++
 .../BoardInitLib/PeiX58Ich10InitPostMemLib.c       |  34 +++
 .../BoardInitLib/PeiX58Ich10InitPreMemLib.c        | 111 ++++++++
 .../BoardX58Ich10/DecomprScratchEnd.fdf.inc        |  67 +++++
 .../BoardInitLib/PeiBoardInitPostMemLib.inf        |  36 +++
 .../Library/BoardInitLib/PeiBoardInitPreMemLib.inf |  39 +++
 .../Library/BoardInitLib/PeiX58Ich10InitLib.h      |  16 ++
 .../BoardX58Ich10/OpenBoardPkg.dsc                 | 233 ++++++++++++++++
 .../BoardX58Ich10/OpenBoardPkg.fdf                 | 304 +++++++++++++++++++++
 .../BoardX58Ich10/OpenBoardPkg.fdf.inc             |  54 ++++
 .../BoardX58Ich10/OpenBoardPkgBuildOption.dsc      |  78 ++++++
 .../BoardX58Ich10/OpenBoardPkgConfig.dsc           |  56 ++++
 .../BoardX58Ich10/OpenBoardPkgPcd.dsc              | 281 +++++++++++++++++++
 .../BoardX58Ich10/VarStore.fdf.inc                 |  53 ++++
 .../BoardX58Ich10/build_config.cfg                 |  31 +++
 17 files changed, 1573 insertions(+)
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10Detect.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPostMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPreMemLib.c
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/DecomprScratchEnd.fdf.inc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitLib.h
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf.inc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOption.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgPcd.dsc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/VarStore.fdf.inc
 create mode 100644 Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg

diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.c b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.c
new file mode 100644
index 0000000000..5ece8c6e34
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.c
@@ -0,0 +1,44 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/BoardInitLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitBeforeSiliconInit (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitAfterSiliconInit (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+BoardInitBeforeSiliconInit (
+  VOID
+  )
+{
+  X58Ich10BoardInitBeforeSiliconInit ();
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BoardInitAfterSiliconInit (
+  VOID
+  )
+{
+  X58Ich10BoardInitAfterSiliconInit ();
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.c b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.c
new file mode 100644
index 0000000000..d16e649d34
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.c
@@ -0,0 +1,110 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/BoardInitLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardDetect(
+  VOID
+  );
+
+EFI_BOOT_MODE
+EFIAPI
+X58Ich10BoardBootModeDetect (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardDebugInit (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitBeforeMemoryInit (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitAfterMemoryInit (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+BoardDetect (
+  VOID
+  )
+{
+  X58Ich10BoardDetect ();
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BoardDebugInit (
+  VOID
+  )
+{
+  X58Ich10BoardDebugInit ();
+  return EFI_SUCCESS;
+}
+
+EFI_BOOT_MODE
+EFIAPI
+BoardBootModeDetect (
+  VOID
+  )
+{
+  return X58Ich10BoardBootModeDetect ();
+}
+
+EFI_STATUS
+EFIAPI
+BoardInitBeforeMemoryInit (
+  VOID
+  )
+{
+  X58Ich10BoardInitBeforeMemoryInit ();
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BoardInitAfterMemoryInit (
+  VOID
+  )
+{
+  X58Ich10BoardInitAfterMemoryInit ();
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BoardInitBeforeTempRamExit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BoardInitAfterTempRamExit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10Detect.c b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10Detect.c
new file mode 100644
index 0000000000..03488ef1f4
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10Detect.c
@@ -0,0 +1,26 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BoardInitLib.h>
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardDetect (
+  VOID
+  )
+{
+  DEBUG ((EFI_D_INFO, "X58Ich10BoardDetect\n"));
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPostMemLib.c b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPostMemLib.c
new file mode 100644
index 0000000000..bd6924e269
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPostMemLib.c
@@ -0,0 +1,34 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+
+#include "PeiX58Ich10InitLib.h"
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitBeforeSiliconInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitAfterSiliconInit (
+  VOID
+  )
+{
+
+  DEBUG((EFI_D_ERROR, "X58Ich10BoardInitAfterSiliconInit\n"));
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPreMemLib.c b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPreMemLib.c
new file mode 100644
index 0000000000..c3a31ed426
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitPreMemLib.c
@@ -0,0 +1,111 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/BoardInitLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+#include "PeiX58Ich10InitLib.h"
+#include <Register/X58Ich10.h>
+/**
+  Reads 8-bits of CMOS data.
+
+  Reads the 8-bits of CMOS data at the location specified by Index.
+  The 8-bit read value is returned.
+
+  @param  Index  The CMOS location to read.
+
+  @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8(
+  IN  UINTN                     Index
+  )
+{
+  IoWrite8 (0x70, (UINT8)Index);
+  return IoRead8(0x71);
+}
+
+
+/**
+  Writes 8-bits of CMOS data.
+
+  Writes 8-bits of CMOS data to the location specified by Index
+  with the value specified by Value and returns Value.
+
+  @param  Index  The CMOS location to write.
+  @param  Value  The value to write to CMOS.
+
+  @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8(
+  IN  UINTN                     Index,
+  IN  UINT8                     Value
+  )
+{
+  IoWrite8 (0x70, (UINT8)Index);
+  IoWrite8 (0x71, Value);
+  return Value;
+}
+
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitBeforeMemoryInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardInitAfterMemoryInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+X58Ich10BoardDebugInit (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EFI_BOOT_MODE
+EFIAPI
+X58Ich10BoardBootModeDetect (
+  VOID
+  )
+{
+  EFI_BOOT_MODE BootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+  DEBUG((EFI_D_INFO, "modeValue = %x\n", IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12)));
+  if (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) == 0x5) {
+    BootMode = BOOT_ON_S3_RESUME;
+  }
+
+  return BootMode;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/DecomprScratchEnd.fdf.inc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/DecomprScratchEnd.fdf.inc
new file mode 100644
index 0000000000..ae9a625da9
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/DecomprScratchEnd.fdf.inc
@@ -0,0 +1,67 @@
+## @file
+#  This FDF include file computes the end of the scratch buffer used in
+#  DecompressMemFvs() [SimicsX58Pkg/Sec/SecMain.c]. It is based on the decompressed
+#  (ie. original) size of the LZMA-compressed section of the one FFS file in
+#  the FVMAIN_COMPACT firmware volume.
+#
+#  Copyright (C) 2015, Red Hat, Inc.
+#  Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# The GUID EE4E5898-3914-4259-9D6E-DC7BD79403CF means "LzmaCustomDecompress".
+# The decompressed output will have the following structure (see the file
+# "9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy" in the
+# Build/SimicsX58*/*/FV/Ffs/9E21FD93-9C72-4c15-8C4B-E77F1DB2D792/ directory):
+#
+# Size                 Contents
+# -------------------  --------------------------------------------------------
+#                   4  EFI_COMMON_SECTION_HEADER, stating size 124 (0x7C) and
+#                      type 0x19 (EFI_SECTION_RAW). The purpose of this section
+#                      is to pad the start of PEIFV to 128 bytes.
+#                 120  Zero bytes (padding).
+#
+#                   4  EFI_COMMON_SECTION_HEADER, stating size
+#                      (PcdSimicsPeiMemFvSize + 4), and type 0x17
+#                      (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdSimicsPeiMemFvSize  PEIFV. Note that the above sizes pad the offset of this
+#                      object to 128 bytes. See also the "guided.dummy.txt"
+#                      file in the same directory.
+#
+#                   4  EFI_COMMON_SECTION_HEADER, stating size 12 (0xC) and
+#                      type 0x19 (EFI_SECTION_RAW). The purpose of this section
+#                      is to pad the start of DXEFV to 16 bytes.
+#                   8  Zero bytes (padding).
+#
+#                   4  EFI_COMMON_SECTION_HEADER, stating size
+#                      (PcdSimicsDxeMemFvSize + 4), and type 0x17
+#                      (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdSimicsDxeMemFvSize  DXEFV. Note that the above sizes pad the offset of this
+#                      object to 16 bytes. See also the "guided.dummy.txt" file
+#                      in the same directory.
+#
+# The total size after decompression is (128 + PcdSimicsPeiMemFvSize + 16 +
+# PcdSimicsDxeMemFvSize).
+
+DEFINE OUTPUT_SIZE = (128 + gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize + 16 + gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize)
+
+# LzmaCustomDecompressLib uses a constant scratch buffer size of 64KB; see
+# SCRATCH_BUFFER_REQUEST_SIZE in
+# "MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c".
+
+DEFINE DECOMP_SCRATCH_SIZE = 0x00010000
+
+# Note: when we use PcdSimicsDxeMemFvBase in this context, BaseTools have not yet
+# offset it with MEMFD's base address. For that reason we have to do it manually.
+#
+# The calculation below mirrors DecompressMemFvs() [SimicsX58Pkg/Sec/SecMain.c].
+
+DEFINE OUTPUT_BASE                   = ($(MEMFD_BASE_ADDRESS) + gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase + 0x00100000)
+DEFINE DECOMP_SCRATCH_BASE_UNALIGNED = ($(OUTPUT_BASE) + $(OUTPUT_SIZE))
+DEFINE DECOMP_SCRATCH_BASE_ALIGNMENT = 0x000FFFFF
+DEFINE DECOMP_SCRATCH_BASE_MASK      = 0xFFF00000
+DEFINE DECOMP_SCRATCH_BASE           = (($(DECOMP_SCRATCH_BASE_UNALIGNED) + $(DECOMP_SCRATCH_BASE_ALIGNMENT)) & $(DECOMP_SCRATCH_BASE_MASK))
+
+SET gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd = $(DECOMP_SCRATCH_BASE) + $(DECOMP_SCRATCH_SIZE)
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.inf b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.inf
new file mode 100644
index 0000000000..a035eb0e50
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPostMemLib.inf
@@ -0,0 +1,36 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiBoardPostMemInitLib
+  FILE_GUID                      = 30F407D6-6B92-412A-B2DA-8E73E2B386E6
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = BoardInitLib
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  PcdLib
+
+[Packages]
+  MinPlatformPkg/MinPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+  PeiX58Ich10InitPostMemLib.c
+  PeiBoardInitPostMemLib.c
+
+[FixedPcd]
+
+[Pcd]
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.inf b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
new file mode 100644
index 0000000000..08a6eb159a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
@@ -0,0 +1,39 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiBoardInitPreMemLib
+  FILE_GUID                      = 73AA24AE-FB20-43F9-A3BA-448953A03A78
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = BoardInitLib
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  PcdLib
+
+[Packages]
+  MinPlatformPkg/MinPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SimicsOpenBoardPkg/OpenBoardPkg.dec
+  SimicsIch10Pkg/Ich10Pkg.dec
+
+[Sources]
+  PeiX58Ich10Detect.c
+  PeiX58Ich10InitPreMemLib.c
+  PeiBoardInitPreMemLib.c
+
+[Pcd]
+
+[FixedPcd]
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitLib.h b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitLib.h
new file mode 100644
index 0000000000..93544a838b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX58Ich10InitLib.h
@@ -0,0 +1,16 @@
+/** @file
+  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PEI_X58Ich10_BOARD_INIT_LIB_H_
+#define _PEI_X58Ich10_BOARD_INIT_LIB_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.dsc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.dsc
new file mode 100644
index 0000000000..59e13154a7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.dsc
@@ -0,0 +1,233 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  DEFINE PLATFORM_PACKAGE      = MinPlatformPkg
+  DEFINE BOARD_NAME            = BoardX58Ich10
+  DEFINE BOARD_PKG             = SimicsOpenBoardPkg
+  DEFINE SKT_PKG               = SimicsX58SktPkg
+  DEFINE PCH_PKG               = SimicsIch10Pkg
+  DEFINE DXE_ARCH              = X64
+  DEFINE PEI_ARCH              = IA32
+
+  PLATFORM_NAME                  = SimicsX58
+  PLATFORM_GUID                  = EE8EBB5A-CC95-412f-9987-2AF70F88B69A
+  PLATFORM_VERSION               = 0.1
+  DSC_SPECIFICATION              = 0x00010005
+  OUTPUT_DIRECTORY               = Build/SimicsX58Ia32X64
+  SUPPORTED_ARCHITECTURES        = IA32|X64
+  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
+  SKUID_IDENTIFIER               = DEFAULT
+  FLASH_DEFINITION               = $(BOARD_PKG)/$(BOARD_NAME)/OpenBoardPkg.fdf
+
+  DEFINE SMM_REQUIRE             = TRUE
+
+  #
+  #PLATFORMX64_ENABLE is set to TRUE when PEI is IA32 and DXE is X64 platform
+  #
+  DEFINE PLATFORMX64_ENABLE             = TRUE
+  DEFINE NETWORK_TLS_ENABLE             = FALSE
+  DEFINE NETWORK_ISCSI_ENABLE           = FALSE
+  DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+  !include NetworkPkg/NetworkDefines.dsc.inc
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this Platform.
+#
+################################################################################
+[SkuIds]
+  0|DEFAULT
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+[PcdsFeatureFlag]
+  #
+  # Platform On/Off features are defined here
+  #
+  !include $(BOARD_PKG)/$(BOARD_NAME)/OpenBoardPkgConfig.dsc
+  !include MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
+  !include $(PCH_PKG)/IchCommonLib.dsc
+
+[LibraryClasses]
+  ReportFvLib|$(BOARD_PKG)/Library/PeiReportFvLib/PeiReportFvLib.inf
+  BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+  SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
+  NvVarsFileLib|$(BOARD_PKG)/Library/NvVarsFileLib/NvVarsFileLib.inf
+  SerializeVariablesLib|$(BOARD_PKG)/Library/SerializeVariablesLib/SerializeVariablesLib.inf
+  DxeLoadLinuxLib|$(BOARD_PKG)/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
+  CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
+
+  TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLibNull/TestPointCheckLibNull.inf
+  BoardInitLib|MinPlatformPkg/PlatformInit/Library/BoardInitLibNull/BoardInitLibNull.inf
+  SiliconPolicyInitLib|$(BOARD_PKG)/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
+  SiliconPolicyUpdateLib|$(BOARD_PKG)/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
+  PciSegmentInfoLib|MinPlatformPkg/Pci/Library/PciSegmentInfoLibSimple/PciSegmentInfoLibSimple.inf
+
+  !include MinPlatformPkg/Include/Dsc/CorePeiLib.dsc
+
+  S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+  AslUpdateLib|MinPlatformPkg/Acpi/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf
+  LogoLib|$(BOARD_PKG)/Library/DxeLogoLib/DxeLogoLib.inf
+[LibraryClasses.common.SEC]
+  ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+
+[LibraryClasses.common.PEI_CORE]
+
+[LibraryClasses.common.PEIM]
+  PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+  MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+
+[LibraryClasses.IA32]
+!if $(TARGET) == DEBUG
+  TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLib/PeiTestPointCheckLib.inf
+!endif
+  TestPointLib|MinPlatformPkg/Test/Library/TestPointLib/PeiTestPointLib.inf
+
+  !include MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc
+
+[LibraryClasses.common.DXE_DRIVER]
+  PlatformBootManagerLib|$(BOARD_PKG)/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+  SpiFlashCommonLib|$(PCH_PKG)/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
+
+  !include $(BOARD_PKG)/$(BOARD_NAME)/OpenBoardPkgPcd.dsc
+
+[Components.IA32]
+  $(BOARD_PKG)/SecCore/SecMain.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+  }
+  !include $(SKT_PKG)/SktPkgPei.dsc
+  !include MinPlatformPkg/Include/Dsc/CorePeiInclude.dsc
+
+  $(BOARD_PKG)/SimicsPei/SimicsPei.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+#  S3 SMM driver
+#  UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf {
+    <LibraryClasses>
+      LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+  }
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly == FALSE
+  $(SKT_PKG)/Smm/Access/SmmAccessPei.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
+!endif
+  $(PLATFORM_PACKAGE)/PlatformInit/ReportFv/ReportFvPei.inf
+
+  MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPreMem.inf {
+    <LibraryClasses>
+      BoardInitLib|$(BOARD_PKG)/$(BOARD_NAME)/Library/BoardInitLib/PeiBoardInitPreMemLib.inf
+  }
+  MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPostMem.inf {
+    <LibraryClasses>
+      BoardInitLib|$(BOARD_PKG)/$(BOARD_NAME)/Library/BoardInitLib/PeiBoardInitPostMemLib.inf
+  }
+  MinPlatformPkg/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPreMem.inf
+  MinPlatformPkg/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPostMem.inf
+
+[Components.X64]
+  !include MinPlatformPkg/Include/Dsc/CoreDxeInclude.dsc
+  !include AdvancedFeaturePkg/Include/Dsc/CoreAdvancedDxeInclude.dsc
+
+  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+
+  MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
+  #
+  # ISA Support
+  #
+  $(BOARD_PKG)/LegacySioDxe/LegacySioDxe.inf
+  MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+
+  $(BOARD_PKG)/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+  $(BOARD_PKG)/AcpiTables/AcpiTables.inf
+  #
+  # Video support
+  #
+  $(BOARD_PKG)/SimicsVideoDxe/SimicsVideoDxe.inf
+
+  MinPlatformPkg/PlatformInit/PlatformInitDxe/PlatformInitDxe.inf
+  MinPlatformPkg/PlatformInit/PlatformInitSmm/PlatformInitSmm.inf
+  $(BOARD_PKG)/SimicsDxe/SimicsDxe.inf
+  MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+  MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+
+  SimicsIch10BinPkg/UndiBinary/UndiDxe.inf
+
+  #
+  # Shell
+  #
+  ShellPkg/Application/Shell/Shell.inf {
+   <PcdsFixedAtBuild>
+     gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+   <LibraryClasses>
+     NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+     NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
+     ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+     HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+     BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+     ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+     ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+  }
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly == FALSE
+  $(SKT_PKG)/Smm/Access/SmmAccess2Dxe.inf
+  $(PCH_PKG)/SmmControl/RuntimeDxe/SmmControl2Dxe.inf
+  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+  $(PCH_PKG)/Spi/Smm/PchSpiSmm.inf
+  MinPlatformPkg/Flash/SpiFvbService/SpiFvbServiceSmm.inf
+  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+  MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf {
+    <LibraryClasses>
+      LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+  }
+!endif
+  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
+    <LibraryClasses>
+      PciHostBridgeLib|$(BOARD_PKG)/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+  }
+  MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+
+  UefiCpuPkg/CpuDxe/CpuDxe.inf
+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+  #
+  # ACPI Support
+  #
+  MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+  $(BOARD_PKG)/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
+
+!if gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosEnable == TRUE
+  AdvancedFeaturePkg/Smbios/SmbiosBasicDxe/SmbiosBasicDxe.inf
+!endif
+
+  !include $(BOARD_PKG)/$(BOARD_NAME)/OpenBoardPkgBuildOption.dsc
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf
new file mode 100644
index 0000000000..6c1579bef7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf
@@ -0,0 +1,304 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+!include OpenBoardPkg.fdf.inc
+
+#
+# Build the variable store and the firmware code as one unified flash device
+# image.
+#
+[FD.SIMICSX58IA32X64]
+BaseAddress   = $(FW_BASE_ADDRESS)
+Size          = $(FW_SIZE)
+ErasePolarity = 1
+BlockSize     = $(BLOCK_SIZE)
+NumBlocks     = $(FW_BLOCKS)
+
+!include VarStore.fdf.inc
+
+$(VARS_SIZE)|0x00002000
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#NV_FTW_WORKING
+DATA = {
+  # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid         =
+  #  { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+  0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+  0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95,
+  # Crc:UINT32            #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+  0xE2, 0x33, 0xF2, 0x03, 0xFE, 0xFF, 0xFF, 0xFF,
+  # WriteQueueSize: UINT64
+  0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+0x00040000|0x00040000
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+#NV_FTW_SPARE
+
+0x00080000|0x0016C000
+FV = FVMAIN_COMPACT
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+FV = FvTempMemorySilicon
+
+#
+# Build the variable store and the firmware code as separate flash device
+# images.
+#
+[FD.SIMICS_VARS]
+BaseAddress   = $(FW_BASE_ADDRESS)
+Size          = 0x80000
+ErasePolarity = 1
+BlockSize     = $(BLOCK_SIZE)
+NumBlocks     = 0x80
+
+!include VarStore.fdf.inc
+
+[FD.SIMICS_CODE]
+BaseAddress   = $(CODE_BASE_ADDRESS)
+Size          = $(CODE_SIZE)
+ErasePolarity = 1
+BlockSize     = $(BLOCK_SIZE)
+NumBlocks     = $(CODE_BLOCKS)
+
+0x00000000|0x0016C000
+FV = FVMAIN_COMPACT
+
+0x0016C000|$(SECFV_SIZE)
+FV = FvTempMemorySilicon
+
+[FD.MEMFD]
+BaseAddress   = $(MEMFD_BASE_ADDRESS)
+Size          = 0xB00000
+ErasePolarity = 1
+BlockSize     = 0x10000
+NumBlocks     = 0xB0
+
+0x000000|0x006000
+gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase|gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesSize
+
+0x006000|0x001000
+gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase|gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize
+
+0x007000|0x001000
+gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+
+0x010000|0x008000
+gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize
+
+0x020000|0x0E0000
+gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase|gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+FV = FvPreMemory
+
+0x100000|0xA00000
+gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase|gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+FV = DXEFV
+
+################################################################################
+
+[FV.FvTempMemorySilicon]
+FvAlignment        = 16
+FvForceRebase      = TRUE
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+FvNameGuid         = 229EEDCE-8E76-4809-B233-EC36BFBF6989
+
+INF  RuleOverride=RESET_SECMAIN USE = IA32 $(BOARD_PKG)/SecCore/SecMain.inf
+!include $(SKT_PKG)/SktSecInclude.fdf
+
+[FV.FvPreMemory]
+FvAlignment        = 16
+FvForceRebase      = TRUE
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+FvNameGuid         = 6522280D-28F9-4131-ADC4-F40EBFA45864
+
+##
+#  PEI Apriori file example, more PEIM module added later.
+##
+INF  MdeModulePkg/Core/Pei/PeiMain.inf
+!include $(SKT_PKG)/SktPreMemoryInclude.fdf
+!include $(PCH_PKG)/IchPreMemoryInclude.fdf
+!include MinPlatformPkg/Include/Fdf/CorePreMemoryInclude.fdf
+INF  MinPlatformPkg/PlatformInit/ReportFv/ReportFvPei.inf
+INF  MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPreMem.inf
+INF  MinPlatformPkg/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPreMem.inf
+!include MinPlatformPkg/Include/Fdf/CoreSecurityPreMemoryInclude.fdf
+!include AdvancedFeaturePkg/Include/Fdf/CoreAdvancedPreMemoryInclude.fdf
+INF  $(BOARD_PKG)/SimicsPei/SimicsPei.inf
+!include $(SKT_PKG)/SktPostMemoryInclude.fdf
+!include $(PCH_PKG)/IchPostMemoryInclude.fdf
+!include MinPlatformPkg/Include/Fdf/CorePostMemoryInclude.fdf
+INF  MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPostMem.inf
+INF  MinPlatformPkg/PlatformInit/SiliconPolicyPei/SiliconPolicyPeiPostMem.inf
+!include MinPlatformPkg/Include/Fdf/CoreSecurityPostMemoryInclude.fdf
+!include AdvancedFeaturePkg/Include/Fdf/CoreAdvancedPostMemoryInclude.fdf
+
+INF  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+INF  $(SKT_PKG)/Smm/Access/SmmAccessPei.inf
+# S3 SMM PEI driver
+#INF  UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
+
+[FV.DXEFV]
+FvNameGuid         = EACAB9EA-C3C6-4438-8FD7-2270826DC0BB
+BlockSize          = 0x10000
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+!include MinPlatformPkg/Include/Fdf/CoreUefiBootInclude.fdf
+!include $(SKT_PKG)/SktUefiBootInclude.fdf
+!include $(PCH_PKG)/IchUefiBootInclude.fdf
+
+INF  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+INF  MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
+INF  UefiCpuPkg/CpuDxe/CpuDxe.inf
+
+!include MinPlatformPkg/Include/Fdf/CoreOsBootInclude.fdf
+INF  MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+INF  MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+INF  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+INF  MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+INF  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF  MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+INF  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+
+INF  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+INF  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+INF  MinPlatformPkg/Flash/SpiFvbService/SpiFvbServiceSmm.inf
+INF  MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+
+INF  $(BOARD_PKG)/LegacySioDxe/LegacySioDxe.inf
+INF  MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+
+INF  $(BOARD_PKG)/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+INF  MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+INF  $(BOARD_PKG)/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
+INF  RuleOverride=ACPITABLE $(BOARD_PKG)/AcpiTables/AcpiTables.inf
+
+INF $(BOARD_PKG)/SimicsVideoDxe/SimicsVideoDxe.inf
+INF  MinPlatformPkg/PlatformInit/PlatformInitDxe/PlatformInitDxe.inf
+INF  MinPlatformPkg/PlatformInit/PlatformInitSmm/PlatformInitSmm.inf
+INF  $(BOARD_PKG)/SimicsDxe/SimicsDxe.inf
+
+FILE FREEFORM = 7BB28B99-61BB-11D5-9A5D-0090273FC14D {
+  SECTION RAW = $(BOARD_PKG)/Logo/Logo.bmp
+}
+
+INF  ShellPkg/Application/Shell/Shell.inf
+
+#
+# Network modules
+#
+INF  SimicsIch10BinPkg/UndiBinary/UndiDxe.inf
+
+!include AdvancedFeaturePkg/Include/Fdf/CoreAdvancedLateInclude.fdf
+
+!if gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosEnable == TRUE
+  INF  AdvancedFeaturePkg/Smbios/SmbiosBasicDxe/SmbiosBasicDxe.inf
+!endif
+
+!include MinPlatformPkg/Include/Fdf/CoreSecurityLateInclude.fdf
+
+[FV.FVMAIN_COMPACT]
+FvNameGuid         = 6189987A-DDA6-4060-B313-49168DA9BD46
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+  SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+    #
+    # These firmware volumes will have files placed in them uncompressed,
+    # and then both firmware volumes will be compressed in a single
+    # compression operation in order to achieve better overall compression.
+    #
+    SECTION FV_IMAGE = FvPreMemory
+    SECTION FV_IMAGE = DXEFV
+  }
+}
+
+!include DecomprScratchEnd.fdf.inc
+
+
+################################################################################
+#
+# Rules are use with the [FV] section's module INF type to define
+# how an FFS file is created for a given INF file. The following Rule are the default
+# rules for the different module type. User can add the customized rules to define the
+# content of the FFS file.
+#
+################################################################################
+
+!include MinPlatformPkg/Include/Fdf/RuleInclude.fdf
+
+[Rule.Common.SEC.RESET_VECTOR]
+  FILE RAW = $(NAMED_GUID) {
+    RAW RAW      |.raw
+  }
+
+[Rule.Common.SEC.RESET_SECMAIN]
+  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+    PE32  PE32    Align = 16      $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf.inc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf.inc
new file mode 100644
index 0000000000..044129c941
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.fdf.inc
@@ -0,0 +1,54 @@
+## @file
+#  FDF include file that defines the main macros and sets the dependent PCDs.
+#
+#  Copyright (C) 2014, Red Hat, Inc.
+#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# Default flash size is 2MB.
+#
+# Defining FD_SIZE_2MB on the build command line can override this.
+#
+
+DEFINE BLOCK_SIZE        = 0x1000
+DEFINE VARS_SIZE         = 0x3e000
+DEFINE VARS_BLOCKS       = 0x3e
+
+DEFINE FW_BASE_ADDRESS   = 0xFFE00000
+DEFINE FW_SIZE           = 0x00200000
+DEFINE FW_BLOCKS         = 0x200
+DEFINE CODE_BASE_ADDRESS = 0xFFE80000
+DEFINE CODE_SIZE         = 0x00180000
+DEFINE CODE_BLOCKS       = 0x180
+DEFINE FVMAIN_SIZE       = 0x0016C000
+DEFINE SECFV_OFFSET      = 0x001EC000
+DEFINE SECFV_SIZE        = 0x14000
+
+
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFdBaseAddress     = $(FW_BASE_ADDRESS)
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareFdSize    = $(FW_SIZE)
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareBlockSize = $(BLOCK_SIZE)
+
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase = $(FW_BASE_ADDRESS)
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize = 0xE000
+
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogBase = gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize = $(BLOCK_SIZE)
+
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase = gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogBase + gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZE)
+
+SET gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwSpareBase = gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = 0x10000
+
+SET gEfiPchTokenSpaceGuid.PcdFlashAreaBaseAddress = 0xFFE00000
+SET gEfiPchTokenSpaceGuid.PcdFlashAreaSize = 0x00200000
+
+SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress = gEfiPchTokenSpaceGuid.PcdFlashAreaBaseAddress
+SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = gEfiPchTokenSpaceGuid.PcdFlashAreaSize
+
+DEFINE MEMFD_BASE_ADDRESS = 0x800000
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOption.dsc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOption.dsc
new file mode 100644
index 0000000000..25998b83e7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOption.dsc
@@ -0,0 +1,78 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[BuildOptions.Common.EDKII]
+# Append build options for EDK and EDKII drivers (= is Append, == is Replace)
+
+  DEFINE EDKII_DSC_FEATURE_BUILD_OPTIONS =
+
+!if $(TARGET) == "DEBUG"
+  DEFINE DEBUG_BUILD_FLAG = -D SERIAL_DBG_MSG=1
+!else
+  DEFINE DEBUG_BUILD_FLAG = -D MDEPKG_NDEBUG -D SILENT_MODE
+!endif
+
+  DEFINE EDKII_DSC_FEATURE_BUILD_OPTIONS     = $(EDKII_DSC_FEATURE_BUILD_OPTIONS) $(DEBUG_BUILD_FLAG)
+#
+# PC_BUILD_END
+#
+
+
+  DEFINE EDKII_DSC_FEATURE_BUILD_OPTIONS     = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+
+
+  *_*_IA32_CC_FLAGS    = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_IA32_VFRPP_FLAGS = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_IA32_APP_FLAGS   = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_IA32_PP_FLAGS    = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_IA32_ASLPP_FLAGS = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_IA32_ASLCC_FLAGS = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+
+  *_*_X64_CC_FLAGS     = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_X64_VFRPP_FLAGS  = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_X64_APP_FLAGS    = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_X64_PP_FLAGS     = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_X64_ASLPP_FLAGS  = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+  *_*_X64_ASLCC_FLAGS  = $(EDKII_DSC_FEATURE_BUILD_OPTIONS)
+
+
+
+#
+# Enable source level debugging for RELEASE build
+#
+!if $(TARGET) == "RELEASE"
+  DEFINE EDKII_RELEASE_SRCDBG_ASM_BUILD_OPTIONS   = /Zi
+  DEFINE EDKII_RELEASE_SRCDBG_CC_BUILD_OPTIONS    = /Zi /Gm
+  DEFINE EDKII_RELEASE_SRCDBG_DLINK_BUILD_OPTIONS = /DEBUG
+
+  MSFT:*_*_*_ASM_FLAGS    = $(EDKII_RELEASE_SRCDBG_ASM_BUILD_OPTIONS)
+  MSFT:*_*_*_CC_FLAGS     = $(EDKII_RELEASE_SRCDBG_CC_BUILD_OPTIONS)
+  MSFT:*_*_*_DLINK_FLAGS  = $(EDKII_RELEASE_SRCDBG_DLINK_BUILD_OPTIONS)
+!endif
+
+
+#
+# Override the existing iasl path in tools_def.template
+#
+#  MSFT:*_*_*_ASL_PATH == c:/Iasl/iasl.exe
+
+#
+# Override the VFR compile flags to speed the build time
+#
+
+*_*_*_VFR_FLAGS                     ==  -n
+
+# Force PE/COFF sections to be aligned at 4KB boundaries to support page level protection
+#[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
+#  MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
+#  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
+
+# Force PE/COFF sections to be aligned at 4KB boundaries to support MemoryAttribute table
+#[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+#  MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
+#  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.dsc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.dsc
new file mode 100644
index 0000000000..75de60e5bc
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.dsc
@@ -0,0 +1,56 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# TRUE is ENABLE. FALSE is DISABLE.
+#
+
+[PcdsFixedAtBuild]
+  gMinPlatformPkgTokenSpaceGuid.PcdBootStage|4
+
+[PcdsFeatureFlag]
+  gMinPlatformPkgTokenSpaceGuid.PcdStopAfterDebugInit|FALSE
+  gMinPlatformPkgTokenSpaceGuid.PcdStopAfterMemInit|FALSE
+  gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly|FALSE
+  gMinPlatformPkgTokenSpaceGuid.PcdUefiSecureBootEnable|FALSE
+  gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable|FALSE
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootStage >= 1
+  gMinPlatformPkgTokenSpaceGuid.PcdStopAfterDebugInit|TRUE
+!endif
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootStage >= 2
+  gMinPlatformPkgTokenSpaceGuid.PcdStopAfterDebugInit|FALSE
+  gMinPlatformPkgTokenSpaceGuid.PcdStopAfterMemInit|TRUE
+!endif
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootStage >= 3
+  gMinPlatformPkgTokenSpaceGuid.PcdStopAfterMemInit|FALSE
+  gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly|TRUE
+!endif
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootStage >= 4
+  gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly|FALSE
+!endif
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootStage >= 5
+  gMinPlatformPkgTokenSpaceGuid.PcdUefiSecureBootEnable|TRUE
+  gMinPlatformPkgTokenSpaceGuid.PcdTpm2Enable|TRUE
+!endif
+
+  !if $(TARGET) == DEBUG
+    gMinPlatformPkgTokenSpaceGuid.PcdSmiHandlerProfileEnable|TRUE
+  !else
+    gMinPlatformPkgTokenSpaceGuid.PcdSmiHandlerProfileEnable|FALSE
+  !endif
+
+  gMinPlatformPkgTokenSpaceGuid.PcdPerformanceEnable|FALSE
+
+  gAdvancedFeaturePkgTokenSpaceGuid.PcdNetworkEnable|TRUE
+  gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosEnable|TRUE
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgPcd.dsc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgPcd.dsc
new file mode 100644
index 0000000000..3bf10ee524
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgPcd.dsc
@@ -0,0 +1,281 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsFeatureFlag.common]
+!if $(TARGET) == RELEASE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+!else
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
+!endif
+  # Server doesn't support capsle update on Reset.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport|FALSE
+
+
+#S3 add
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE
+#S3 add
+
+  ## This PCD specified whether ACPI SDT protocol is installed.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+
+[PcdsFeatureFlag.X64]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard|FALSE
+
+[PcdsFeatureFlag]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu|TRUE
+
+[PcdsDynamicExDefault]
+
+[PcdsFixedAtBuild.common]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|TRUE
+!if $(TARGET) == "RELEASE"
+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x03
+!else
+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+!endif
+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x0
+#S3 modified
+  gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot|TRUE
+#S3 modified
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x0
+  gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x0
+  gEfiMdePkgTokenSpaceGuid.PcdFSBClock|133333333
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize|0x100000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x1700000
+
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout|10000
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|512
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x4000
+
+  ## Specifies delay value in microseconds after sending out an INIT IPI.
+  # @Prompt Configure delay value after send an INIT IPI
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds|10
+
+  ## Specifies max supported number of Logical Processors.
+  # @Prompt Configure max supported number of Logical Processorss
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|512
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize|0x1000
+!if gMinPlatformPkgTokenSpaceGuid.PcdPerformanceEnable == TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1
+!endif
+
+  ## Defines the ACPI register set base address.
+  #  The invalid 0xFFFF is as its default value. It must be configured to the real value.
+  # @Prompt ACPI Timer IO Port Address
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress         |  0x0400
+
+  ## Defines the PCI Bus Number of the PCI device that contains the BAR and Enable for ACPI hardware registers.
+  # @Prompt ACPI Hardware PCI Bus Number
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber            |  0x00
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision|0x00000002
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId|0x4C544E49
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision|0x20091013
+
+  ## Defines the PCI Device Number of the PCI device that contains the BAR and Enable for ACPI hardware registers.
+  #  The invalid 0xFF is as its default value. It must be configured to the real value.
+  # @Prompt ACPI Hardware PCI Device Number
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber         |  0x1F
+
+  ## Defines the PCI Function Number of the PCI device that contains the BAR and Enable for ACPI hardware registers.
+  #  The invalid 0xFF is as its default value. It must be configured to the real value.
+  # @Prompt ACPI Hardware PCI Function Number
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber       |  0x00
+
+  ## Defines the PCI Register Offset of the PCI device that contains the Enable for ACPI hardware registers.
+  #  The invalid 0xFFFF is as its default value. It must be configured to the real value.
+  # @Prompt ACPI Hardware PCI Register Offset
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset |0x0044
+
+  ## Defines the bit mask that must be set to enable the APIC hardware register BAR.
+  # @Prompt ACPI Hardware PCI Bar Enable BitMask
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask           |  0x80
+
+  ## Defines the PCI Register Offset of the PCI device that contains the BAR for ACPI hardware registers.
+  #  The invalid 0xFFFF is as its default value. It must be configured to the real value.
+  # @Prompt ACPI Hardware PCI Bar Register Offset
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset    |0x0040
+
+  ## Defines the offset to the 32-bit Timer Value register that resides within the ACPI BAR.
+  # @Prompt Offset to 32-bit Timer register in ACPI BAR
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset              |0x0008
+
+  ## Defines the bit mask to retrieve ACPI IO Port Base Address
+  # @Prompt ACPI IO Port Base Address Mask
+  gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddressMask     |0xFFFC
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuThreadCount|4
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuCoreCount|128
+  gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount|4
+  gMinPlatformPkgTokenSpaceGuid.PcdLocalApicAddress|0xFEE00000
+  gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicAddressBase|0xFEC01000
+  gMinPlatformPkgTokenSpaceGuid.PcdFadtPreferredPmProfile|0x0
+  gMinPlatformPkgTokenSpaceGuid.PcdFadtIaPcBootArch|0x0003
+  gMinPlatformPkgTokenSpaceGuid.PcdFadtFlags|0x000004A5
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AEventBlockAddress|0x400
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BEventBlockAddress|0
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AControlBlockAddress|0x404
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BControlBlockAddress|0
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm2ControlBlockAddress|0x450
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiPmTimerBlockAddress|0x408
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe0BlockAddress|0x420
+  gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe1BlockAddress|0
+
+[PcdsFixedAtBuild.X64]
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0x0eB8
+  gPcAtChipsetPkgTokenSpaceGuid.PcdMinimalValidYear|2015
+  gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear|2099
+  # Change PcdBootManagerMenuFile to UiApp
+##
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable |TRUE
+
+ [PcdsPatchableInModule.common]
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdSmiHandlerProfileEnable == TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSmiHandlerProfilePropertyMask|0x1
+!endif
+
+  gPcAtChipsetPkgTokenSpaceGuid.PcdHpetBaseAddress|0xFED00000
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|1024
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
+
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeBase|0x0
+  gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeSize|0x0
+
+[PcdsDynamicExDefault.common.DEFAULT]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|30000
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress|0
+
+[PcdsDynamicExHii.common.DEFAULT]
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|50 # Variable: L"Timeout"
+  gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport"
+
+
+[PcdsDynamicExDefault]
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1F
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L""|VOID*|36
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId|{0x49, 0x4E, 0x54, 0x45, 0x4C, 0x20}
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId|0x2046573030363253
+
+[PcdsDynamicExDefault.X64]
+
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1
+  gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|0
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|800
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|600
+
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress|0
+
+[PcdsFeatureFlag]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+  #gOptionRomPkgTokenSpaceGuid.PcdSupportGop|TRUE
+  #gOptionRomPkgTokenSpaceGuid.PcdSupportUga|FALSE
+
+!if gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly == FALSE
+  gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire|TRUE
+!endif
+
+[PcdsFixedAtBuild]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x400
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xc000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0xc000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x2000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x10000
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+
+  # DEBUG_INIT      0x00000001  // Initialization
+  # DEBUG_WARN      0x00000002  // Warnings
+  # DEBUG_LOAD      0x00000004  // Load events
+  # DEBUG_FS        0x00000008  // EFI File system
+  # DEBUG_POOL      0x00000010  // Alloc & Free (pool)
+  # DEBUG_PAGE      0x00000020  // Alloc & Free (page)
+  # DEBUG_INFO      0x00000040  // Informational debug messages
+  # DEBUG_DISPATCH  0x00000080  // PEI/DXE/SMM Dispatchers
+  # DEBUG_VARIABLE  0x00000100  // Variable
+  # DEBUG_BM        0x00000400  // Boot Manager
+  # DEBUG_BLKIO     0x00001000  // BlkIo Driver
+  # DEBUG_NET       0x00004000  // SNP Driver
+  # DEBUG_UNDI      0x00010000  // UNDI Driver
+  # DEBUG_LOADFILE  0x00020000  // LoadFile
+  # DEBUG_EVENT     0x00080000  // Event messages
+  # DEBUG_GCD       0x00100000  // Global Coherency Database changes
+  # DEBUG_CACHE     0x00200000  // Memory range cachability changes
+  # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
+  #                             // significantly impact boot performance
+  # DEBUG_ERROR     0x80000000  // Error
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+
+  #
+  # PCI feature overrides.
+  #
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|FALSE
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+
+  gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId|0
+  gBoardModuleTokenSpaceGuid.PcdPciIoBase|0x0
+  gBoardModuleTokenSpaceGuid.PcdPciIoSize|0x0
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Base|0x0
+  gBoardModuleTokenSpaceGuid.PcdPciMmio32Size|0x0
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Base|0x0
+  gBoardModuleTokenSpaceGuid.PcdPciMmio64Size|0x800000000
+
+  gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0StringBiosVersion|"Ver.1.0.0"
+  gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType1StringProductName|"QSP UEFI BIOS"
+  gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType2StringProductName|"QSP UEFI BIOS"
+  gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0StringBiosReleaseDate|"2019-08-09"
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable|FALSE
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/VarStore.fdf.inc b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/VarStore.fdf.inc
new file mode 100644
index 0000000000..ea5b86228f
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/VarStore.fdf.inc
@@ -0,0 +1,53 @@
+## @file
+#  FDF include file with Layout Regions that define an empty variable store.
+#
+#  Copyright (C) 2014, Red Hat, Inc.
+#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+0x00000000|0x0003e000
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#NV_VARIABLE_STORE
+DATA = {
+  ## This is the EFI_FIRMWARE_VOLUME_HEADER
+  # ZeroVector []
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  # FileSystemGuid: gEfiSystemNvDataFvGuid         =
+  #   { 0xFFF12B8D, 0x7696, 0x4C8B,
+  #     { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+  0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+  0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+  # FvLength: 0x80000
+  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  #Signature "_FVH"       #Attributes
+  0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+  #HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision
+  0x48, 0x00, 0x2A, 0x09, 0x00, 0x00, 0x00, 0x02,
+  #Blockmap[0]: 7 Blocks * 0x10000 Bytes / Block
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+  #Blockmap[1]: End
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  ## This is the VARIABLE_STORE_HEADER
+!if $(SECURE_BOOT_ENABLE) == TRUE
+  # Signature: gEfiAuthenticatedVariableGuid =
+  #   { 0xaaf32c78, 0x947b, 0x439a,
+  #     { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
+  0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+  0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+!else
+  #Signature: gEfiVariableGuid =
+  #  { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
+  0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
+  0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
+!endif
+  #Size: 0x3E000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x03DFB8
+  # This can speed up the Variable Dispatch a bit.
+  0xB8, 0xDF, 0x03, 0x00,
+  # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+  0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg
new file mode 100644
index 0000000000..72512837f5
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg
@@ -0,0 +1,31 @@
+# @ build_config.cfg
+# This is the BoardX58Ich10 board specific build settings
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+
+[CONFIG]
+WORKSPACE_PLATFORM_BIN = edk2-non-osi/Platform/Intel
+EDK_SETUP_OPTION =
+openssl_path =
+PLATFORM_BOARD_PACKAGE = SimicsOpenBoardPkg
+PROJECT = SimicsOpenBoardPkg/BoardX58Ich10
+BOARD = BoardX58Ich10
+FLASH_MAP_FDF = SimicsOpenBoardPkg/BoardX58Ich10/Include/Fdf/FlashMapInclude.fdf
+PROJECT_DSC = SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkg.dsc
+BOARD_PKG_PCD_DSC = SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgPcd.dsc
+PrepRELEASE = DEBUG
+SILENT_MODE = FALSE
+EXT_CONFIG_CLEAR =
+CapsuleBuild = FALSE
+EXT_BUILD_FLAGS =
+CAPSULE_BUILD = 0
+TARGET = DEBUG
+TARGET_SHORT = D
+PERFORMANCE_BUILD = FALSE
+FSP_WRAPPER_BUILD = FALSE
+FSP_BINARY_BUILD = FALSE
+FSP_TEST_RELEASE = FALSE
+SECURE_BOOT_ENABLE = FALSE
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform
  2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (5 preceding siblings ...)
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 6/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
@ 2019-09-05 21:38 ` David Wei
  2019-09-07  1:03   ` [edk2-devel] " Kubacki, Michael A
  6 siblings, 1 reply; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
  To: devel
  Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
	Kubacki Michael A, Nate DeSimone, Michael D Kinney

Add build option in build script for SIMICS QSP(Quick Start Platform) Platform
Add Maintainers of Simics QSP related packages

Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>

Signed-off-by: David Wei <david.y.wei@intel.com>
---
 Maintainers.txt              | 12 ++++++++++++
 Platform/Intel/build.cfg     |  2 ++
 Platform/Intel/build_bios.py |  3 +++
 3 files changed, 17 insertions(+)

diff --git a/Maintainers.txt b/Maintainers.txt
index b16432bf87..90eb3c3dd0 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -103,6 +103,10 @@ M: Chasel Chiu <chasel.chiu@intel.com>
 M: Michael Kubacki <michael.a.kubacki@intel.com>
 M: Nate DeSimone <nathaniel.l.desimone@intel.com>
 
+Platform/Intel/SimicsOpenBoardPkg
+M: Wei David Y <david.y.wei@intel.com>
+M: Agyeman Prince <prince.agyeman@intel.com>
+
 Platform/Intel/Tools
 M: Bob Feng <bob.c.feng@intel.com>
 M: Liming Gao <liming.gao@intel.com>
@@ -155,6 +159,14 @@ M: Gillispie, Thad <thad.gillispie@intel.com>
 M: Bu, Daocheng <daocheng.bu@intel.com>
 M: Oram, Isaac W <isaac.w.oram@intel.com>
 
+Silicon/Intel/SimicsX58SktPkg
+M: Wei David Y <david.y.wei@intel.com>
+M: Agyeman Prince <prince.agyeman@intel.com>
+
+Silicon/Intel/SimicsIch10Pkg
+M: Wei David Y <david.y.wei@intel.com>
+M: Agyeman Prince <prince.agyeman@intel.com>
+
 Silicon/Intel/Tools
 M: Bob Feng <bob.c.feng@intel.com>
 M: Liming Gao <liming.gao@intel.com>
diff --git a/Platform/Intel/build.cfg b/Platform/Intel/build.cfg
index b6d32ada49..75cb446aa5 100644
--- a/Platform/Intel/build.cfg
+++ b/Platform/Intel/build.cfg
@@ -11,6 +11,7 @@ WORKSPACE =
 WORKSPACE_FSP_BIN = FSP
 EDK_TOOLS_BIN = edk2-BaseTools-win32
 EDK_BASETOOLS = BaseTools
+WORKSPACE_DRIVERS = edk2-platforms/Drivers
 WORKSPACE_PLATFORM = edk2-platforms/Platform/Intel
 WORKSPACE_SILICON = edk2-platforms/Silicon/Intel
 WORKSPACE_PLATFORM_BIN =
@@ -52,6 +53,7 @@ NUMBER_OF_PROCESSORS = 0
 [PLATFORMS]
 # board_name = path_to_board_build_config.cfg
 BoardMtOlympus = PurleyOpenBoardPkg/BoardMtOlympus/build_config.cfg
+BoardX58Ich10 = SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg
 KabylakeRvp3 = KabylakeOpenBoardPkg/KabylakeRvp3/build_config.cfg
 N1xxWU = ClevoOpenBoardPkg/N1xxWU/build_config.cfg
 WhiskeylakeURvp = WhiskeylakeOpenBoardPkg/WhiskeylakeURvp/build_config.cfg
diff --git a/Platform/Intel/build_bios.py b/Platform/Intel/build_bios.py
index 9152670dcb..46285df19a 100644
--- a/Platform/Intel/build_bios.py
+++ b/Platform/Intel/build_bios.py
@@ -104,6 +104,8 @@ def pre_build(build_config, build_type="DEBUG", silent=False, toolchain=None):
                                                 config["WORKSPACE_PLATFORM"])
     config["WORKSPACE_SILICON"] = os.path.join(config["WORKSPACE"],
                                                config["WORKSPACE_SILICON"])
+    config["WORKSPACE_DRIVERS"] = os.path.join(config["WORKSPACE"],
+                                               config["WORKSPACE_DRIVERS"])
     config["WORKSPACE_PLATFORM_BIN"] = \
         os.path.join(config["WORKSPACE"], config["WORKSPACE_PLATFORM_BIN"])
     config["WORKSPACE_SILICON_BIN"] = \
@@ -115,6 +117,7 @@ def pre_build(build_config, build_type="DEBUG", silent=False, toolchain=None):
     config["PACKAGES_PATH"] = config["WORKSPACE_PLATFORM"]
     config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_SILICON"]
     config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_SILICON_BIN"]
+    config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_DRIVERS"]
     config["PACKAGES_PATH"] += os.pathsep + \
         os.path.join(config["WORKSPACE"], "FSP")
     config["PACKAGES_PATH"] += os.pathsep + \
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform
  2019-09-05 21:38 ` [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
@ 2019-09-07  1:03   ` Kubacki, Michael A
  0 siblings, 0 replies; 9+ messages in thread
From: Kubacki, Michael A @ 2019-09-07  1:03 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wei, David Y
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Desimone, Nathaniel L, Kinney, Michael D

Reviewed-by: Michael Kubacki <michael.a.kubacki@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of David Wei
> Sent: Thursday, September 5, 2019 2:39 PM
> To: devel@edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Sinha, Ankit <ankit.sinha@intel.com>; Agyeman, Prince
> <prince.agyeman@intel.com>; Kubacki, Michael A
> <michael.a.kubacki@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Subject: [edk2-devel] [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build
> option for SIMICS QSP Platform
> 
> Add build option in build script for SIMICS QSP(Quick Start Platform) Platform
> Add Maintainers of Simics QSP related packages
> 
> Cc: Hao Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Ankit Sinha <ankit.sinha@intel.com>
> Cc: Agyeman Prince <prince.agyeman@intel.com>
> Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> 
> Signed-off-by: David Wei <david.y.wei@intel.com>
> ---
>  Maintainers.txt              | 12 ++++++++++++
>  Platform/Intel/build.cfg     |  2 ++
>  Platform/Intel/build_bios.py |  3 +++
>  3 files changed, 17 insertions(+)
> 
> diff --git a/Maintainers.txt b/Maintainers.txt index b16432bf87..90eb3c3dd0
> 100644
> --- a/Maintainers.txt
> +++ b/Maintainers.txt
> @@ -103,6 +103,10 @@ M: Chasel Chiu <chasel.chiu@intel.com>
>  M: Michael Kubacki <michael.a.kubacki@intel.com>
>  M: Nate DeSimone <nathaniel.l.desimone@intel.com>
> 
> +Platform/Intel/SimicsOpenBoardPkg
> +M: Wei David Y <david.y.wei@intel.com>
> +M: Agyeman Prince <prince.agyeman@intel.com>
> +
>  Platform/Intel/Tools
>  M: Bob Feng <bob.c.feng@intel.com>
>  M: Liming Gao <liming.gao@intel.com>
> @@ -155,6 +159,14 @@ M: Gillispie, Thad <thad.gillispie@intel.com>
>  M: Bu, Daocheng <daocheng.bu@intel.com>
>  M: Oram, Isaac W <isaac.w.oram@intel.com>
> 
> +Silicon/Intel/SimicsX58SktPkg
> +M: Wei David Y <david.y.wei@intel.com>
> +M: Agyeman Prince <prince.agyeman@intel.com>
> +
> +Silicon/Intel/SimicsIch10Pkg
> +M: Wei David Y <david.y.wei@intel.com>
> +M: Agyeman Prince <prince.agyeman@intel.com>
> +
>  Silicon/Intel/Tools
>  M: Bob Feng <bob.c.feng@intel.com>
>  M: Liming Gao <liming.gao@intel.com>
> diff --git a/Platform/Intel/build.cfg b/Platform/Intel/build.cfg index
> b6d32ada49..75cb446aa5 100644
> --- a/Platform/Intel/build.cfg
> +++ b/Platform/Intel/build.cfg
> @@ -11,6 +11,7 @@ WORKSPACE =
>  WORKSPACE_FSP_BIN = FSP
>  EDK_TOOLS_BIN = edk2-BaseTools-win32
>  EDK_BASETOOLS = BaseTools
> +WORKSPACE_DRIVERS = edk2-platforms/Drivers
>  WORKSPACE_PLATFORM = edk2-platforms/Platform/Intel
> WORKSPACE_SILICON = edk2-platforms/Silicon/Intel
> WORKSPACE_PLATFORM_BIN = @@ -52,6 +53,7 @@
> NUMBER_OF_PROCESSORS = 0  [PLATFORMS]  # board_name =
> path_to_board_build_config.cfg  BoardMtOlympus =
> PurleyOpenBoardPkg/BoardMtOlympus/build_config.cfg
> +BoardX58Ich10 = SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg
>  KabylakeRvp3 = KabylakeOpenBoardPkg/KabylakeRvp3/build_config.cfg
>  N1xxWU = ClevoOpenBoardPkg/N1xxWU/build_config.cfg
>  WhiskeylakeURvp =
> WhiskeylakeOpenBoardPkg/WhiskeylakeURvp/build_config.cfg
> diff --git a/Platform/Intel/build_bios.py b/Platform/Intel/build_bios.py index
> 9152670dcb..46285df19a 100644
> --- a/Platform/Intel/build_bios.py
> +++ b/Platform/Intel/build_bios.py
> @@ -104,6 +104,8 @@ def pre_build(build_config, build_type="DEBUG",
> silent=False, toolchain=None):
>                                                  config["WORKSPACE_PLATFORM"])
>      config["WORKSPACE_SILICON"] = os.path.join(config["WORKSPACE"],
>                                                 config["WORKSPACE_SILICON"])
> +    config["WORKSPACE_DRIVERS"] = os.path.join(config["WORKSPACE"],
> +
> + config["WORKSPACE_DRIVERS"])
>      config["WORKSPACE_PLATFORM_BIN"] = \
>          os.path.join(config["WORKSPACE"],
> config["WORKSPACE_PLATFORM_BIN"])
>      config["WORKSPACE_SILICON_BIN"] = \ @@ -115,6 +117,7 @@ def
> pre_build(build_config, build_type="DEBUG", silent=False, toolchain=None):
>      config["PACKAGES_PATH"] = config["WORKSPACE_PLATFORM"]
>      config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_SILICON"]
>      config["PACKAGES_PATH"] += os.pathsep +
> config["WORKSPACE_SILICON_BIN"]
> +    config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_DRIVERS"]
>      config["PACKAGES_PATH"] += os.pathsep + \
>          os.path.join(config["WORKSPACE"], "FSP")
>      config["PACKAGES_PATH"] += os.pathsep + \
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-09-07  1:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 2/7] SimicsIch10Pkg: Add Ich Pkg for SimicsIch10 David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 6/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
2019-09-07  1:03   ` [edk2-devel] " Kubacki, Michael A

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox