public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Kubacki, Michael A" <michael.a.kubacki@intel.com>
To: "Wei, David Y" <david.y.wei@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Wu, Hao A" <hao.a.wu@intel.com>,
	"Gao, Liming" <liming.gao@intel.com>,
	"Sinha, Ankit" <ankit.sinha@intel.com>,
	"Agyeman, Prince" <prince.agyeman@intel.com>,
	"Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>,
	"Kinney, Michael D" <michael.d.kinney@intel.com>
Subject: Re: [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules
Date: Wed, 4 Sep 2019 06:40:22 +0000	[thread overview]
Message-ID: <49AB4ACB9627B8468F29D589A27B745588AA0250@ORSMSX121.amr.corp.intel.com> (raw)
In-Reply-To: <e9ed36dae4c261640f5928b0af885ba7ffc9ce87.1567199162.git.david.y.wei@intel.com>

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

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

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


  parent reply	other threads:[~2019-09-04  6:40 UTC|newest]

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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49AB4ACB9627B8468F29D589A27B745588AA0250@ORSMSX121.amr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox