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

Kubacki, Michael A michael.a.kubacki at intel.com
Mon Aug 26 23:13:20 UTC 2019


> 11. LoadLinuxLib.inf: Library name does not following naming convention. I.e.
> should be BaseLoadLinuxLib.inf.
> Ydwei: This driver is from edk2\OvmfPkg\Library\LoadLinuxLib. I didn't make
> change.
makubacki: While SimicsOpenBoardPkg has an instance of the library, it should follow the naming convention expected in the package. You do not need to change the OvmfPkg instance but please update this instance.

> 12. LoadLinuxLib.inf: This is not truly a BASE library. For example, gBS (boot
> services) are unavailable in Runtime DXE.
> Ydwei: This driver is from edk2\OvmfPkg\Library\LoadLinuxLib. I think it is just
> used by Linux Loader.
makubacki: Can the library just have type DXE_DRIVER then?

> 15. Cmos.c: It seems CmosAccessLib in BoardModulePkg could be used here to
> avoid duplication.
> Ydwei: I tried CmosAccessLib in BoardModulePkg and it cause build error. I
> didn't make change.
makubacki: I'll file a BZ to investigate and consolidate this in the future.

> 16. Fv.c: In MinPlatform, a more intuitive place to manage FVs is in a board-
> specific instance of PeiReportFvLib
> Ydwei: It is used for SIMICS S3 resume. Different purpose.
makubacki: Boot mode can be read in S3 resume. See:
https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/MinPlatformPkg/PlatformInit/Library/PeiReportFvLib/PeiReportFvLib.c
ReportFvPei in MinPlatformPkg links against a ReportFvLib library class to allow custom FV installation behavior. In this case, it seems the SimicsOpenBoardPkg ReportFvLib library instance just needs to perform the logic currently in PeiFvInitialization ().

> 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.
> Ydwei: They are SIMICS specifical. So I change their name as SimicsPei and
> SimicsDxe
makubacki: The name change is good to reduce confusion. But the code should be moved to the BoardInitLib behind the proper board APIs. One of the goals of the Minimum Platform is for code to be in predictable locations with a consistent boot flow. If the code is not moved now, a BZ will need to be filed so the code can be moved to the appropriate locations in a follow up change.

> -----Original Message-----
> From: Wei, David Y
> Sent: Friday, August 23, 2019 9:58 AM
> To: Kubacki, Michael A <michael.a.kubacki at intel.com>; devel at edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu at intel.com>; Gao, Liming <liming.gao at intel.com>;
> Sinha, Ankit <ankit.sinha at intel.com>; Agyeman, Prince
> <prince.agyeman at intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone at intel.com>; Kinney, Michael D
> <michael.d.kinney at intel.com>
> Subject: RE: [edk2-platform patch 3/7] SimicsOpenBoardPkg: Add
> SimicsOpenBoardPkg and its modules
> 
> Hi Mike,
> Please see the updates online below. Please let me know if you have any more
> comments.
> 
> Thanks
> David
> 
> -----Original Message-----
> From: Kubacki, Michael A
> Sent: Monday, August 19, 2019 6:04 PM
> To: Wei, David Y <david.y.wei at intel.com>; devel at edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu at intel.com>; Gao, Liming <liming.gao at intel.com>;
> Sinha, Ankit <ankit.sinha at intel.com>; Agyeman, Prince
> <prince.agyeman at intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone at intel.com>; Kinney, Michael D
> <michael.d.kinney at intel.com>
> Subject: RE: [edk2-platform patch 3/7] SimicsOpenBoardPkg: Add
> SimicsOpenBoardPkg and its modules
> 
> 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) {"
> Ydwei: done
> 2. BasePchSpiCommonLib.inf: This silicon package should not have a
> dependency on SimicsOpenBoardPkg.dec.
> Ydwei: done
> 3. Platform.h: This header guard definition is unusual in style and convention,
> please correct: "_Platform_h_INCLUDED_"
> Ydwei: done
> 4. Platform.h: Please update usage of "OVMF" in various signatures throughout
> the file to something package unique.
> Ydwei: done
> 5. SimicsX58PlatformConfig.h: Why is this file not in SimicsX58SktPkg?
> Ydwei: done
> 6. SimicsX58PlatformConfig.h: Change "OVMF" in copyright header to "Simics
> X58"
> Ydwei: done
> 7. SimicsPlatforms.h: Change "OVMF" in copyright header to "Simics"
> Ydwei: done
> 8. SimicsPlatforms.h - Line 16: Follow up on TODO
> Ydwei: done
> 9. X58Ich10.h: Why is this file in the Simics board package? It should be in the
> silicon package.
> Ydwei: done
> 10. LoadLinuxLib.inf: This package should avoid a depdency on OvmfPkg.dec
> Ydwei: done
> 11. LoadLinuxLib.inf: Library name does not following naming convention. I.e.
> should be BaseLoadLinuxLib.inf.
> Ydwei: This driver is from edk2\OvmfPkg\Library\LoadLinuxLib. I didn't make
> change.
> 12. LoadLinuxLib.inf: This is not truly a BASE library. For example, gBS (boot
> services) are unavailable in Runtime DXE.
> Ydwei: This driver is from edk2\OvmfPkg\Library\LoadLinuxLib. I think it is just
> used by Linux Loader.
> 13. Platform.c: Change "OVMF" reference in copyright header.
> Ydwei: done
> 14. Platform.h: Change "OVMF" reference in copyright header.
> Ydwei: done
> 15. Cmos.c: It seems CmosAccessLib in BoardModulePkg could be used here to
> avoid duplication.
> Ydwei: I tried CmosAccessLib in BoardModulePkg and it cause build error. I
> didn't make change.
> 16. Fv.c: In MinPlatform, a more intuitive place to manage FVs is in a board-
> specific instance of PeiReportFvLib
> Ydwei: It is used for SIMICS S3 resume. Different purpose.
> 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.
> Ydwei: They are SIMICS specifical. So I change their name as SimicsPei and
> SimicsDxe
> 18. PlatformPei.inf: This package should avoid a depdency on OvmfPkg.dec
> Ydwei: done
> 19. X58SmamSaveStateMap.h: If X58-specific, it should go to SimicsX58SktPkg.
> Ydwei: done
> 20. SerializeVariablesLib.inf: This package should avoid a depdency on
> OvmfPkg.dec
> Ydwei: done
> 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.
> Ydwei: done
> 22. SimicsOpenBoardPkg.dec: "X58" should be removed from the copyright
> header as the DEC is at the package-level
>        and not the board level.
> Ydwei: done
> 23. SimicsOpenBoardPkg.dec: The PACKAGE_NAME should not be "
> SimicsX58Pkg" as the DEC is at package-level and
>        not Simics board-specific.
> Ydwei: done
> > -----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 (#46384): https://edk2.groups.io/g/devel/message/46384
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