[edk2-devel] [edk2-platform patch 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules

Kubacki, Michael A michael.a.kubacki at intel.com
Tue Aug 20 01:04:18 UTC 2019


Feedback I could not find already covered elsewhere:

1. Dsdt.asl: Change "OVMF" in the following line to something else unique to this implementation:
     "DefinitionBlock ("Dsdt.aml", "DSDT", 1, "INTEL ", "OVMF    ", 4) {"
2. BasePchSpiCommonLib.inf: This silicon package should not have a dependency on SimicsOpenBoardPkg.dec.
3. Platform.h: This header guard definition is unusual in style and convention, please correct: "_Platform_h_INCLUDED_"
4. Platform.h: Please update usage of "OVMF" in various signatures throughout the file to something package unique.
5. SimicsX58PlatformConfig.h: Why is this file not in SimicsX58SktPkg?
6. SimicsX58PlatformConfig.h: Change "OVMF" in copyright header to "Simics X58"
7. SimicsPlatforms.h: Change "OVMF" in copyright header to "Simics"
8. SimicsPlatforms.h - Line 16: Follow up on TODO 
9. X58Ich10.h: Why is this file in the Simics board package? It should be in the silicon package.
10. LoadLinuxLib.inf: This package should avoid a depdency on OvmfPkg.dec
11. LoadLinuxLib.inf: Library name does not following naming convention. I.e. should be BaseLoadLinuxLib.inf.
12. LoadLinuxLib.inf: This is not truly a BASE library. For example, gBS (boot services) are unavailable in Runtime DXE.
13. Platform.c: Change "OVMF" reference in copyright header.
14. Platform.h: Change "OVMF" reference in copyright header.
15. Cmos.c: It seems CmosAccessLib in BoardModulePkg could be used here to avoid duplication.
16. Fv.c: In MinPlatform, a more intuitive place to manage FVs is in a board-specific instance of PeiReportFvLib
17. General comment: The modules "PlatformPei" and "PlatformDxe" should be avoided in a MinPlatform.
        MinPlatformPkg is considered the "platform" and SimicsOpenBoardPkg is considered the "board", therefore this
        code should likely be in a board library linked against a PlatformInit module in MinPlatformPkg. Such as BoardInitLib
        which is very empty at the moment. At a minimum, if kept as a module for dispatch, the name should not lead to confusion
        with platform modules in MinPlatformPkg.
18. PlatformPei.inf: This package should avoid a depdency on OvmfPkg.dec
19. X58SmamSaveStateMap.h: If X58-specific, it should go to SimicsX58SktPkg.
20. SerializeVariablesLib.inf: This package should avoid a depdency on OvmfPkg.dec
21. SimicsOpenBoardPkg.dec: Pcds in the gSimicsX58PkgTokenSpaceGuid token space should be declared in a DEC file
       in the SimicsX58SktPkg. SimicsOpenBoardPkg should not be hardcoded to this particular silicon design.
22. SimicsOpenBoardPkg.dec: "X58" should be removed from the copyright header as the DEC is at the package-level
       and not the board level.
23. SimicsOpenBoardPkg.dec: The PACKAGE_NAME should not be " SimicsX58Pkg" as the DEC is at package-level and
       not Simics board-specific.

> -----Original Message-----
> From: Wei, David Y
> Sent: Friday, August 9, 2019 3:47 PM
> To: devel at edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu at intel.com>; Gao, Liming <liming.gao at intel.com>;
> Sinha, Ankit <ankit.sinha at intel.com>; Agyeman, Prince
> <prince.agyeman at intel.com>; Kubacki, Michael A
> <michael.a.kubacki at intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone at intel.com>; Kinney, Michael D
> <michael.d.kinney at intel.com>
> Subject: [edk2-platform patch 3/7] SimicsOpenBoardPkg: Add
> SimicsOpenBoardPkg and its modules
> 
> Add modules AcpiTables, Include, Library, PlatformDxe, PlatformPei, Policy,
> SmbiosPlatformDxe
> for Simics QSP platform support
> 
> Cc: Hao Wu <hao.a.wu at intel.com>
> Cc: Liming Gao <liming.gao at intel.com>
> Cc: Ankit Sinha <ankit.sinha at intel.com>
> Cc: Agyeman Prince <prince.agyeman at intel.com>
> Cc: Kubacki Michael A <michael.a.kubacki at intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> 
> Signed-off-by: David Wei <david.y.wei at intel.com>
> ---
>  .../Library/LoadLinuxLib/Linux.c                   | 662 ++++++++++++++++
>  .../Library/LoadLinuxLib/LinuxGdt.c                | 175 +++++
>  .../Library/NvVarsFileLib/FsAccess.c               | 507 ++++++++++++
>  .../Library/NvVarsFileLib/NvVarsFileLib.c          |  77 ++
>  .../SerializeVariablesLib/SerializeVariablesLib.c  | 869
> +++++++++++++++++++++
>  .../SimicsOpenBoardPkg/PlatformDxe/Platform.c      | 865
> ++++++++++++++++++++
>  .../PlatformDxe/PlatformConfig.c                   | 123 +++
>  .../Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.c    |  57 ++
>  .../PlatformPei/FeatureControl.c                   | 114 +++
>  Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Fv.c | 100 +++
>  .../SimicsOpenBoardPkg/PlatformPei/MemDetect.c     | 568 ++++++++++++++
>  .../SimicsOpenBoardPkg/PlatformPei/Platform.c      | 631 +++++++++++++++
>  .../SiliconPolicyInitLib/SiliconPolicyInitLib.c    | 108 +++
>  .../SiliconPolicyUpdateLib.c                       |  70 ++
>  .../SmbiosPlatformDxe/SmbiosPlatformDxe.c          | 148 ++++
>  .../SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf   |  31 +
>  .../Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl   | 821
> +++++++++++++++++++
>  .../Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h |  75 ++
>  .../Include/Guid/SimicsX58PlatformConfig.h         |  17 +
>  .../Include/IndustryStandard/X58Ich10.h            | 106 +++
>  .../SimicsOpenBoardPkg/Include/Protocol/IsaAcpi.h  | 298 +++++++
>  .../SimicsOpenBoardPkg/Include/Protocol/IsaIo.h    | 356 +++++++++
>  .../Include/Protocol/Legacy8259.h                  | 291 +++++++
>  .../Include/Register/X58SmramSaveStateMap.h        | 178 +++++
>  .../SimicsOpenBoardPkg/Include/SimicsPlatforms.h   |  54 ++
>  .../Library/LoadLinuxLib/Ia32/JumpToKernel.nasm    |  41 +
>  .../Library/LoadLinuxLib/LoadLinuxLib.h            |  52 ++
>  .../Library/LoadLinuxLib/LoadLinuxLib.inf          |  42 +
>  .../Library/LoadLinuxLib/X64/JumpToKernel.nasm     |  85 ++
>  .../Library/NvVarsFileLib/NvVarsFileLib.h          |  55 ++
>  .../Library/NvVarsFileLib/NvVarsFileLib.inf        |  53 ++
>  .../SerializeVariablesLib/SerializeVariablesLib.h  |  33 +
>  .../SerializeVariablesLib.inf                      |  36 +
>  .../SimicsOpenBoardPkg/PlatformDxe/Platform.h      |  37 +
>  .../SimicsOpenBoardPkg/PlatformDxe/Platform.inf    |  65 ++
>  .../SimicsOpenBoardPkg/PlatformDxe/Platform.uni    |  31 +
>  .../PlatformDxe/PlatformConfig.h                   |  51 ++
>  .../PlatformDxe/PlatformForms.vfr                  |  67 ++
>  .../Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.h    |  50 ++
>  .../SimicsOpenBoardPkg/PlatformPei/Platform.h      |  93 +++
>  .../SimicsOpenBoardPkg/PlatformPei/PlatformPei.inf | 109 +++
>  .../SiliconPolicyInitLib/SiliconPolicyInitLib.inf  |  38 +
>  .../SiliconPolicyUpdateLib.inf                     |  35 +
>  .../SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec      | 168 ++++
>  .../SmbiosPlatformDxe/SmbiosPlatformDxe.h          |  38 +
>  .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf        |  51 ++
>  46 files changed, 8531 insertions(+)
>  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/SerializeVariablesLib/SerializeVaria
> blesLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformConfig.c
>  create mode 100644 Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformPei/FeatureControl.c
>  create mode 100644 Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Fv.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformPei/MemDetect.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Platform.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconP
> olicyInitLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Silic
> onPolicyUpdateLib.c
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.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/Platform.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsX58PlatformConfig.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/X58Ich10.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaAcpi.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaIo.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/Legacy8259.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/Register/X58SmramSaveStateMap
> .h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
>  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/LoadLinuxLib.inf
>  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/SerializeVariablesLib/SerializeVaria
> blesLib.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVaria
> blesLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.uni
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformConfig.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformForms.vfr
>  create mode 100644 Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Platform.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/PlatformPei/PlatformPei.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconP
> olicyInitLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Silic
> onPolicyUpdateLib.inf
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
>  create mode 100644
> Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.i
> nf
> 
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
> new file mode 100644
> index 0000000000..43a2dee9f6
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
> @@ -0,0 +1,662 @@
> +/** @file
> +  Copyright (c) 2011 - 2014 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..624fbc37cb
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
> @@ -0,0 +1,175 @@
> +/** @file
> +  Initialize GDT for Linux.
> +
> +  Copyright (c) 2006 - 2012 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..6ba8784cf3
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
> @@ -0,0 +1,507 @@
> +/** @file
> +  File System Access for NvVarsFileLib
> +
> +  Copyright (c) 2004 - 2014 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..f60fbc6112
> --- /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) 2009 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/SerializeVariablesLib/SerializeVa
> riablesLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVa
> riablesLib.c
> new file mode 100644
> index 0000000000..c32a978550
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVa
> riablesLib.c
> @@ -0,0 +1,869 @@
> +/** @file
> +  Serialize Variables Library implementation
> +
> +  Copyright (c) 2004 - 2011 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/PlatformDxe/Platform.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.c
> new file mode 100644
> index 0000000000..7bede1496d
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.c
> @@ -0,0 +1,865 @@
> +/** @file
> +  This driver effectuates OVMF's platform configuration settings and exposes
> +  them via HII.
> +
> +  Copyright (C) 2014, Red Hat, Inc.
> +  Copyright (c) 2009 - 2014, 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/SimicsX58PlatformConfig.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 PlatformDxeStrings[];
> +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,
> &gSimicsX58PlatformConfigGuid,
> +               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
> +                         PlatformDxeStrings, // 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/PlatformDxe/PlatformConfig.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformConfig.c
> new file mode 100644
> index 0000000000..b3b2b34064
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformConfig.c
> @@ -0,0 +1,123 @@
> +/** @file
> +  Utility functions for serializing (persistently storing) and deserializing
> +  OVMF's platform configuration.
> +
> +  Copyright (C) 2014, Red Hat, Inc.
> +
> +  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/SimicsX58PlatformConfig.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, &gSimicsX58PlatformConfigGuid,
> +                  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, &gSimicsX58PlatformConfigGuid,
> &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/PlatformPei/Cmos.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.c
> new file mode 100644
> index 0000000000..fa2c22116c
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.c
> @@ -0,0 +1,57 @@
> +/** @file
> +  PC/AT CMOS access routines
> +
> +  Copyright (c) 2006 - 2009 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/PlatformPei/FeatureControl.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/FeatureControl.c
> new file mode 100644
> index 0000000000..692405e417
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/FeatureControl.c
> @@ -0,0 +1,114 @@
> +/** @file
> +  Install a callback when necessary for setting the Feature Control MSR on all
> +  processors.
> +
> +  Copyright (C) 2016, Red Hat, Inc.
> +
> +  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/PlatformPei/Fv.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Fv.c
> new file mode 100644
> index 0000000000..818d135c95
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Fv.c
> @@ -0,0 +1,100 @@
> +/** @file
> +  Build FV related hobs for platform.
> +
> +  Copyright (c) 2006 - 2013 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PiPei.h"
> +#include "Platform.h"
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/PcdLib.h>
> +
> +
> +/**
> +  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/PlatformPei/MemDetect.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/MemDetect.c
> new file mode 100644
> index 0000000000..4c527baef2
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/MemDetect.c
> @@ -0,0 +1,568 @@
> +/** @file
> +  Memory Detection for Virtual Machines.
> +
> +  Copyright (c) 2006 - 2016 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/PlatformPei/Platform.c
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Platform.c
> new file mode 100644
> index 0000000000..e64bdc7c56
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Platform.c
> @@ -0,0 +1,631 @@
> +/** @file
> +  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2011, Andrei Warkentin <andreiw at 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 ();
> +    }
> +    PeiFvInitialization ();
> +    MemMapInitialization ();
> +  }
> +
> +  MiscInitialization ();
> +  InstallFeatureControlCallback ();
> +
> +  return EFI_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..01a9ed40d5
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.c
> @@ -0,0 +1,108 @@
> +/** @file
> +  Copyright (c) 2018 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/Sil
> iconPolicyUpdateLib.c
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sil
> iconPolicyUpdateLib.c
> new file mode 100644
> index 0000000000..6d9da67975
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sil
> iconPolicyUpdateLib.c
> @@ -0,0 +1,70 @@
> +/** @file
> +  Copyright (c) 2018 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/SmbiosPlatformDxe/SmbiosPlatformDxe
> .c
> b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe
> .c
> new file mode 100644
> index 0000000000..82a2d60959
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe
> .c
> @@ -0,0 +1,148 @@
> +/** @file
> +  This driver installs SMBIOS information for OVMF
> +
> +  Copyright (c) 2011, Bei Guan <gbtju85 at gmail.com>
> +  Copyright (c) 2011 - 2015, 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.
> +
> + at param  Index  The CMOS location to read.
> +
> + at 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 OVMF
> +
> +  @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/AcpiTables/AcpiTables.inf
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
> new file mode 100644
> index 0000000000..839626eb86
> --- /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 - 2018 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..76a8fbc081
> --- /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) 2008 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +DefinitionBlock ("Dsdt.aml", "DSDT", 1, "INTEL ", "OVMF    ", 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/Platform.h
> b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
> new file mode 100644
> index 0000000000..6395ec11e2
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
> @@ -0,0 +1,75 @@
> +/** @file
> +  Platform specific defines for constructing ACPI tables
> +
> +  Copyright (c) 2013 - 2008 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _Platform_h_INCLUDED_
> +#define _Platform_h_INCLUDED_
> +
> +#include <PiDxe.h>
> +#include <IndustryStandard/Acpi.h>
> +
> +//
> +// ACPI table information used to initialize tables.
> +//
> +#define EFI_ACPI_OEM_ID           'O','V','M','F',' ',' '   // OEMID 6 bytes long
> +#define EFI_ACPI_OEM_TABLE_ID
> SIGNATURE_64('O','V','M','F','E','D','K','2') // OEM table id 8 bytes long
> +#define EFI_ACPI_OEM_REVISION     0x02000820
> +#define EFI_ACPI_CREATOR_ID       SIGNATURE_32('O','V','M','F')
> +#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/Include/Guid/SimicsX58PlatformConfig.
> h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsX58PlatformConfig.
> h
> new file mode 100644
> index 0000000000..f65f61d74d
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsX58PlatformConfig.
> h
> @@ -0,0 +1,17 @@
> +/** @file
> +  GUID for UEFI variables that are specific to OVMF configuration.
> +
> +  Copyright (C) 2014, Red Hat, Inc.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef __SIMICSX58_PLATFORM_CONFIG_H__
> +#define __SIMICSX58_PLATFORM_CONFIG_H__
> +
> +#define SIMICSX58_PLATFORM_CONFIG_GUID \
> +{0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59,
> 0xa5}}
> +
> +extern EFI_GUID gSimicsX58PlatformConfigGuid;
> +
> +#endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/X58Ich10.h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/X58Ich10.h
> new file mode 100644
> index 0000000000..36c08176d1
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/X58Ich10.h
> @@ -0,0 +1,106 @@
> +/** @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 at cmu.edu>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef __X58_ICH10_H__
> +#define __X58_ICH10_H__
> +
> +#include <Library/PciLib.h>
> +
> +//
> +// 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/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaAcpi.h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaAcpi.h
> new file mode 100644
> index 0000000000..12aeb1227c
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaAcpi.h
> @@ -0,0 +1,298 @@
> +/** @file
> +  EFI ISA ACPI Protocol is used to enumerate and manage all the ISA controllers
> on
> +  the platform's ISA Bus.
> +
> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef __ISA_ACPI_H_
> +#define __ISA_ACPI_H_
> +
> +///
> +/// Global ID for the EFI ISA ACPI Protocol.
> +///
> +#define EFI_ISA_ACPI_PROTOCOL_GUID \
> +  { \
> +    0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33,
> 0x55 } \
> +  }
> +
> +///
> +/// Forward declaration fo the EFI ISA ACPI Protocol
> +///
> +typedef struct _EFI_ISA_ACPI_PROTOCOL EFI_ISA_ACPI_PROTOCOL;
> +
> +///
> +/// ISA ACPI Protocol interrupt resource attributes.
> +///
> +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE   0x01   ///<
> Edge triggered interrupt on a rising edge.
> +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE    0x02   ///<
> Edge triggered interrupt on a falling edge.
> +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE  0x04   ///<
> Level sensitive interrupt active high.
> +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE   0x08   ///<
> Level sensitive interrupt active low.
> +
> +///
> +/// ISA ACPI Protocol DMA resource attributes.
> +///
> +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_MASK                 0x03   ///< Bit mask
> of supported DMA speed attributes.
> +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_COMPATIBILITY        0x00   ///< ISA
> controller supports compatibility mode DMA transfers.
> +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_A                    0x01   ///< ISA
> controller supports type A DMA transfers.
> +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_B                    0x02   ///< ISA
> controller supports type B DMA transfers.
> +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_F                    0x03   ///< ISA
> controller supports type F DMA transfers.
> +#define EFI_ISA_ACPI_DMA_COUNT_BY_BYTE                   0x04   ///< ISA
> controller increments DMA address by bytes (8-bit).
> +#define EFI_ISA_ACPI_DMA_COUNT_BY_WORD                   0x08   ///< ISA
> controller increments DMA address by words (16-bit).
> +#define EFI_ISA_ACPI_DMA_BUS_MASTER                      0x10   ///< ISA
> controller is a DMA bus master.
> +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT             0x20   ///< ISA
> controller only supports 8-bit DMA transfers.
> +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT  0x40
> ///< ISA controller both 8-bit and 16-bit DMA transfers.
> +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_16_BIT            0x80   ///< ISA
> controller only supports 16-bit DMA transfers.
> +
> +///
> +/// ISA ACPI Protocol MMIO resource attributes
> +///
> +#define EFI_ISA_ACPI_MEMORY_WIDTH_MASK                   0x03   ///< Bit mask
> of supported ISA memory width attributes.
> +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT                  0x00   ///< ISA
> MMIO region only supports 8-bit access.
> +#define EFI_ISA_ACPI_MEMORY_WIDTH_16_BIT                 0x01   ///< ISA
> MMIO region only supports 16-bit access.
> +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT_AND_16_BIT       0x02   ///<
> ISA MMIO region supports both 8-bit and 16-bit access.
> +#define EFI_ISA_ACPI_MEMORY_WRITEABLE                    0x04   ///< ISA MMIO
> region supports write transactions.
> +#define EFI_ISA_ACPI_MEMORY_CACHEABLE                    0x08   ///< ISA MMIO
> region supports being cached.
> +#define EFI_ISA_ACPI_MEMORY_SHADOWABLE                   0x10   ///< ISA
> MMIO region may be shadowed.
> +#define EFI_ISA_ACPI_MEMORY_EXPANSION_ROM                0x20   ///< ISA
> MMIO region is an expansion ROM.
> +
> +///
> +/// ISA ACPI Protocol I/O resource attributes
> +///
> +#define EFI_ISA_ACPI_IO_DECODE_10_BITS                   0x01    ///< ISA
> controllers uses a 10-bit address decoder for I/O cycles.
> +#define EFI_ISA_ACPI_IO_DECODE_16_BITS                   0x02    ///< ISA
> controllers uses a 16-bit address decoder for I/O cycles.
> +
> +///
> +/// EFI ISA ACPI resource type
> +///
> +typedef enum {
> +  EfiIsaAcpiResourceEndOfList,    ///< Marks the end if a resource list.
> +  EfiIsaAcpiResourceIo,           ///< ISA I/O port resource range.
> +  EfiIsaAcpiResourceMemory,       ///< ISA MMIO resource range.
> +  EfiIsaAcpiResourceDma,          ///< ISA DMA resource.
> +  EfiIsaAcpiResourceInterrupt     ///< ISA interrupt resource.
> +} EFI_ISA_ACPI_RESOURCE_TYPE;
> +
> +///
> +/// EFI ISA ACPI generic resource structure
> +///
> +typedef struct {
> +  EFI_ISA_ACPI_RESOURCE_TYPE  Type;         ///< The type of resource (I/O,
> MMIO, DMA, Interrupt).
> +  UINT32                      Attribute;    ///< Bit mask of attributes associated with this
> resource.  See EFI_ISA_ACPI_xxx macros for valid combinations.
> +  UINT32                      StartRange;   ///< The start of the resource range.
> +  UINT32                      EndRange;     ///< The end of the resource range.
> +} EFI_ISA_ACPI_RESOURCE;
> +
> +///
> +/// EFI ISA ACPI resource device identifier
> +///
> +typedef struct {
> +  UINT32  HID;   ///< The ACPI Hardware Identifier value associated with an ISA
> controller.  Matchs ACPI DSDT contents.
> +  UINT32  UID;   ///< The ACPI Unique Identifier value associated with an ISA
> controller.  Matches ACPI DSDT contents.
> +} EFI_ISA_ACPI_DEVICE_ID;
> +
> +///
> +/// EFI ISA ACPI resource list
> +///
> +typedef struct {
> +  EFI_ISA_ACPI_DEVICE_ID  Device;          ///< The ACPI HID/UID associated with
> an ISA controller.
> +  EFI_ISA_ACPI_RESOURCE   *ResourceItem;   ///< A pointer to the list of
> resources associated with an ISA controller.
> +} EFI_ISA_ACPI_RESOURCE_LIST;
> +
> +/**
> +  Enumerates the ISA controllers on an ISA bus.
> +
> +  This service allows all the ISA controllers on an ISA bus to be enumerated.  If
> +  Device is a pointer to a NULL value, then the first ISA controller on the ISA
> +  bus is returned in Device and EFI_SUCCESS is returned.  If Device is a pointer
> +  to a value that was returned on a prior call to DeviceEnumerate(), then the
> next
> +  ISA controller on the ISA bus is returned in Device and EFI_SUCCESS is
> returned.
> +  If Device is a pointer to the last ISA controller on the ISA bus, then
> +  EFI_NOT_FOUND is returned.
> +
> +  @param[in]  This     The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[out] Device   The pointer to an ISA controller named by ACPI
> HID/UID.
> +
> +  @retval EFI_SUCCESS    The next ISA controller on the ISA bus was returned.
> +  @retval EFI_NOT_FOUND  No device found.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_DEVICE_ENUMERATE)(
> +  IN  EFI_ISA_ACPI_PROTOCOL   *This,
> +  OUT EFI_ISA_ACPI_DEVICE_ID  **Device
> +  );
> +
> +/**
> +  Sets the power state of an ISA controller.
> +
> +  This services sets the power state of the ISA controller specified by Device to
> +  the power state specified by OnOff.  TRUE denotes on, FALSE denotes off.
> +  If the power state is sucessfully set on the ISA Controller, then
> +  EFI_SUCCESS is returned.
> +
> +  @param[in] This     The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[in] Device   The pointer to an ISA controller named by ACPI HID/UID.
> +  @param[in] OnOff    TRUE denotes on, FALSE denotes off.
> +
> +  @retval EFI_SUCCESS   Successfully set the power state of the ISA controller.
> +  @retval Other         The ISA controller could not be placed in the requested
> power state.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_SET_DEVICE_POWER)(
> +  IN EFI_ISA_ACPI_PROTOCOL   *This,
> +  IN EFI_ISA_ACPI_DEVICE_ID  *Device,
> +  IN BOOLEAN                 OnOff
> +  );
> +
> +/**
> +  Retrieves the current set of resources associated with an ISA controller.
> +
> +  Retrieves the set of I/O, MMIO, DMA, and interrupt resources currently
> +  assigned to the ISA controller specified by Device.  These resources
> +  are returned in ResourceList.
> +
> +  @param[in]  This          The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[in]  Device        The pointer to an ISA controller named by ACPI
> HID/UID.
> +  @param[out] ResourceList  The pointer to the current resource list for Device.
> +
> +  @retval EFI_SUCCESS    Successfully retrieved the current resource list.
> +  @retval EFI_NOT_FOUND  The resource list could not be retrieved.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_GET_CUR_RESOURCE)(
> +  IN  EFI_ISA_ACPI_PROTOCOL       *This,
> +  IN  EFI_ISA_ACPI_DEVICE_ID      *Device,
> +  OUT EFI_ISA_ACPI_RESOURCE_LIST  **ResourceList
> +  );
> +
> +/**
> +  Retrieves the set of possible resources that may be assigned to an ISA
> controller
> +  with SetResource().
> +
> +  Retrieves the possible sets of I/O, MMIO, DMA, and interrupt resources for
> the
> +  ISA controller specified by Device.  The sets are returned in ResourceList.
> +
> +  @param[in]  This           The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[in]  Device         The pointer to an ISA controller named by ACPI
> HID/UID.
> +  @param[out] ResourceList   The pointer to the returned list of resource lists.
> +
> +  @retval EFI_UNSUPPORTED  This service is not supported.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_GET_POS_RESOURCE)(
> +  IN EFI_ISA_ACPI_PROTOCOL        *This,
> +  IN EFI_ISA_ACPI_DEVICE_ID       *Device,
> +  OUT EFI_ISA_ACPI_RESOURCE_LIST  **ResourceList
> +  );
> +
> +/**
> +  Assigns resources to an ISA controller.
> +
> +  Assigns the I/O, MMIO, DMA, and interrupt resources specified by
> ResourceList
> +  to the ISA controller specified by Device.  ResourceList must match a resource
> list returned by GetPosResource() for the same ISA controller.
> +
> +  @param[in] This           The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[in] Device         The pointer to an ISA controller named by ACPI
> HID/UID.
> +  @param[in] ResourceList   The pointer to a resources list that must be one of
> the
> +                            resource lists returned by GetPosResource() for the
> +                            ISA controller specified by Device.
> +
> +  @retval EFI_SUCCESS  Successfully set resources on the ISA controller.
> +  @retval Other        The resources could not be set for the ISA controller.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_SET_RESOURCE)(
> +  IN EFI_ISA_ACPI_PROTOCOL       *This,
> +  IN EFI_ISA_ACPI_DEVICE_ID      *Device,
> +  IN EFI_ISA_ACPI_RESOURCE_LIST  *ResourceList
> +  );
> +
> +/**
> +  Enables or disables an ISA controller.
> +
> +  @param[in] This     The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[in] Device   The pointer to the ISA controller to enable/disable.
> +  @param[in] Enable   TRUE to enable the ISA controller.  FALSE to disable the
> +                      ISA controller.
> +
> +  @retval EFI_SUCCESS   Successfully enabled/disabled the ISA controller.
> +  @retval Other         The ISA controller could not be placed in the requested
> state.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_ENABLE_DEVICE)(
> +  IN EFI_ISA_ACPI_PROTOCOL   *This,
> +  IN EFI_ISA_ACPI_DEVICE_ID  *Device,
> +  IN BOOLEAN                 Enable
> +  );
> +
> +/**
> +  Initializes an ISA controller, so that it can be used.  This service must be called
> +  before SetResource(), EnableDevice(), or SetPower() will behave as expected.
> +
> +  @param[in] This     The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +  @param[in] Device   The pointer to an ISA controller named by ACPI HID/UID.
> +
> +  @retval EFI_SUCCESS   Successfully initialized an ISA controller.
> +  @retval Other         The ISA controller could not be initialized.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_INIT_DEVICE)(
> +  IN EFI_ISA_ACPI_PROTOCOL   *This,
> +  IN EFI_ISA_ACPI_DEVICE_ID  *Device
> +  );
> +
> +/**
> +  Initializes all the HW states required for the ISA controllers on the ISA bus
> +  to be enumerated and managed by the rest of the services in this prorotol.
> +  This service must be called before any of the other services in this
> +  protocol will function as expected.
> +
> +  @param[in] This  The pointer to the EFI_ISA_ACPI_PROTOCOL instance.
> +
> +  @retval EFI_SUCCESS   Successfully initialized all required hardware states.
> +  @retval Other         The ISA interface could not be initialized.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_ACPI_INTERFACE_INIT)(
> +  IN EFI_ISA_ACPI_PROTOCOL  *This
> +  );
> +
> +///
> +/// The EFI_ISA_ACPI_PROTOCOL provides the services to enumerate and
> manage
> +/// ISA controllers on an ISA bus.  These services include the ability to initialize,
> +/// enable, disable, and manage the power state of ISA controllers.  It also
> +/// includes services to query current resources, query possible resources,
> +/// and assign resources to an ISA controller.
> +///
> +struct _EFI_ISA_ACPI_PROTOCOL {
> +  EFI_ISA_ACPI_DEVICE_ENUMERATE  DeviceEnumerate;
> +  EFI_ISA_ACPI_SET_DEVICE_POWER  SetPower;
> +  EFI_ISA_ACPI_GET_CUR_RESOURCE  GetCurResource;
> +  EFI_ISA_ACPI_GET_POS_RESOURCE  GetPosResource;
> +  EFI_ISA_ACPI_SET_RESOURCE      SetResource;
> +  EFI_ISA_ACPI_ENABLE_DEVICE     EnableDevice;
> +  EFI_ISA_ACPI_INIT_DEVICE       InitDevice;
> +  EFI_ISA_ACPI_INTERFACE_INIT    InterfaceInit;
> +};
> +
> +extern EFI_GUID gEfiIsaAcpiProtocolGuid;
> +
> +#endif
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaIo.h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaIo.h
> new file mode 100644
> index 0000000000..30000305fb
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/IsaIo.h
> @@ -0,0 +1,356 @@
> +/** @file
> +  ISA I/O Protocol is used by ISA device drivers to perform I/O, MMIO and DMA
> +  operations on the ISA controllers they manage.
> +
> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _EFI_ISA_IO_H_
> +#define _EFI_ISA_IO_H_
> +
> +#include <Protocol/IsaAcpi.h>
> +
> +///
> +/// Global ID for the EFI_ISA_IO_PROTOCOL
> +///
> +#define EFI_ISA_IO_PROTOCOL_GUID \
> +  { \
> +    0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1,
> 0x4d } \
> +  }
> +
> +///
> +/// Forward declaration for the EFI_ISA_IO_PROTOCOL.
> +///
> +typedef struct _EFI_ISA_IO_PROTOCOL EFI_ISA_IO_PROTOCOL;
> +
> +///
> +/// Width of EFI_ISA_IO_PROTOCOL I/O Port and MMIO operations.
> +///
> +typedef enum {
> +  EfiIsaIoWidthUint8 = 0,      ///< 8-bit operation.
> +  EfiIsaIoWidthUint16,         ///< 16-bit operation.
> +  EfiIsaIoWidthUint32,         ///< 32-bit operation
> +  EfiIsaIoWidthReserved,
> +  EfiIsaIoWidthFifoUint8,      ///< 8-bit FIFO operation.
> +  EfiIsaIoWidthFifoUint16,     ///< 16-bit FIFO operation.
> +  EfiIsaIoWidthFifoUint32,     ///< 32-bit FIFO operation.
> +  EfiIsaIoWidthFifoReserved,
> +  EfiIsaIoWidthFillUint8,      ///< 8-bit Fill operation.
> +  EfiIsaIoWidthFillUint16,     ///< 16-bit Fill operation.
> +  EfiIsaIoWidthFillUint32,     ///< 32-bit Fill operation.
> +  EfiIsaIoWidthFillReserved,
> +  EfiIsaIoWidthMaximum
> +} EFI_ISA_IO_PROTOCOL_WIDTH;
> +
> +///
> +/// Attributes for the EFI_ISA_IO_PROTOCOL common DMA buffer allocations.
> +///
> +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE  0x080    ///<
> Map a memory range so write are combined.
> +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED         0x800    ///< Map a
> memory range so all read and write accesses are cached.
> +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_DISABLE        0x1000   ///< Disable
> a memory range.
> +
> +///
> +/// Channel attribute for EFI_ISA_IO_PROTOCOL slave DMA requests
> +///
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE  0x001
> ///< Set the speed of the DMA transfer in compatible mode.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A           0x002   ///< Not
> supported.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B           0x004   ///< Not
> supported.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C           0x008   ///< Not
> supported.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8           0x010   ///<
> Request 8-bit DMA transfers.  Only available on channels 0..3.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16          0x020   ///<
> Request 16-bit DMA transfers.  Only available on channels 4..7.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE       0x040   ///<
> Request a single DMA transfer.
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE       0x080
> ///< Request multiple DMA transfers until TC (Terminal Count) or EOP (End of
> Process).
> +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE   0x100   ///<
> Automatically reload base and count at the end of the DMA transfer.
> +
> +///
> +/// The DMA opreration type for EFI_ISA_IO_PROTOCOL DMA requests.
> +///
> +typedef enum {
> +  ///
> +  /// A read operation from system memory by a bus master.
> +  ///
> +  EfiIsaIoOperationBusMasterRead,
> +  ///
> +  /// A write operation to system memory by a bus master.
> +  ///
> +  EfiIsaIoOperationBusMasterWrite,
> +  ///
> +  /// Provides both read and write access to system memory by both the
> processor
> +  /// and a bus master. The buffer is coherent from both the processor's and
> the
> +  /// bus master's point of view.
> +  ///
> +  EfiIsaIoOperationBusMasterCommonBuffer,
> +  ///
> +  /// A read operation from system memory by a slave device.
> +  ///
> +  EfiIsaIoOperationSlaveRead,
> +  ///
> +  /// A write operation to system memory by a slave master.
> +  ///
> +  EfiIsaIoOperationSlaveWrite,
> +  EfiIsaIoOperationMaximum
> +} EFI_ISA_IO_PROTOCOL_OPERATION;
> +
> +/**
> +  Performs ISA I/O and MMIO Read/Write Cycles
> +
> +  @param[in]      This     A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +  @param[in]      Width    Specifies the width of the I/O or MMIO operation.
> +  @param[in]      Offset   The offset into the ISA I/O or MMIO space to start the
> +                           operation.
> +  @param[in]      Count    The number of I/O or MMIO operations to perform.
> +  @param[in, out] Buffer   For read operations, the destination buffer to store
> +                           the results. For write operations, the source buffer to
> +                           write data from.
> +
> +  @retval EFI_SUCCESS             The data was successfully read from or written to
> the device.
> +  @retval EFI_UNSUPPORTED         The Offset is not valid for this device.
> +  @retval EFI_INVALID_PARAMETER   Width or Count, or both, were invalid.
> +  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due
> to a lack of resources.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_IO_MEM)(
> +  IN     EFI_ISA_IO_PROTOCOL        *This,
> +  IN     EFI_ISA_IO_PROTOCOL_WIDTH  Width,
> +  IN     UINT32                     Offset,
> +  IN     UINTN                      Count,
> +  IN OUT VOID                       *Buffer
> +  );
> +
> +///
> +/// Structure of functions for accessing ISA I/O and MMIO space.
> +///
> +typedef struct {
> +  ///
> +  /// Read from ISA I/O or MMIO space.
> +  ///
> +  EFI_ISA_IO_PROTOCOL_IO_MEM  Read;
> +  ///
> +  /// Write to ISA I/O or MMIO space.
> +  ///
> +  EFI_ISA_IO_PROTOCOL_IO_MEM  Write;
> +} EFI_ISA_IO_PROTOCOL_ACCESS;
> +
> +/**
> +  Copies data from one region of ISA MMIO space to another region of ISA
> +  MMIO space.
> +
> +  @param[in] This         A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +  @param[in] Width        Specifies the width of the MMIO copy operation.
> +  @param[in] DestOffset   The offset of the destination in ISA MMIO space.
> +  @param[in] SrcOffset    The offset of the source in ISA MMIO space.
> +  @param[in] Count        The number tranfers to perform for this copy
> operation.
> +
> +  @retval EFI_SUCCESS             The data was copied sucessfully.
> +  @retval EFI_UNSUPPORTED         The DestOffset or SrcOffset is not valid for
> this device.
> +  @retval EFI_INVALID_PARAMETER   Width or Count, or both, were invalid.
> +  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due
> to a lack of resources.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_COPY_MEM)(
> +  IN EFI_ISA_IO_PROTOCOL         *This,
> +  IN EFI_ISA_IO_PROTOCOL_WIDTH   Width,
> +  IN UINT32                      DestOffset,
> +  IN UINT32                      SrcOffset,
> +  IN UINTN                       Count
> +  );
> +
> +/**
> +  Maps a memory region for DMA.
> +
> +  This function returns the device-specific addresses required to access system
> memory.
> +  This function is used to map system memory for ISA DMA operations.  All ISA
> DMA
> +  operations must be performed through their mapped addresses, and such
> mappings must
> +  be freed with EFI_ISA_IO_PROTOCOL.Unmap() after the DMA operation is
> completed.
> +
> +  If the DMA operation is a single read or write data transfer through an ISA bus
> +  master, then EfiIsaIoOperationBusMasterRead or
> EfiIsaIoOperationBusMasterWrite
> +  is used and the range is unmapped to complete the operation. If the DMA
> operation
> +  is a single read or write data transfer through an ISA slave controller, then
> +  EfiIsaIoOperationSlaveRead or EfiIsaIoOperationSlaveWrite is used and the
> range
> +  is unmapped to complete the operation.
> +
> +  If performing a DMA read operation, all the data must be present in system
> memory before the Map() is performed.  Similarly,
> +  if performing a DMA write operation, the data must not be accessed in system
> +  memory until EFI_ISA_IO_PROTOCOL.Unmap() is performed.  Bus master
> operations that
> +  require both read and write access or require multiple host device
> interactions
> +  within the same mapped region must use
> EfiIsaIoOperationBusMasterCommonBuffer.
> +  However, only memory allocated via the
> EFI_ISA_IO_PROTOCOL.AllocateBuffer() interface
> +  is guaranteed to be able to be mapped for this operation type.  In all mapping
> +  requests the NumberOfBytes returned may be less than originally requested.
> It is
> +  the caller's responsibility to make additional requests to complete the entire
> +  transfer.
> +
> +  @param[in]      This                A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +  @param[in]      Operation           Indicates the type of DMA (slave or bus
> master),
> +                                      and if the DMA operation is going to read or
> +                                      write to system memory.
> +  @param[in]      ChannelNumber       The slave channel number to use for this
> DMA
> +                                      operation.  If Operation and ChannelAttributes
> +                                      shows that this device performs bus mastering
> +                                      DMA, then this field is ignored.  The legal
> +                                      range for this field is 0..7.
> +  @param[in]      ChannelAttributes   A bitmask of the attributes used to
> configure
> +                                      the slave DMA channel for this DMA operation.
> +                                      See EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_* for the
> +                                      legal bit combinations.
> +  @param[in]      HostAddress         The system memory address to map to the
> device.
> +  @param[in, out] NumberOfBytes       On input the number of bytes to map.
> On
> +                                      output the number of bytes that were mapped.
> +  @param[out]     DeviceAddress       The resulting map address for the bus
> master
> +                                      device to use to access the hosts HostAddress.
> +  @param[out]     Mapping             A returned value that must be passed to into
> +                                      EFI_ISA_IO_PROTOCOL.Unmap() to free all the the
> +                                      resources associated with this map request.
> +
> +  @retval EFI_SUCCESS             The range was mapped for the returned
> NumberOfBytes.
> +  @retval EFI_INVALID_PARAMETER   The Operation is undefined.
> +  @retval EFI_INVALID_PARAMETER   The HostAddress is undefined.
> +  @retval EFI_UNSUPPORTED         The HostAddress can not be mapped as a
> common buffer.
> +  @retval EFI_DEVICE_ERROR        The system hardware could not map the
> requested address.
> +  @retval EFI_OUT_OF_RESOURCES    The memory pages could not be
> allocated.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_MAP)(
> +  IN     EFI_ISA_IO_PROTOCOL            *This,
> +  IN     EFI_ISA_IO_PROTOCOL_OPERATION  Operation,
> +  IN     UINT8                          ChannelNumber      OPTIONAL,
> +  IN     UINT32                         ChannelAttributes,
> +  IN     VOID                           *HostAddress,
> +  IN OUT UINTN                          *NumberOfBytes,
> +  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
> +  OUT    VOID                           **Mapping
> +  );
> +
> +/**
> +  Unmaps a memory region that was previously mapped with
> EFI_ISA_IO_PROTOCOL.Map().
> +
> +  The EFI_ISA_IO_PROTOCOL.Map() operation is completed and any
> corresponding
> +  resources are released.  If the operation was EfiIsaIoOperationSlaveWrite
> +  or EfiIsaIoOperationBusMasterWrite, the data is committed to system
> memory.
> +  Any resources used for the mapping are freed.
> +
> +  @param[in] This           A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +  @param[in] Mapping        The mapping value returned from
> EFI_ISA_IO_PROTOCOL.Map().
> +
> +  @retval EFI_SUCCESS       The memory region was unmapped.
> +  @retval EFI_DEVICE_ERROR  The data was not committed to the target
> system memory.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_UNMAP)(
> +  IN  EFI_ISA_IO_PROTOCOL  *This,
> +  IN  VOID                 *Mapping
> +  );
> +
> +/**
> +  Allocates pages that are suitable for an
> EfiIsaIoOperationBusMasterCommonBuffer
> +  mapping.
> +
> +  @param[in]  This          A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +  @param[in]  Type          The type allocation to perform.
> +  @param[in]  MemoryType    The type of memory to allocate.
> +  @param[in]  Pages         The number of pages to allocate.
> +  @param[out] HostAddress   A pointer to store the base address of the
> allocated range.
> +  @param[in]  Attributes    The requested bit mask of attributes for the
> allocated range.
> +
> +  @retval EFI_SUCCESS             The requested memory pages were allocated.
> +  @retval EFI_INVALID_PARAMETER   Type is invalid.
> +  @retval EFI_INVALID_PARAMETER   MemoryType is invalid.
> +  @retval EFI_INVALID_PARAMETER   HostAddress is NULL.
> +  @retval EFI_UNSUPPORTED         Attributes is unsupported.
> +  @retval EFI_UNSUPPORTED         The memory range specified by
> HostAddress, Pages,
> +                                  and Type is not available for common buffer use.
> +  @retval EFI_OUT_OF_RESOURCES    The memory pages could not be
> allocated.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER)(
> +  IN  EFI_ISA_IO_PROTOCOL  *This,
> +  IN  EFI_ALLOCATE_TYPE    Type,
> +  IN  EFI_MEMORY_TYPE      MemoryType,
> +  IN  UINTN                Pages,
> +  OUT VOID                 **HostAddress,
> +  IN  UINT64               Attributes
> +  );
> +
> +/**
> +  Frees a common buffer that was allocated with
> EFI_ISA_IO_PROTOCOL.AllocateBuffer().
> +
> +  @param[in] This          A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +  @param[in] Pages         The number of pages to free from the previously
> allocated common buffer.
> +  @param[in] HostAddress   The base address of the previously allocated
> common buffer.
> +
> +
> +  @retval EFI_SUCCESS             The requested memory pages were freed.
> +  @retval EFI_INVALID_PARAMETER   The memory was not allocated with
> EFI_ISA_IO.AllocateBufer().
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_FREE_BUFFER)(
> +  IN  EFI_ISA_IO_PROTOCOL  *This,
> +  IN  UINTN                Pages,
> +  IN  VOID                 *HostAddress
> +  );
> +
> +/**
> +  Flushes a DMA buffer, which forces all DMA posted write transactions to
> complete.
> +
> +  @param[in] This   A pointer to the EFI_ISA_IO_PROTOCOL instance.
> +
> +  @retval  EFI_SUCCESS        The DMA buffers were flushed.
> +  @retval  EFI_DEVICE_ERROR   The buffers were not flushed due to a
> hardware error.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_ISA_IO_PROTOCOL_FLUSH)(
> +  IN EFI_ISA_IO_PROTOCOL  *This
> +  );
> +
> +///
> +/// The EFI_ISA_IO_PROTOCOL provides the basic Memory, I/O, and DMA
> interfaces
> +/// used to abstract accesses to ISA controllers.  There is one
> EFI_ISA_IO_PROTOCOL
> +/// instance for each ISA controller on a ISA bus. A device driver that wishes
> +/// to manage an ISA controller in a system will have to retrieve the
> +/// ISA_PCI_IO_PROTOCOL instance associated with the ISA controller.
> +///
> +struct _EFI_ISA_IO_PROTOCOL {
> +  EFI_ISA_IO_PROTOCOL_ACCESS           Mem;
> +  EFI_ISA_IO_PROTOCOL_ACCESS           Io;
> +  EFI_ISA_IO_PROTOCOL_COPY_MEM         CopyMem;
> +  EFI_ISA_IO_PROTOCOL_MAP              Map;
> +  EFI_ISA_IO_PROTOCOL_UNMAP            Unmap;
> +  EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER  AllocateBuffer;
> +  EFI_ISA_IO_PROTOCOL_FREE_BUFFER      FreeBuffer;
> +  EFI_ISA_IO_PROTOCOL_FLUSH            Flush;
> +  ///
> +  /// The list of I/O , MMIO, DMA, and Interrupt resources associated with the
> +  /// ISA controller abstracted by this instance of the EFI_ISA_IO_PROTOCOL.
> +  ///
> +  EFI_ISA_ACPI_RESOURCE_LIST           *ResourceList;
> +  ///
> +  /// The size, in bytes, of the ROM image.
> +  ///
> +  UINT32                               RomSize;
> +  ///
> +  /// A pointer to the in memory copy of the ROM image. The ISA Bus Driver is
> responsible
> +  /// for allocating memory for the ROM image, and copying the contents of the
> ROM to memory
> +  /// during ISA Bus initialization.
> +  ///
> +  VOID                                 *RomImage;
> +};
> +
> +extern EFI_GUID gEfiIsaIoProtocolGuid;
> +
> +#endif
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/Legacy8259.h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/Legacy8259.h
> new file mode 100644
> index 0000000000..c38f2feba7
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Protocol/Legacy8259.h
> @@ -0,0 +1,291 @@
> +/** @file
> +  This protocol abstracts the 8259 interrupt controller. This includes
> +  PCI IRQ routing needed to program the PCI Interrupt Line register.
> +
> +  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Revision Reference:
> +  This protocol is defined in Framework for EFI Compatibility Support Module
> spec
> +  Version 0.97.
> +
> +**/
> +
> +#ifndef _EFI_LEGACY_8259_H_
> +#define _EFI_LEGACY_8259_H_
> +
> +
> +#define EFI_LEGACY_8259_PROTOCOL_GUID \
> +  { \
> +    0x38321dba, 0x4fe0, 0x4e17, {0x8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed,
> 0xc1 } \
> +  }
> +
> +typedef struct _EFI_LEGACY_8259_PROTOCOL
> EFI_LEGACY_8259_PROTOCOL;
> +
> +typedef enum {
> +  Efi8259Irq0,
> +  Efi8259Irq1,
> +  Efi8259Irq2,
> +  Efi8259Irq3,
> +  Efi8259Irq4,
> +  Efi8259Irq5,
> +  Efi8259Irq6,
> +  Efi8259Irq7,
> +  Efi8259Irq8,
> +  Efi8259Irq9,
> +  Efi8259Irq10,
> +  Efi8259Irq11,
> +  Efi8259Irq12,
> +  Efi8259Irq13,
> +  Efi8259Irq14,
> +  Efi8259Irq15,
> +  Efi8259IrqMax
> +} EFI_8259_IRQ;
> +
> +typedef enum {
> +  Efi8259LegacyMode,
> +  Efi8259ProtectedMode,
> +  Efi8259MaxMode
> +} EFI_8259_MODE;
> +
> +/**
> +  Get the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for
> +  the legacy mode mask and the protected mode mask. The base address for
> the 8259
> +  is different for legacy and protected mode, so two masks are required.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  MasterBase            The base vector for the Master PIC in the 8259
> controller.
> +  @param  SlaveBase             The base vector for the Slave PIC in the 8259
> controller.
> +
> +  @retval EFI_SUCCESS           The new bases were programmed.
> +  @retval EFI_DEVICE_ERROR      A device error occured programming the
> vector bases.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_SET_VECTOR_BASE)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  UINT8                             MasterBase,
> +  IN  UINT8                             SlaveBase
> +  );
> +
> +/**
> +  Get the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for
> +  the legacy mode mask and the protected mode mask. The base address for
> the 8259
> +  is different for legacy and protected mode, so two masks are required.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  LegacyMask            Bit 0 is Irq0 - Bit 15 is Irq15.
> +  @param  LegacyEdgeLevel       Bit 0 is Irq0 - Bit 15 is Irq15.
> +  @param  ProtectedMask         Bit 0 is Irq0 - Bit 15 is Irq15.
> +  @param  ProtectedEdgeLevel    Bit 0 is Irq0 - Bit 15 is Irq15.
> +
> +  @retval EFI_SUCCESS           8259 status returned.
> +  @retval EFI_DEVICE_ERROR      Error reading 8259.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_GET_MASK)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  OUT UINT16                            *LegacyMask, OPTIONAL
> +  OUT UINT16                            *LegacyEdgeLevel, OPTIONAL
> +  OUT UINT16                            *ProtectedMask, OPTIONAL
> +  OUT UINT16                            *ProtectedEdgeLevel OPTIONAL
> +  );
> +
> +/**
> +  Set the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for
> +  the legacy mode mask and the protected mode mask. The base address for
> the 8259
> +  is different for legacy and protected mode, so two masks are required.
> +  Also set the edge/level masks.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  LegacyMask            Bit 0 is Irq0 - Bit 15 is Irq15.
> +  @param  LegacyEdgeLevel       Bit 0 is Irq0 - Bit 15 is Irq15.
> +  @param  ProtectedMask         Bit 0 is Irq0 - Bit 15 is Irq15.
> +  @param  ProtectedEdgeLevel    Bit 0 is Irq0 - Bit 15 is Irq15.
> +
> +  @retval EFI_SUCCESS           8259 status returned.
> +  @retval EFI_DEVICE_ERROR      Error writing 8259.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_SET_MASK)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  UINT16                            *LegacyMask, OPTIONAL
> +  IN  UINT16                            *LegacyEdgeLevel, OPTIONAL
> +  IN  UINT16                            *ProtectedMask, OPTIONAL
> +  IN  UINT16                            *ProtectedEdgeLevel OPTIONAL
> +  );
> +
> +/**
> +  Set the 8259 mode of operation. The base address for the 8259 is different
> for
> +  legacy and protected mode. The legacy mode requires the master 8259 to
> have a
> +  master base of 0x08 and the slave base of 0x70. The protected mode base
> locations
> +  are not defined. Interrupts must be masked by the caller before this function
> +  is called. The interrupt mask from the current mode is saved. The interrupt
> +  mask for the new mode is Mask, or if Mask does not exist the previously saved
> +  mask is used.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  Mode                  The mode of operation. i.e. the real mode or
> protected mode.
> +  @param  Mask                  Optional interupt mask for the new mode.
> +  @param  EdgeLevel             Optional trigger mask for the new mode.
> +
> +  @retval EFI_SUCCESS           8259 programmed.
> +  @retval EFI_DEVICE_ERROR      Error writing to 8259.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_SET_MODE)(
> +  IN EFI_LEGACY_8259_PROTOCOL         *This,
> +  IN  EFI_8259_MODE                   Mode,
> +  IN  UINT16                          *Mask, OPTIONAL
> +  IN  UINT16                          *EdgeLevel OPTIONAL
> +  );
> +
> +/**
> +  Convert from IRQ to processor interrupt vector number.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  Irq                   8259 IRQ0 - IRQ15.
> +  @param  Vector                The processor vector number that matches an Irq.
> +
> +  @retval EFI_SUCCESS           The Vector matching Irq is returned.
> +  @retval EFI_INVALID_PARAMETER The Irq not valid.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_GET_VECTOR)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  EFI_8259_IRQ                      Irq,
> +  OUT UINT8                             *Vector
> +  );
> +
> +/**
> +  Enable Irq by unmasking interrupt in 8259
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  Irq                   8259 IRQ0 - IRQ15.
> +  @param  LevelTriggered        TRUE if level triggered. FALSE if edge triggered.
> +
> +  @retval EFI_SUCCESS           The Irq was enabled on 8259.
> +  @retval EFI_INVALID_PARAMETER The Irq is not valid.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_ENABLE_IRQ)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  EFI_8259_IRQ                      Irq,
> +  IN  BOOLEAN                           LevelTriggered
> +  );
> +
> +/**
> +  Disable Irq by masking interrupt in 8259
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  Irq                   8259 IRQ0 - IRQ15.
> +
> +  @retval EFI_SUCCESS           The Irq was disabled on 8259.
> +  @retval EFI_INVALID_PARAMETER The Irq is not valid.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_DISABLE_IRQ)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  EFI_8259_IRQ                      Irq
> +  );
> +
> +/**
> +  PciHandle represents a PCI config space of a PCI function. Vector
> +  represents Interrupt Pin (from PCI config space) and it is the data
> +  that is programmed into the Interrupt Line (from the PCI config space)
> +  register.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  PciHandle             The PCI function to return the vector for.
> +  @param  Vector                The vector for the function it matches.
> +
> +  @retval EFI_SUCCESS           A valid Vector was returned.
> +  @retval EFI_INVALID_PARAMETER PciHandle not valid.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_GET_INTERRUPT_LINE)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  EFI_HANDLE                        PciHandle,
> +  OUT UINT8                             *Vector
> +  );
> +
> +/**
> +  Send an EOI to 8259
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  Irq                   8259 IRQ0 - IRQ15.
> +
> +  @retval EFI_SUCCESS           EOI was successfully sent to 8259.
> +  @retval EFI_INVALID_PARAMETER The Irq isnot valid.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_LEGACY_8259_END_OF_INTERRUPT)(
> +  IN EFI_LEGACY_8259_PROTOCOL           *This,
> +  IN  EFI_8259_IRQ                      Irq
> +  );
> +
> +/**
> +  @par Protocol Description:
> +  Abstracts the 8259 and APIC hardware control between EFI usage and
> +  Compatibility16 usage.
> +
> +  @param SetVectorBase
> +  Sets the vector bases for master and slave PICs.
> +
> +  @param GetMask
> +  Gets IRQ and edge/level masks for 16-bit real mode and 32-bit protected
> mode.
> +
> +  @param SetMask
> +  Sets the IRQ and edge\level masks for 16-bit real mode and 32-bit protected
> mode.
> +
> +  @param SetMode
> +  Sets PIC mode to 16-bit real mode or 32-bit protected mode.
> +
> +  @param GetVector
> +  Gets the base vector assigned to an IRQ.
> +
> +  @param EnableIrq
> +  Enables an IRQ.
> +
> +  @param DisableIrq
> +  Disables an IRQ.
> +
> +  @param GetInterruptLine
> +  Gets an IRQ that is assigned to a PCI device.
> +
> +  @param EndOfInterrupt
> +  Issues the end of interrupt command.
> +
> +**/
> +struct _EFI_LEGACY_8259_PROTOCOL {
> +  EFI_LEGACY_8259_SET_VECTOR_BASE     SetVectorBase;
> +  EFI_LEGACY_8259_GET_MASK            GetMask;
> +  EFI_LEGACY_8259_SET_MASK            SetMask;
> +  EFI_LEGACY_8259_SET_MODE            SetMode;
> +  EFI_LEGACY_8259_GET_VECTOR          GetVector;
> +  EFI_LEGACY_8259_ENABLE_IRQ          EnableIrq;
> +  EFI_LEGACY_8259_DISABLE_IRQ         DisableIrq;
> +  EFI_LEGACY_8259_GET_INTERRUPT_LINE  GetInterruptLine;
> +  EFI_LEGACY_8259_END_OF_INTERRUPT    EndOfInterrupt;
> +};
> +
> +extern EFI_GUID gEfiLegacy8259ProtocolGuid;
> +
> +#endif
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Include/Register/X58SmramSaveStateM
> ap.h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Register/X58SmramSaveStateM
> ap.h
> new file mode 100644
> index 0000000000..640ac4943d
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Include/Register/X58SmramSaveStateM
> ap.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) 2015, 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/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
> b/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
> new file mode 100644
> index 0000000000..c79111d811
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
> @@ -0,0 +1,54 @@
> +/** @file
> +  OVMF Platform definitions
> +
> +  Copyright (C) 2015, Red Hat, Inc.
> +  Copyright (c) 2014, Gabriel L. Somlo <somlo at cmu.edu>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef __OVMF_PLATFORMS_H__
> +#define __OVMF_PLATFORMS_H__
> +
> +#include <Library/PciLib.h>
> +#include <IndustryStandard/Pci22.h>
> +#include <IndustryStandard/X58Ich10.h>
> +#include <IndustryStandard/I440FxPiix4.h> // TODO: remove
> +
> +//
> +// 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/LoadLinuxLib/Ia32/JumpToKern
> el.nasm
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKern
> el.nasm
> new file mode 100644
> index 0000000000..3f3cd33c8a
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKern
> el.nasm
> @@ -0,0 +1,41 @@
> +; @file
> +; Copyright (c) 2006 - 2013 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..c4cc4dd8e7
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
> @@ -0,0 +1,52 @@
> +/** @file
> +  Boot UEFI Linux.
> +
> +  Copyright (c) 2008 - 2013 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/LoadLinuxLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
> new file mode 100644
> index 0000000000..89664f4e42
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
> @@ -0,0 +1,42 @@
> +## @file
> +#
> +# Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = LoadLinuxLib
> +  FILE_GUID                      = 63CC8497-C9D0-46A8-AC08-49DF92A2FF62
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = LoadLinuxLib
> +
> +#
> +# 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
> +  OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKerne
> l.nasm
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKerne
> l.nasm
> new file mode 100644
> index 0000000000..79e6b8e7ba
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKerne
> l.nasm
> @@ -0,0 +1,85 @@
> +; @file
> +; Copyright (c) 2006 - 2013 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..92aa038cdd
> --- /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 - 2011 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..e4c3b7ccff
> --- /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 - 2018 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/SerializeVariablesLib/SerializeVa
> riablesLib.h
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVa
> riablesLib.h
> new file mode 100644
> index 0000000000..7e78cd4b21
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVa
> riablesLib.h
> @@ -0,0 +1,33 @@
> +/** @file
> +  Serialize Variables Library implementation
> +
> +  Copyright (c) 2009 - 2011 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/SerializeVa
> riablesLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVa
> riablesLib.inf
> new file mode 100644
> index 0000000000..25901192b2
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVa
> riablesLib.inf
> @@ -0,0 +1,36 @@
> +## @file
> +#  Serialize Variables Library implementation
> +#
> +#  This library serializes and deserializes UEFI variables
> +#
> +# Copyright (c) 2006 - 2018 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
> +  OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.h
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.h
> new file mode 100644
> index 0000000000..63b5e52575
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.h
> @@ -0,0 +1,37 @@
> +/** @file
> +  This driver effectuates OVMF's platform configuration settings and exposes
> +  them via HII.
> +
> +  Copyright (C) 2014, Red Hat, Inc.
> +
> +  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/PlatformDxe/Platform.inf
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.inf
> new file mode 100644
> index 0000000000..804ab59610
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.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 - 2010, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PlatformDxe
> +  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/SimicsOpenBoardPkg.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
> +  gSimicsX58PlatformConfigGuid
> +
> +[Depex]
> +  gEfiHiiConfigRoutingProtocolGuid  AND
> +  gEfiHiiDatabaseProtocolGuid       AND
> +  gEfiVariableArchProtocolGuid      AND
> +  gEfiVariableWriteArchProtocolGuid
> diff --git a/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.uni
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.uni
> new file mode 100644
> index 0000000000..6d68cbeb4f
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/Platform.uni
> @@ -0,0 +1,31 @@
> +// *++
> +//
> +// Copyright (C) 2014, Red Hat, Inc.
> +// Copyright (c) 2009, 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/PlatformDxe/PlatformConfig.h
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformConfig.h
> new file mode 100644
> index 0000000000..d3f041ddea
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformConfig.h
> @@ -0,0 +1,51 @@
> +/** @file
> +  Utility functions for serializing (persistently storing) and deserializing
> +  OVMF's platform configuration.
> +
> +  Copyright (C) 2014, Red Hat, Inc.
> +
> +  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/PlatformDxe/PlatformForms.vfr
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformForms.vfr
> new file mode 100644
> index 0000000000..1c02565ebb
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformDxe/PlatformForms.vfr
> @@ -0,0 +1,67 @@
> +// *++
> +//
> +// Copyright (C) 2014, Red Hat, Inc.
> +// Copyright (c) 2009 - 2011, 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/SimicsX58PlatformConfig.h>
> +#include "Platform.h"
> +
> +formset
> +  guid  = SIMICSX58_PLATFORM_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  = SIMICSX58_PLATFORM_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/PlatformPei/Cmos.h
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.h
> new file mode 100644
> index 0000000000..616d2d74cb
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Cmos.h
> @@ -0,0 +1,50 @@
> +/** @file
> +  PC/AT CMOS access routines
> +
> +  Copyright (c) 2006 - 2009 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/PlatformPei/Platform.h
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Platform.h
> new file mode 100644
> index 0000000000..5b1a9b5f57
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/Platform.h
> @@ -0,0 +1,93 @@
> +/** @file
> +  Platform PEI module include file.
> +
> +  Copyright (c) 2006 - 2016 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
> +  );
> +
> +EFI_STATUS
> +PeiFvInitialization (
> +  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/PlatformPei/PlatformPei.inf
> b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/PlatformPei.inf
> new file mode 100644
> index 0000000000..eb8048c655
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/PlatformPei/PlatformPei.inf
> @@ -0,0 +1,109 @@
> +## @file
> +#  Platform PEI driver
> +#
> +#  This module provides platform specific function to detect boot mode.
> +# Copyright (c) 2006 - 2018 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PlatformPei
> +  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
> +  Fv.c
> +  MemDetect.c
> +  Platform.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +  SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> +  MinPlatformPkg/MinPlatformPkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +
> +[Guids]
> +  gEfiMemoryTypeInformationGuid
> +  gEfiSmmPeiSmramMemoryReserveGuid              ## CONSUMES
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  HobLib
> +  IoLib
> +  PciLib
> +  PeiResourcePublicationLib
> +  PeiServicesLib
> +  PeiServicesTablePointerLib
> +  PeimEntryPoint
> +  MtrrLib
> +  PcdLib
> +
> +[Pcd]
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsLockBoxStorageBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsLockBoxStorageSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPageTablesBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPeiTempRamBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPeiTempRamSize
> +  gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
> +  gSimicsX58PkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciIoBase
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciIoSize
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio32Base
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio32Size
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio64Base
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio64Size
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
> +  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/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.inf
> new file mode 100644
> index 0000000000..b9bcb5d2bd
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/Silicon
> PolicyInitLib.inf
> @@ -0,0 +1,38 @@
> +## @file
> +#
> +# Copyright (c) 2018 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/Sil
> iconPolicyUpdateLib.inf
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sil
> iconPolicyUpdateLib.inf
> new file mode 100644
> index 0000000000..da165ac947
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/Sil
> iconPolicyUpdateLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +#
> +# Copyright (c) 2018 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/SimicsOpenBoardPkg.dec
> b/Platform/Intel/SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> new file mode 100644
> index 0000000000..17c87aca8c
> --- /dev/null
> +++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec
> @@ -0,0 +1,168 @@
> +## @file
> +#  EFI/Framework Simics X58 platform
> +#
> +# Copyright (c) 2018 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  DEC_SPECIFICATION              = 0x00010005
> +  PACKAGE_NAME                   = SimicsX58Pkg
> +  PACKAGE_GUID                   = E6A03E0D-5944-4dc6-9292-090D609EDD3A
> +  PACKAGE_VERSION                = 0.1
> +
> +[Includes]
> +  Include
> +
> +[Guids]
> +  gSimicsX58PkgTokenSpaceGuid   = {0x5b276d20, 0x37d0, 0x4af0, {0x8d,
> 0x04, 0x47, 0x91, 0x2b, 0x7c, 0x1d, 0x44}}
> +  gSimicsX58PlatformConfigGuid  = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a,
> 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
> +
> +[Protocols]
> +  gEfiLegacy8259ProtocolGuid          = {0x38321dba, 0x4fe0, 0x4e17, {0x8a,
> 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1}}
> +  gEfiIsaAcpiProtocolGuid             = {0x64a892dc, 0x5561, 0x4536, {0x92, 0xc7,
> 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55}}
> +  gEfiIsaIoProtocolGuid               = {0x7ee2bd44, 0x3da0, 0x11d4, {0x9a, 0x38,
> 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d}}
> +
> +[PcdsFixedAtBuild]
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvBase|0x0|UINT32|0
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvSize|0x0|UINT32|1
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvBase|0x0|UINT32|0x15
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvSize|0x0|UINT32|0x16
> +
> +  #TODO: Remove these two when we integrate new PlatformPei
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsMemFvBase|0x00800000|UINT32|2
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsMemFvSize|0x00500000|UINT32|3
> +
> +  ## 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
> +
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogBase|0x0|UI
> NT32|0x8
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize|0x0|UI
> NT32|0x9
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsFirmwareFdSize|0x0|UINT32|0xa
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsFirmwareBlockSize|0|UINT32|0xb
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase|0x0|UI
> NT32|0xc
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsFlashNvStorageFtwSpareBase|0x0|UI
> NT32|0xd
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase|0x0
> |UINT32|0xe
> +  gSimicsX58PkgTokenSpaceGuid.PcdSimicsFdBaseAddress|0x0|UINT32|0xf
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPageTablesBase|0x0|UINT32|0x1
> 1
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPageTablesSize|0x0|UINT32|0x1
> 2
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|0x0|UINT32|0
> x13
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPeiTempRamSize|0x0|UINT32|0x
> 14
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsLockBoxStorageBase|0x0|UINT32|0x
> 18
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsLockBoxStorageSize|0x0|UINT32|0x
> 19
> +
> gSimicsX58PkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT3
> 2|0x1a
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsDecompressionScratchEnd|0x0|UINT
> 32|0x1f
> +
> +[PcdsDynamic, PcdsDynamicEx]
> +
> +  # TODO: investigate whether next two Pcds are needed
> +  gSimicsX58PkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|0x28
> +
> gSimicsX58PkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEA
> N|0x10
> +
> gSimicsX58PkgTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId|0|UINT16|0
> x1b
> +
> +  ## The IO port aperture shared by all PCI root bridges.
> +  #
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x23
> +
> +  ## The 32-bit MMIO aperture shared by all PCI root bridges.
> +  #
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT64|0x24
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT64|0x25
> +
> +  ## The 64-bit MMIO aperture shared by all PCI root bridges.
> +  #
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x26
> +  gSimicsX58PkgTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x27
> +
> +[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|0x1
> e
> +
> +
> +[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|UIN
> T16|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|BOOLE
> AN|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|0
> x00000007
> +
> +  ## 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|0
> x00000008
> +
> +[PcdsFixedAtBuild, PcdsPatchableInModule]
> +  ## FFS filename to find the shell application.
> +  # @Prompt FFS Name of Shell Application
> +  gSimicsX58PkgTokenSpaceGuid.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 |
> (gSimicsX58PkgTokenSpaceGuid.PcdIsaBusSupportedFeatures & 0xF8) == 0
> +
> gSimicsX58PkgTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x0
> 0010040
> \ No newline at end of file
> diff --git
> a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe
> .h
> b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe
> .h
> new file mode 100644
> index 0000000000..38a71a3527
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe
> .h
> @@ -0,0 +1,38 @@
> +/** @file
> +  This driver installs SMBIOS information for OVMF
> +
> +  Copyright (c) 2011, Bei Guan <gbtju85 at gmail.com>
> +  Copyright (c) 2011, 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..6adaf0beb7
> --- /dev/null
> +++
> b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe
> .inf
> @@ -0,0 +1,51 @@
> +## @file
> +#  This driver installs SMBIOS information for OVMF
> +#
> +#  Copyright (c) 2011, Bei Guan <gbtju85 at gmail.com>
> +#  Copyright (c) 2011 - 2018, 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/SimicsOpenBoardPkg.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


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

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





More information about the edk2-devel-archive mailing list