public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS
@ 2019-08-30 21:19 David Wei
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
                   ` (6 more replies)
  0 siblings, 7 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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 V3:
  Change package name to SimicsIch10BinPkg
  Merge V3 patch changes 8,9,10,11 to proper Package patches
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
  Platform/Intel:  Add build option for SIMICS QSP Platform
  SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip

 .../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] 22+ messages in thread

* [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:01   ` Nate DeSimone
  2019-09-04  6:39   ` [edk2-devel] " Kubacki, Michael A
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10 David Wei
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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 QSP 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..12e43e86d0
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the SkyLake 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..b38c3b1108
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
@@ -0,0 +1,14 @@
+## @file
+#  Component description file for the SkyLake 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] 22+ messages in thread

* [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:01   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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 QSP 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..143abda7c1
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
@@ -0,0 +1,12 @@
+## @file
+#  Component description file for the SkyLake 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..12e43e86d0
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the SkyLake 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..1b683ba97c
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
@@ -0,0 +1,13 @@
+## @file
+#  Component description file for the SkyLake 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] 22+ messages in thread

* [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10 David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:06   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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 QSP 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] 22+ messages in thread

* [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (2 preceding siblings ...)
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:08   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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] 22+ messages in thread

* [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (3 preceding siblings ...)
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:13   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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] 22+ messages in thread

* [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (4 preceding siblings ...)
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:54   ` Nate DeSimone
  2019-09-04  6:40   ` [edk2-devel] " Kubacki, Michael A
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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 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] 22+ messages in thread

* [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip
  2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
                   ` (5 preceding siblings ...)
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
@ 2019-08-30 21:19 ` David Wei
  2019-09-03  4:56   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  6 siblings, 2 replies; 22+ messages in thread
From: David Wei @ 2019-08-30 21:19 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 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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
@ 2019-09-03  4:01   ` Nate DeSimone
  2019-09-04  6:39   ` [edk2-devel] " Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:01 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58

Add CPU Pkg for SimicsX58. It is added for simics QSP 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/X58SmramSaveStateMa
+++ p.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..12e43e86d0
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the SkyLake 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..b38c3b1108
--- /dev/null
+++ b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
@@ -0,0 +1,14 @@
+## @file
+#  Component description file for the SkyLake 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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10 David Wei
@ 2019-09-03  4:01   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:01 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10

Add ICH Pkg for SimicsICH10. It is added for simics QSP 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..143abda7c1
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
@@ -0,0 +1,12 @@
+## @file
+#  Component description file for the SkyLake 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..12e43e86d0
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
@@ -0,0 +1,9 @@
+## @file
+#  Component description file for the SkyLake 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..1b683ba97c
--- /dev/null
+++ b/Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
@@ -0,0 +1,13 @@
+## @file
+#  Component description file for the SkyLake 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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
@ 2019-09-03  4:06   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:06 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules

Add modules Include, Library, SimicsDxe, SimicsPei, Policy, SmbiosPlatformDxe
and SecCore for Simics QSP 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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
@ 2019-09-03  4:08   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:08 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio

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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
@ 2019-09-03  4:13   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:13 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg

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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
@ 2019-09-03  4:54   ` Nate DeSimone
  2019-09-04  6:40   ` [edk2-devel] " Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:54 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform

Add build option in build script for SIMICS QSP 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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
@ 2019-09-03  4:56   ` Nate DeSimone
  2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Nate DeSimone @ 2019-09-03  4:56 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Kubacki, Michael A, Kinney, Michael D

Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>

-----Original Message-----
From: Wei, David Y 
Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip

Add BoardX58ICH10 modules for QSP 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] 22+ messages in thread

* Re: [edk2-devel] [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
  2019-09-03  4:01   ` Nate DeSimone
@ 2019-09-04  6:39   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:39 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

The following files still have "SkyLake" in the comment at the top of the file. This needs to be changed.
 * SktUefiBootInclude.fdf
 * SktPostMemoryInclude.fdf

Given this is the first commit for Simics QSP, I think it would be helpful to expand the QSP acronym (Quick Start Package) in the commit message.

With those changes:
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: Friday, August 30, 2019 2:19 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 v4 1/7] SimicsX58SktPkg: Add CPU
> Pkg for SimicsX58
> 
> Add CPU Pkg for SimicsX58. It is added for simics QSP 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/X58SmramSaveStateMa
> +++ p.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..12e43e86d0
> --- /dev/null
> +++ b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf
> @@ -0,0 +1,9 @@
> +## @file
> +#  Component description file for the SkyLake 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..b38c3b1108
> --- /dev/null
> +++ b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf
> @@ -0,0 +1,14 @@
> +## @file
> +#  Component description file for the SkyLake 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	[flat|nested] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10 David Wei
  2019-09-03  4:01   ` Nate DeSimone
@ 2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:40 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Desimone, Nathaniel L, Kinney, Michael D

The naming convention in the commit message is inconsistent with the actual package name (ICH vs Ich).  It would be helpful to expand the QSP acronym (Quick Start Package) in the commit message.

A few files still have "SkyLake" in the comment at the top of the file. This needs to be changed.
 * IchCommonLib.dsc
 * IchPostMemoryInclude.fdf
 * IchUefiBootInclude.fdf

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

> -----Original Message-----
> From: Wei, David Y
> Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for
> SimicsICH10
> 
> Add ICH Pkg for SimicsICH10. It is added for simics QSP 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/SpiFlashCommon
> SmmLib.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/SmmSpiFlashCom
> monLib.inf
>  create mode 100644
> Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchSpi
> CommonLib.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/SpiFlashComm
> on.c
> b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashComm
> on.c
> new file mode 100644
> index 0000000000..9e3461cbd6
> --- /dev/null
> +++
> b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashComm
> on.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/SpiFlashComm
> onSmmLib.c
> b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashComm
> onSmmLib.c
> new file mode 100644
> index 0000000000..984b7733c6
> --- /dev/null
> +++
> b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SpiFlashComm
> onSmmLib.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/SpiComm
> on.c
> b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiComm
> on.c
> new file mode 100644
> index 0000000000..bd08b2453b
> --- /dev/null
> +++
> b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/SpiComm
> on.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|0x100
> 00001
> +  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..143abda7c1
> --- /dev/null
> +++ b/Silicon/Intel/SimicsIch10Pkg/IchCommonLib.dsc
> @@ -0,0 +1,12 @@
> +## @file
> +#  Component description file for the SkyLake 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/BasePch
> SpiCommonLib.inf
> diff --git a/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
> b/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
> new file mode 100644
> index 0000000000..12e43e86d0
> --- /dev/null
> +++ b/Silicon/Intel/SimicsIch10Pkg/IchPostMemoryInclude.fdf
> @@ -0,0 +1,9 @@
> +## @file
> +#  Component description file for the SkyLake 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..1b683ba97c
> --- /dev/null
> +++ b/Silicon/Intel/SimicsIch10Pkg/IchUefiBootInclude.fdf
> @@ -0,0 +1,13 @@
> +## @file
> +#  Component description file for the SkyLake 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/SmmSpiFlashCo
> mmonLib.inf
> b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCo
> mmonLib.inf
> new file mode 100644
> index 0000000000..23b334a080
> --- /dev/null
> +++
> b/Silicon/Intel/SimicsIch10Pkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCo
> mmonLib.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/BasePchS
> piCommonLib.inf
> b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchS
> piCommonLib.inf
> new file mode 100644
> index 0000000000..df1da274a6
> --- /dev/null
> +++
> b/Silicon/Intel/SimicsIch10Pkg/LibraryPrivate/BasePchSpiCommonLib/BasePchS
> piCommonLib.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	[flat|nested] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
  2019-09-03  4:06   ` Nate DeSimone
@ 2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:40 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  Cc: Wu, Hao A, Gao, Liming, Sinha, Ankit, Agyeman, Prince,
	Desimone, Nathaniel L, Kinney, Michael D

It would be helpful to expand the QSP acronym (Quick Start Package) in the commit message before being committed.

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

> -----Original Message-----
> From: Wei, David Y
> Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add
> SimicsOpenBoardPkg and its modules
> 
> Add modules Include, Library, SimicsDxe, SimicsPei, Policy, SmbiosPlatformDxe
> and SecCore for Simics QSP 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/BdsPlatf
> orm.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/Platform
> Data.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVaria
> blesLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPo
> licyInitLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Silic
> onPolicyUpdateLib.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.n
> asm
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.n
> asm
>  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/BdsPlatf
> orm.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/Platform
> BootManagerLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVaria
> blesLib.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVaria
> blesLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPo
> licyInitLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Silic
> onPolicyUpdateLib.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.in
> f
> 
> 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/PciHostBridgeL
> ib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeL
> ib.c
> new file mode 100644
> index 0000000000..3b71c8ae97
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeL
> ib.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/BdsPla
> tform.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPla
> tform.c
> new file mode 100644
> index 0000000000..117c72b35f
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPla
> tform.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/Platfo
> rmData.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/Platfo
> rmData.c
> new file mode 100644
> index 0000000000..768843a8bf
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/Platfo
> rmData.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/SerializeVar
> iablesLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVar
> iablesLib.c
> new file mode 100644
> index 0000000000..be619c838a
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVar
> iablesLib.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/Silicon
> PolicyInitLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.c
> new file mode 100644
> index 0000000000..383501898d
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.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/Sili
> conPolicyUpdateLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sili
> conPolicyUpdateLib.c
> new file mode 100644
> index 0000000000..3b207a4e78
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sili
> conPolicyUpdateLib.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.in
> f
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.in
> f
> new file mode 100644
> index 0000000000..cdefeebbdd
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.in
> f
> @@ -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/JumpToKerne
> l.nasm
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKerne
> l.nasm
> new file mode 100644
> index 0000000000..c6f1c31a59
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKerne
> l.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/PciHostBridgeL
> ib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeL
> ib.inf
> new file mode 100644
> index 0000000000..e1920bd2ff
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeL
> ib.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.in
> f
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.in
> f
> new file mode 100644
> index 0000000000..bc85420f97
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.in
> f
> @@ -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/BdsPla
> tform.h
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPla
> tform.h
> new file mode 100644
> index 0000000000..01ba20d2da
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPla
> tform.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/Platfo
> rmBootManagerLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/Platfo
> rmBootManagerLib.inf
> new file mode 100644
> index 0000000000..cdb6e242e8
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/Platfo
> rmBootManagerLib.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/SerializeVar
> iablesLib.h
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVar
> iablesLib.h
> new file mode 100644
> index 0000000000..9b4c2a629a
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVar
> iablesLib.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/SerializeVar
> iablesLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVar
> iablesLib.inf
> new file mode 100644
> index 0000000000..08c561f586
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVar
> iablesLib.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/Silicon
> PolicyInitLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.inf
> new file mode 100644
> index 0000000000..6be3b301ad
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.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/Sili
> conPolicyUpdateLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sili
> conPolicyUpdateLib.inf
> new file mode 100644
> index 0000000000..4fde3c75a6
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sili
> conPolicyUpdateLib.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	[flat|nested] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
  2019-09-03  4:08   ` Nate DeSimone
@ 2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:40 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  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: Wei, David Y
> Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver
> for Legacy Sio
> 
> 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)SioComponentNameGet
> ControllerName,
> +  "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	[flat|nested] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
  2019-09-03  4:13   ` Nate DeSimone
@ 2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:40 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  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: Wei, David Y
> Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and
> dec file under SimicsOpenBoardPkg
> 
> 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/AcpiPla
> tform.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/F
> acs.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/F
> adt.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/H
> pet.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/AcpiPla
> tform.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPla
> tform.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/Acpi
> Platform.c
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Acpi
> Platform.c
> new file mode 100644
> index 0000000000..1edac89240
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Acpi
> Platform.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_HEAD
> ER                        *McfgTable;
> +
> EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADD
> RESS_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_BAS
> E_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_BAS
> E_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISI
> ON,
> +    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_HEAD
> ER) +
> +                                      sizeof
> (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_AD
> DRESS_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_BAS
> E_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/Wsm
> t/Wsmt.c
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsm
> t/Wsmt.c
> new file mode 100644
> index 0000000000..625b7560bb
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsm
> t/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/DriverSupportedEfiVersi
> on.c
> b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersi
> on.c
> new file mode 100644
> index 0000000000..a743056382
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersi
> on.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/Acpi
> Platform.h
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Acpi
> Platform.h
> new file mode 100644
> index 0000000000..e98aac4676
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Acpi
> Platform.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/Acpi
> Platform.inf
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Acpi
> Platform.inf
> new file mode 100644
> index 0000000000..7dfd0832a3
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Acpi
> Platform.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..86d7030833a096f545393735
> d931d9f4f2fbf8c0
> 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|2h
> 0&
> 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!ohM
> F
> 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%B
> x4@
> 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}#_#BI
> 4uv
> 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{s5
> Us
> 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*AdsRkDKJv
> p4
> 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*7CT
> H
> 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|kF
> BR1
> 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^Lt
> d
> 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?jvJ
> IX
> ztDWeWyA9Kh)8dy7H9N2OH&>TO#QwaF9m~tVSBI({H5)jxx;~mktz$=i_XLhaJHk9
> y
> 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#>@hAg
> 0B
> 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+iWL
> O
> 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}cT
> AJ`
> 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*HPy8DTq3t
> 7-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>_pcC
> U
> 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~0iLGTxcoRPfI
> 4bJ
> 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;Yf7uPTcSGHdc
> x
> 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|19DjGz
> y
> z))6N;{kM!UU==K3Tlz{PU`6!m8$GmgqIm2zRsI`Ldqs21z{<!0FBI80CauTnFi+GX
> zUfR)QxRlWp+$$L{BnCz%WwZ1ZHEqt)RW~<GXUs!fox7`gyb09i@yd>xv4$el;opq
> N
> 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;F
> g
> 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@pcEza
> bu
> 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%(XB
> z`
> z06k6~NFgA@NI7a@!*eN(2hj*}428tz3H6ZtZKRX%&pRY)!5DxM0m?%Wy#bDlHq
> q`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*2o
> Vz
> 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~a
> 3L
> 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{EARWbyDMHh
> U<^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>N
> Y
> 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*+f0
> D
> 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?NDGSQ
> Xu
> 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+3
> yn
> 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(?uRGaG
> M
> 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@W
> x1<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@_W
> U=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$qYGd
> fag<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;>nibBwVGn
> p
> 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%X
> Atbzu
> 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=YChMvhdi4HZ13pyBl
> o7
> 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+)@Xj
> 9*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~|*Nyv
> 3
> 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*#0Bd
> ov
> 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^~p8uUy
> I
> 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|UI
> NT32|0x8
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize|0x0|UIN
> T32|0x9
> +  gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareFdSize|0x0|UINT32|0xa
> +  gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareBlockSize|0|UINT32|0xb
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase|0x0|UIN
> T32|0xc
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwSpareBase|0x0|UI
> NT32|0xd
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase|0x0|
> UINT32|0xe
> +  gBoardModuleTokenSpaceGuid.PcdSimicsFdBaseAddress|0x0|UINT32|0xf
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase|0x0|UINT32|0x1
> 1
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesSize|0x0|UINT32|0x12
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|0x0|UINT32|0x
> 13
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize|0x0|UINT32|0x1
> 4
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase|0x0|UINT32|0x
> 18
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize|0x0|UINT32|0x1
> 9
> +
> gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32
> |0x1a
> +
> gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd|0x0|UINT
> 32|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|0x
> 1b
> +
> +  ## 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|0
> x00000001
> +
> +  ## 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|UINT
> 16|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|0x0
> 0000003
> +
> +  ## 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|0x0
> 0000004
> +
> +  ## 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|BOOLEA
> N|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|0x
> 00000007
> +
> +  ## 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|0x
> 00000008
> +
> +[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|0x00
> 010040
> +
> +  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	[flat|nested] 22+ messages in thread

* Re: [edk2-devel] [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
  2019-09-03  4:54   ` Nate DeSimone
@ 2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:40 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

This patch adds the following in Platform/Intel/build.cfg:
  BoardX58Ich10 = SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg

But the file SimicsOpenBoardPkg/BoardX58Ich10/build_config.cfg is not added until patch 7/7. This patch seems more appropriate as the final patch of the series.

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of David Wei
> Sent: Friday, August 30, 2019 2:19 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 v4 6/7] Platform/Intel: Add build
> option for SIMICS QSP Platform
> 
> Add build option in build script for SIMICS QSP 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] 22+ messages in thread

* Re: [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip
  2019-08-30 21:19 ` [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
  2019-09-03  4:56   ` Nate DeSimone
@ 2019-09-04  6:40   ` Kubacki, Michael A
  1 sibling, 0 replies; 22+ messages in thread
From: Kubacki, Michael A @ 2019-09-04  6:40 UTC (permalink / raw)
  To: Wei, David Y, devel@edk2.groups.io
  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: Wei, David Y
> Sent: Friday, August 30, 2019 2:19 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-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10:
> Add board modules for QSP Build tip
> 
> Add BoardX58ICH10 modules for QSP 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/PeiBo
> ardInitPostMemLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBo
> ardInitPreMemLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX5
> 8Ich10Detect.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX5
> 8Ich10InitPostMemLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX5
> 8Ich10InitPreMemLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/DecomprScratchEnd.fdf.in
> c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBo
> ardInitPostMemLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiBo
> ardInitPreMemLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/PeiX5
> 8Ich10InitLib.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/Pei
> BoardInitPostMemLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPostMemLib.c
> new file mode 100644
> index 0000000000..5ece8c6e34
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPostMemLib.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/Pei
> BoardInitPreMemLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPreMemLib.c
> new file mode 100644
> index 0000000000..d16e649d34
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPreMemLib.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/Pei
> X58Ich10Detect.c
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10Detect.c
> new file mode 100644
> index 0000000000..03488ef1f4
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10Detect.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/Pei
> X58Ich10InitPostMemLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10InitPostMemLib.c
> new file mode 100644
> index 0000000000..bd6924e269
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10InitPostMemLib.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/Pei
> X58Ich10InitPreMemLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10InitPreMemLib.c
> new file mode 100644
> index 0000000000..c3a31ed426
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10InitPreMemLib.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/Pei
> BoardInitPostMemLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPostMemLib.inf
> new file mode 100644
> index 0000000000..a035eb0e50
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPostMemLib.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/Pei
> BoardInitPreMemLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPreMemLib.inf
> new file mode 100644
> index 0000000000..08a6eb159a
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> BoardInitPreMemLib.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/Pei
> X58Ich10InitLib.h
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10InitLib.h
> new file mode 100644
> index 0000000000..93544a838b
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/Library/BoardInitLib/Pei
> X58Ich10InitLib.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/SerializeVaria
> blesLib.inf
> +  DxeLoadLinuxLib|$(BOARD_PKG)/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
> +
> CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/
> CpuExceptionHandlerLibNull.inf
> +
> +
> TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLibNull/TestPoi
> ntCheckLibNull.inf
> +
> BoardInitLib|MinPlatformPkg/PlatformInit/Library/BoardInitLibNull/BoardInitLib
> Null.inf
> +
> SiliconPolicyInitLib|$(BOARD_PKG)/Policy/Library/SiliconPolicyInitLib/SiliconPoli
> cyInitLib.inf
> +
> SiliconPolicyUpdateLib|$(BOARD_PKG)/Policy/Library/SiliconPolicyUpdateLib/Sil
> iconPolicyUpdateLib.inf
> +
> PciSegmentInfoLib|MinPlatformPkg/Pci/Library/PciSegmentInfoLibSimple/PciSe
> gmentInfoLibSimple.inf
> +
> +  !include MinPlatformPkg/Include/Dsc/CorePeiLib.dsc
> +
> +
> S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScript
> Lib.inf
> +
> AslUpdateLib|MinPlatformPkg/Acpi/Library/DxeAslUpdateLib/DxeAslUpdateLib.i
> nf
> +  LogoLib|$(BOARD_PKG)/Library/DxeLogoLib/DxeLogoLib.inf
> +[LibraryClasses.common.SEC]
> +
> ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExt
> ractGuidedSectionLib.inf
> +
> +[LibraryClasses.common.PEI_CORE]
> +
> +[LibraryClasses.common.PEIM]
> +
> PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiReso
> urcePublicationLib.inf
> +  MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
> +
> +[LibraryClasses.IA32]
> +!if $(TARGET) == DEBUG
> +
> TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLib/PeiTestPoin
> tCheckLib.inf
> +!endif
> +  TestPointLib|MinPlatformPkg/Test/Library/TestPointLib/PeiTestPointLib.inf
> +
> +  !include MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc
> +
> +[LibraryClasses.common.DXE_DRIVER]
> +
> PlatformBootManagerLib|$(BOARD_PKG)/Library/PlatformBootManagerLib/Pla
> tformBootManagerLib.inf
> +
> +[LibraryClasses.common.DXE_SMM_DRIVER]
> +
> SpiFlashCommonLib|$(PCH_PKG)/Library/SmmSpiFlashCommonLib/SmmSpiFlash
> CommonLib.inf
> +
> +  !include $(BOARD_PKG)/$(BOARD_NAME)/OpenBoardPkgPcd.dsc
> +
> +[Components.IA32]
> +  $(BOARD_PKG)/SecCore/SecMain.inf {
> +    <LibraryClasses>
> +
> NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecom
> pressLib.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/PeiBoardIni
> tPreMemLib.inf
> +  }
> +  MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPostMem.inf {
> +    <LibraryClasses>
> +
> BoardInitLib|$(BOARD_PKG)/$(BOARD_NAME)/Library/BoardInitLib/PeiBoardIni
> tPostMemLib.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/UefiShellLevel2Commands
> Lib.inf
> +
> NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1Commands
> Lib.inf
> +
> NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Commands
> Lib.inf
> +
> NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1Comman
> dsLib.inf
> +
> NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1Comman
> dsLib.inf
> +
> NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1Comma
> ndsLib.inf
> +
> NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1Co
> mmandsLib.inf
> +
> NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2Co
> mmandsLib.inf
> +
> ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLi
> b.inf
> +
> HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.i
> nf
> +
> BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCo
> mmandLib.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|gEfi
> MdeModulePkgTokenSpaceGuid.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|gEfiMd
> eModulePkgTokenSpaceGuid.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|gBoardModuleT
> okenSpaceGuid.PcdSimicsSecPageTablesSize
> +
> +0x006000|0x001000
> +gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase|gBoardModule
> TokenSpaceGuid.PcdSimicsLockBoxStorageSize
> +
> +0x007000|0x001000
> +gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gBoardM
> oduleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
> +
> +0x010000|0x008000
> +gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|gBoardModule
> TokenSpaceGuid.PcdSimicsSecPeiTempRamSize
> +
> +0x020000|0x0E0000
> +gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase|gBoardModuleToken
> SpaceGuid.PcdSimicsPeiMemFvSize
> +FV = FvPreMemory
> +
> +0x100000|0xA00000
> +gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase|gBoardModuleToke
> nSpaceGuid.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/OpenBoardPkgBuildOpti
> on.dsc
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOpti
> on.dsc
> new file mode 100644
> index 0000000000..25998b83e7
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgBuildOpti
> on.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.ds
> c
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.ds
> c
> new file mode 100644
> index 0000000000..75de60e5bc
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/BoardX58Ich10/OpenBoardPkgConfig.ds
> c
> @@ -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.PcdResetOnMemoryTypeInformationChang
> e|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|0x170000
> 0
> +
> +  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|0x2009101
> 3
> +
> +  ## 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.PcdResetOnMemoryTypeInformationChang
> e|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"|gEfiGlobalV
> ariableGuid|0x0|50 # Variable: L"Timeout"
> +
> gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSuppor
> t"|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|0x2046573030
> 363253
> +
> +[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|"QS
> P UEFI BIOS"
> +
> gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType2StringProductName|"QS
> P 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|gEfiMde
> ModulePkgTokenSpaceGuid.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	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2019-09-04  6:40 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-08-30 21:19 [edk2-platforms PATCH v4 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
2019-08-30 21:19 ` [edk2-platforms PATCH v4 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
2019-09-03  4:01   ` Nate DeSimone
2019-09-04  6:39   ` [edk2-devel] " Kubacki, Michael A
2019-08-30 21:19 ` [edk2-platforms PATCH v4 2/7] SimicsIch10Pkg: Add ICH Pkg for SimicsICH10 David Wei
2019-09-03  4:01   ` Nate DeSimone
2019-09-04  6:40   ` Kubacki, Michael A
2019-08-30 21:19 ` [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules David Wei
2019-09-03  4:06   ` Nate DeSimone
2019-09-04  6:40   ` Kubacki, Michael A
2019-08-30 21:19 ` [edk2-platforms PATCH v4 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
2019-09-03  4:08   ` Nate DeSimone
2019-09-04  6:40   ` Kubacki, Michael A
2019-08-30 21:19 ` [edk2-platforms PATCH v4 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg David Wei
2019-09-03  4:13   ` Nate DeSimone
2019-09-04  6:40   ` Kubacki, Michael A
2019-08-30 21:19 ` [edk2-platforms PATCH v4 6/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
2019-09-03  4:54   ` Nate DeSimone
2019-09-04  6:40   ` [edk2-devel] " Kubacki, Michael A
2019-08-30 21:19 ` [edk2-platforms PATCH v4 7/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
2019-09-03  4:56   ` Nate DeSimone
2019-09-04  6:40   ` 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