* [edk2-platforms PATCH v5 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules
2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 2/7] SimicsIch10Pkg: Add Ich Pkg for SimicsIch10 David Wei
@ 2019-09-05 21:38 ` David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
To: devel
Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
Kubacki Michael A, Nate DeSimone, Michael D Kinney
Add modules Include, Library, SimicsDxe, SimicsPei, Policy, SmbiosPlatformDxe
and SecCore for Simics Quick Start Platform support
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: David Wei <david.y.wei@intel.com>
---
.../SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c | 647 ++++++++
.../Library/LoadLinuxLib/Linux.c | 662 +++++++++
.../Library/LoadLinuxLib/LinuxGdt.c | 175 +++
.../Library/NvVarsFileLib/FsAccess.c | 507 +++++++
.../Library/NvVarsFileLib/NvVarsFileLib.c | 77 +
.../Library/PciHostBridgeLib/PciHostBridgeLib.c | 419 ++++++
.../SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c | 100 ++
.../Library/PeiReportFvLib/PeiReportFvLib.c | 119 ++
.../Library/PlatformBootManagerLib/BdsPlatform.c | 1553 ++++++++++++++++++++
.../Library/PlatformBootManagerLib/PlatformData.c | 35 +
.../SerializeVariablesLib/SerializeVariablesLib.c | 869 +++++++++++
.../SiliconPolicyInitLib/SiliconPolicyInitLib.c | 108 ++
.../SiliconPolicyUpdateLib.c | 70 +
.../Intel/SimicsOpenBoardPkg/SecCore/SecMain.c | 956 ++++++++++++
.../Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c | 865 +++++++++++
.../SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c | 124 ++
Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c | 57 +
.../SimicsOpenBoardPkg/SimicsPei/FeatureControl.c | 115 ++
.../Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c | 568 +++++++
.../Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c | 630 ++++++++
.../SmbiosPlatformDxe/SmbiosPlatformDxe.c | 148 ++
.../Include/Guid/SimicsBoardConfig.h | 18 +
.../Include/IndustryStandard/I440FxPiix4.h | 50 +
.../Include/IndustryStandard/LinuxBzImage.h | 159 ++
.../Include/Library/LoadLinuxLib.h | 205 +++
.../Include/Library/SerializeVariablesLib.h | 224 +++
.../SimicsOpenBoardPkg/Include/SimicsPlatforms.h | 55 +
.../Library/DxeLogoLib/DxeLogoLib.inf | 55 +
.../Library/DxeLogoLib/OemBadging.h | 83 ++
.../Library/LoadLinuxLib/DxeLoadLinuxLib.inf | 42 +
.../Library/LoadLinuxLib/Ia32/JumpToKernel.nasm | 41 +
.../Library/LoadLinuxLib/LoadLinuxLib.h | 52 +
.../Library/LoadLinuxLib/X64/JumpToKernel.nasm | 85 ++
.../Library/NvVarsFileLib/NvVarsFileLib.h | 55 +
.../Library/NvVarsFileLib/NvVarsFileLib.inf | 53 +
.../Library/PciHostBridgeLib/PciHostBridge.h | 68 +
.../Library/PciHostBridgeLib/PciHostBridgeLib.inf | 51 +
.../Library/PeiReportFvLib/PeiReportFvLib.inf | 56 +
.../Library/PlatformBootManagerLib/BdsPlatform.h | 172 +++
.../PlatformBootManagerLib.inf | 72 +
.../SerializeVariablesLib/SerializeVariablesLib.h | 33 +
.../SerializeVariablesLib.inf | 36 +
.../SiliconPolicyInitLib/SiliconPolicyInitLib.inf | 38 +
.../SiliconPolicyUpdateLib.inf | 35 +
.../SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm | 45 +
.../Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf | 73 +
.../SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm | 45 +
.../Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h | 38 +
.../SimicsOpenBoardPkg/SimicsDxe/Platform.uni | 31 +
.../SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h | 52 +
.../SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr | 67 +
.../SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf | 65 +
Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h | 50 +
.../Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h | 88 ++
.../SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf | 104 ++
.../SmbiosPlatformDxe/SmbiosPlatformDxe.h | 38 +
.../SmbiosPlatformDxe/SmbiosPlatformDxe.inf | 51 +
57 files changed, 11289 insertions(+)
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
new file mode 100644
index 0000000000..48a718a90d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/Logo.c
@@ -0,0 +1,647 @@
+/** @file
+ BDS Lib functions which contain all the code to connect console device
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+#include <Protocol/SimpleTextOut.h>
+#include <OemBadging.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UgaDraw.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#include <IndustryStandard/Bmp.h>
+#include <Protocol/BootLogo.h>
+
+/**
+ Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+ buffer is passed in it will be used if it is big enough.
+
+ @param BmpImage Pointer to BMP file
+ @param BmpImageSize Number of bytes in BmpImage
+ @param GopBlt Buffer containing GOP version of BmpImage.
+ @param GopBltSize Size of GopBlt in bytes.
+ @param PixelHeight Height of GopBlt/BmpImage in pixels
+ @param PixelWidth Width of GopBlt/BmpImage in pixels
+
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
+ @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
+ GopBltSize will contain the required size.
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
+
+**/
+EFI_STATUS
+ConvertBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT VOID **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINT64 BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ UINT32 DataSizePerLine;
+ BOOLEAN IsAllocated;
+ UINT32 ColorMapNum;
+
+ if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Doesn't support compress.
+ //
+ if (BmpHeader->CompressionType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Only support BITMAPINFOHEADER format.
+ // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
+ //
+ if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // The data size in each line must be 4 byte alignment.
+ //
+ DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
+ BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
+ if (BltBufferSize > (UINT32) ~0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BmpHeader->Size != BmpImageSize) ||
+ (BmpHeader->Size < BmpHeader->ImageOffset) ||
+ (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+ if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ ColorMapNum = 2;
+ break;
+ case 4:
+ ColorMapNum = 16;
+ break;
+ case 8:
+ ColorMapNum = 256;
+ break;
+ default:
+ ColorMapNum = 0;
+ break;
+ }
+ //
+ // BMP file may has padding data between the bmp header section and the bmp data section.
+ //
+ if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ //
+ // Calculate the BltBuffer needed size.
+ //
+ BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
+ //
+ // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+ BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ //
+ // GopBlt is not allocated by caller.
+ //
+ *GopBltSize = (UINTN) BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // GopBlt has been allocated by caller.
+ //
+ if (*GopBltSize < (UINTN) BltBufferSize) {
+ *GopBltSize = (UINTN) BltBufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+
+ //
+ // Convert image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Convert 1-bit (2 colors) BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt--;
+ Width--;
+ break;
+
+ case 4:
+ //
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+ break;
+
+ case 8:
+ //
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ //
+ // It is 24-bit BMP.
+ //
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ default:
+ //
+ // Other bit format BMP is not supported.
+ //
+ if (IsAllocated) {
+ FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+ return EFI_UNSUPPORTED;
+ break;
+ };
+
+ }
+
+ ImageIndex = (UINTN) (Image - ImageHeader);
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Use SystemTable Conout to stop video based Simple Text Out consoles from going
+ to the video device. Put up LogoFile on every video device that is a console.
+
+ @param[in] LogoFile File name of logo to display on the center of the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
+ @retval EFI_UNSUPPORTED Logo not found
+
+**/
+EFI_STATUS
+EFIAPI
+EnableBootLogo (
+ IN EFI_GUID *LogoFile
+ )
+{
+ EFI_STATUS Status;
+ EFI_OEM_BADGING_PROTOCOL *Badging;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ INTN DestX;
+ INTN DestY;
+ UINT8 *ImageData;
+ UINTN ImageSize;
+ UINTN BltSize;
+ UINT32 Instance;
+ EFI_BADGING_FORMAT Format;
+ EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN Height;
+ UINTN Width;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_BOOT_LOGO_PROTOCOL *BootLogo;
+ UINTN NumberOfLogos;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
+ UINTN LogoDestX;
+ UINTN LogoDestY;
+ UINTN LogoHeight;
+ UINTN LogoWidth;
+ UINTN NewDestX;
+ UINTN NewDestY;
+ UINTN NewHeight;
+ UINTN NewWidth;
+ UINT64 BufferSize;
+
+ UgaDraw = NULL;
+ //
+ // Try to open GOP first
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ GraphicsOutput = NULL;
+ //
+ // Open GOP failed, try to open UGA
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Try to open Boot Logo Protocol.
+ //
+ BootLogo = NULL;
+ gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
+
+ //
+ // Erase Cursor from screen
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ Badging = NULL;
+ Status = gBS->LocateProtocol (&gEfiOemBadgingProtocolGuid, NULL, (VOID **) &Badging);
+
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ Blt = NULL;
+ NumberOfLogos = 0;
+ LogoDestX = 0;
+ LogoDestY = 0;
+ LogoHeight = 0;
+ LogoWidth = 0;
+ NewDestX = 0;
+ NewDestY = 0;
+ NewHeight = 0;
+ NewWidth = 0;
+ Instance = 0;
+ while (1) {
+ ImageData = NULL;
+ ImageSize = 0;
+
+ if (Badging != NULL) {
+ //
+ // Get image from OEMBadging protocol.
+ //
+ Status = Badging->GetImage (
+ Badging,
+ &Instance,
+ &Format,
+ &ImageData,
+ &ImageSize,
+ &Attribute,
+ &CoordinateX,
+ &CoordinateY
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ } else {
+ //
+ // Get the specified image from FV.
+ //
+ Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CoordinateX = 0;
+ CoordinateY = 0;
+ Attribute = EfiBadgingDisplayAttributeCenter;
+ }
+
+ if (Blt != NULL) {
+ FreePool (Blt);
+ }
+
+ //
+ // Try BMP decoder
+ //
+ Blt = NULL;
+ Status = ConvertBmpToGopBlt (
+ ImageData,
+ ImageSize,
+ (VOID **) &Blt,
+ &BltSize,
+ &Height,
+ &Width
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (ImageData);
+
+ if (Badging == NULL) {
+ return Status;
+ } else {
+ continue;
+ }
+ }
+
+ //
+ // Calculate the display position according to Attribute.
+ //
+ switch (Attribute) {
+ case EfiBadgingDisplayAttributeLeftTop:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+
+ case EfiBadgingDisplayAttributeCenterTop:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = CoordinateY;
+ break;
+
+ case EfiBadgingDisplayAttributeRightTop:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = CoordinateY;;
+ break;
+
+ case EfiBadgingDisplayAttributeCenterRight:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ case EfiBadgingDisplayAttributeRightBottom:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeCenterBottom:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeLeftBottom:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeCenterLeft:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ case EfiBadgingDisplayAttributeCenter:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ default:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+ }
+
+ if ((DestX >= 0) && (DestY >= 0)) {
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) Blt,
+ EfiUgaBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ //
+ // Report displayed Logo information.
+ //
+ if (!EFI_ERROR (Status)) {
+ NumberOfLogos++;
+
+ if (LogoWidth == 0) {
+ //
+ // The first Logo.
+ //
+ LogoDestX = (UINTN) DestX;
+ LogoDestY = (UINTN) DestY;
+ LogoWidth = Width;
+ LogoHeight = Height;
+ } else {
+ //
+ // Merge new logo with old one.
+ //
+ NewDestX = MIN ((UINTN) DestX, LogoDestX);
+ NewDestY = MIN ((UINTN) DestY, LogoDestY);
+ NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;
+ NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;
+
+ LogoDestX = NewDestX;
+ LogoDestY = NewDestY;
+ LogoWidth = NewWidth;
+ LogoHeight = NewHeight;
+ }
+ }
+ }
+
+ FreePool (ImageData);
+
+ if (Badging == NULL) {
+ break;
+ }
+ }
+
+Done:
+ if (BootLogo == NULL || NumberOfLogos == 0) {
+ //
+ // No logo displayed.
+ //
+ if (Blt != NULL) {
+ FreePool (Blt);
+ }
+
+ return Status;
+ }
+
+ //
+ // Advertise displayed Logo information.
+ //
+ if (NumberOfLogos == 1) {
+ //
+ // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
+ //
+ LogoBlt = Blt;
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
+ //
+ if (Blt != NULL) {
+ FreePool (Blt);
+ }
+
+ //
+ // Ensure the LogoHeight * LogoWidth doesn't overflow
+ //
+ if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+ BufferSize = MultU64x64 (LogoWidth, LogoHeight);
+
+ //
+ // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
+ //
+ if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (LogoBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ LogoBlt,
+ EfiBltVideoToBltBuffer,
+ LogoDestX,
+ LogoDestY,
+ 0,
+ 0,
+ LogoWidth,
+ LogoHeight,
+ LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) LogoBlt,
+ EfiUgaVideoToBltBuffer,
+ LogoDestX,
+ LogoDestY,
+ 0,
+ 0,
+ LogoWidth,
+ LogoHeight,
+ LogoWidth * sizeof (EFI_UGA_PIXEL)
+ );
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);
+ }
+ FreePool (LogoBlt);
+
+ return Status;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
new file mode 100644
index 0000000000..631bb7ee69
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Linux.c
@@ -0,0 +1,662 @@
+/** @file
+ Copyright (c) 2011 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "LoadLinuxLib.h"
+
+
+/**
+ A simple check of the kernel setup image
+
+ An assumption is made that the size of the data is at least the
+ size of struct boot_params.
+
+ @param[in] KernelSetup - The kernel setup image
+
+ @retval EFI_SUCCESS - The kernel setup looks valid and supported
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The kernel setup is not valid or supported
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BasicKernelSetupCheck (
+ IN VOID *KernelSetup
+ )
+{
+ return LoadLinuxCheckKernelSetup(KernelSetup, sizeof (struct boot_params));
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxCheckKernelSetup (
+ IN VOID *KernelSetup,
+ IN UINTN KernelSetupSize
+ )
+{
+ struct boot_params *Bp;
+
+ if (KernelSetup == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (KernelSetupSize < sizeof (*Bp)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ if ((Bp->hdr.signature != 0xAA55) || // Check boot sector signature
+ (Bp->hdr.header != SETUP_HDR) ||
+ (Bp->hdr.version < 0x205) || // We only support relocatable kernels
+ (!Bp->hdr.relocatable_kernel)
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+
+UINTN
+EFIAPI
+LoadLinuxGetKernelSize (
+ IN VOID *KernelSetup,
+ IN UINTN KernelSize
+ )
+{
+ struct boot_params *Bp;
+
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+ return 0;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ if (Bp->hdr.version > 0x20a) {
+ return Bp->hdr.init_size;
+ } else {
+ //
+ // Add extra size for kernel decompression
+ //
+ return 3 * KernelSize;
+ }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelSetupPages (
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ Address = BASE_1GB;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ Pages,
+ &Address
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) Address;
+ } else {
+ return NULL;
+ }
+}
+
+EFI_STATUS
+EFIAPI
+LoadLinuxInitializeKernelSetup (
+ IN VOID *KernelSetup
+ )
+{
+ EFI_STATUS Status;
+ UINTN SetupEnd;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ SetupEnd = 0x202 + (Bp->hdr.jump & 0xff);
+
+ //
+ // Clear all but the setup_header
+ //
+ ZeroMem (KernelSetup, 0x1f1);
+ ZeroMem (((UINT8 *)KernelSetup) + SetupEnd, 4096 - SetupEnd);
+ DEBUG ((EFI_D_INFO, "Cleared kernel setup 0-0x1f1, 0x%Lx-0x1000\n",
+ (UINT64)SetupEnd));
+
+ return EFI_SUCCESS;
+}
+
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelPages (
+ IN VOID *KernelSetup,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS KernelAddress;
+ UINT32 Loop;
+ struct boot_params *Bp;
+
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+ return NULL;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ for (Loop = 1; Loop < 512; Loop++) {
+ KernelAddress = MultU64x32 (
+ 2 * Bp->hdr.kernel_alignment,
+ Loop
+ );
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ EfiLoaderData,
+ Pages,
+ &KernelAddress
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) KernelAddress;
+ }
+ }
+
+ return NULL;
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateCommandLinePages (
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ Address = 0xa0000;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ Pages,
+ &Address
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) Address;
+ } else {
+ return NULL;
+ }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateInitrdPages (
+ IN VOID *KernelSetup,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ struct boot_params *Bp;
+
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+ return NULL;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Bp->hdr.ramdisk_max;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ Pages,
+ &Address
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) Address;
+ } else {
+ return NULL;
+ }
+}
+
+
+STATIC
+VOID
+SetupLinuxMemmap (
+ IN OUT struct boot_params *Bp
+ )
+{
+ EFI_STATUS Status;
+ UINT8 TmpMemoryMap[1];
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;
+ UINTN Index;
+ struct efi_info *Efi;
+ struct e820_entry *LastE820;
+ struct e820_entry *E820;
+ UINTN E820EntryCount;
+ EFI_PHYSICAL_ADDRESS LastEndAddr;
+
+ //
+ // Get System MemoryMapSize
+ //
+ MemoryMapSize = sizeof (TmpMemoryMap);
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ //
+ // Enlarge space here, because we will allocate pool now.
+ //
+ MemoryMapSize += EFI_PAGE_SIZE;
+ Status = gBS->AllocatePool (
+ EfiLoaderData,
+ MemoryMapSize,
+ (VOID **) &MemoryMap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get System MemoryMap
+ //
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ LastE820 = NULL;
+ E820 = &Bp->e820_map[0];
+ E820EntryCount = 0;
+ LastEndAddr = 0;
+ MemoryMapPtr = MemoryMap;
+ for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {
+ UINTN E820Type = 0;
+
+ if (MemoryMap->NumberOfPages == 0) {
+ continue;
+ }
+
+ switch(MemoryMap->Type) {
+ case EfiReservedMemoryType:
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ case EfiMemoryMappedIO:
+ case EfiMemoryMappedIOPortSpace:
+ case EfiPalCode:
+ E820Type = E820_RESERVED;
+ break;
+
+ case EfiUnusableMemory:
+ E820Type = E820_UNUSABLE;
+ break;
+
+ case EfiACPIReclaimMemory:
+ E820Type = E820_ACPI;
+ break;
+
+ case EfiLoaderCode:
+ case EfiLoaderData:
+ case EfiBootServicesCode:
+ case EfiBootServicesData:
+ case EfiConventionalMemory:
+ E820Type = E820_RAM;
+ break;
+
+ case EfiACPIMemoryNVS:
+ E820Type = E820_NVS;
+ break;
+
+ default:
+ DEBUG ((
+ EFI_D_ERROR,
+ "Invalid EFI memory descriptor type (0x%x)!\n",
+ MemoryMap->Type
+ ));
+ continue;
+ }
+
+ if ((LastE820 != NULL) &&
+ (LastE820->type == (UINT32) E820Type) &&
+ (MemoryMap->PhysicalStart == LastEndAddr)) {
+ LastE820->size += EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
+ LastEndAddr += EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
+ } else {
+ if (E820EntryCount >= (sizeof (Bp->e820_map) / sizeof (Bp->e820_map[0]))) {
+ break;
+ }
+ E820->type = (UINT32) E820Type;
+ E820->addr = MemoryMap->PhysicalStart;
+ E820->size = EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
+ LastE820 = E820;
+ LastEndAddr = E820->addr + E820->size;
+ E820++;
+ E820EntryCount++;
+ }
+
+ //
+ // Get next item
+ //
+ MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);
+ }
+ Bp->e820_entries = (UINT8) E820EntryCount;
+
+ Efi = &Bp->efi_info;
+ Efi->efi_systab = (UINT32)(UINTN) gST;
+ Efi->efi_memdesc_size = (UINT32) DescriptorSize;
+ Efi->efi_memdesc_version = DescriptorVersion;
+ Efi->efi_memmap = (UINT32)(UINTN) MemoryMapPtr;
+ Efi->efi_memmap_size = (UINT32) MemoryMapSize;
+#ifdef MDE_CPU_IA32
+ Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '3', '2');
+#else
+ Efi->efi_systab_hi = (UINT32) (((UINT64)(UINTN) gST) >> 32);
+ Efi->efi_memmap_hi = (UINT32) (((UINT64)(UINTN) MemoryMapPtr) >> 32);
+ Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '6', '4');
+#endif
+
+ gBS->ExitBootServices (gImageHandle, MapKey);
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxSetCommandLine (
+ IN OUT VOID *KernelSetup,
+ IN CHAR8 *CommandLine
+ )
+{
+ EFI_STATUS Status;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ Bp->hdr.cmd_line_ptr = (UINT32)(UINTN) CommandLine;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxSetInitrd (
+ IN OUT VOID *KernelSetup,
+ IN VOID *Initrd,
+ IN UINTN InitrdSize
+ )
+{
+ EFI_STATUS Status;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;
+ Bp->hdr.ramdisk_len = (UINT32) InitrdSize;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC VOID
+FindBits (
+ unsigned long Mask,
+ UINT8 *Pos,
+ UINT8 *Size
+ )
+{
+ UINT8 First, Len;
+
+ First = 0;
+ Len = 0;
+
+ if (Mask) {
+ while (!(Mask & 0x1)) {
+ Mask = Mask >> 1;
+ First++;
+ }
+
+ while (Mask & 0x1) {
+ Mask = Mask >> 1;
+ Len++;
+ }
+ }
+ *Pos = First;
+ *Size = Len;
+}
+
+
+STATIC
+EFI_STATUS
+SetupGraphicsFromGop (
+ struct screen_info *Si,
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
+ )
+{
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_STATUS Status;
+ UINTN Size;
+
+ Status = Gop->QueryMode(Gop, Gop->Mode->Mode, &Size, &Info);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ /* We found a GOP */
+
+ /* EFI framebuffer */
+ Si->orig_video_isVGA = 0x70;
+
+ Si->orig_x = 0;
+ Si->orig_y = 0;
+ Si->orig_video_page = 0;
+ Si->orig_video_mode = 0;
+ Si->orig_video_cols = 0;
+ Si->orig_video_lines = 0;
+ Si->orig_video_ega_bx = 0;
+ Si->orig_video_points = 0;
+
+ Si->lfb_base = (UINT32) Gop->Mode->FrameBufferBase;
+ Si->lfb_size = (UINT32) Gop->Mode->FrameBufferSize;
+ Si->lfb_width = (UINT16) Info->HorizontalResolution;
+ Si->lfb_height = (UINT16) Info->VerticalResolution;
+ Si->pages = 1;
+ Si->vesapm_seg = 0;
+ Si->vesapm_off = 0;
+
+ if (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
+ Si->lfb_depth = 32;
+ Si->red_size = 8;
+ Si->red_pos = 0;
+ Si->green_size = 8;
+ Si->green_pos = 8;
+ Si->blue_size = 8;
+ Si->blue_pos = 16;
+ Si->rsvd_size = 8;
+ Si->rsvd_pos = 24;
+ Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
+
+ } else if (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
+ Si->lfb_depth = 32;
+ Si->red_size = 8;
+ Si->red_pos = 16;
+ Si->green_size = 8;
+ Si->green_pos = 8;
+ Si->blue_size = 8;
+ Si->blue_pos = 0;
+ Si->rsvd_size = 8;
+ Si->rsvd_pos = 24;
+ Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
+ } else if (Info->PixelFormat == PixelBitMask) {
+ FindBits(Info->PixelInformation.RedMask,
+ &Si->red_pos, &Si->red_size);
+ FindBits(Info->PixelInformation.GreenMask,
+ &Si->green_pos, &Si->green_size);
+ FindBits(Info->PixelInformation.BlueMask,
+ &Si->blue_pos, &Si->blue_size);
+ FindBits(Info->PixelInformation.ReservedMask,
+ &Si->rsvd_pos, &Si->rsvd_size);
+ Si->lfb_depth = Si->red_size + Si->green_size +
+ Si->blue_size + Si->rsvd_size;
+ Si->lfb_linelength = (UINT16) ((Info->PixelsPerScanLine * Si->lfb_depth) / 8);
+ } else {
+ Si->lfb_depth = 4;
+ Si->red_size = 0;
+ Si->red_pos = 0;
+ Si->green_size = 0;
+ Si->green_pos = 0;
+ Si->blue_size = 0;
+ Si->blue_pos = 0;
+ Si->rsvd_size = 0;
+ Si->rsvd_pos = 0;
+ Si->lfb_linelength = Si->lfb_width / 2;
+ }
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+SetupGraphics (
+ IN OUT struct boot_params *Bp
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+ ZeroMem ((VOID*)&Bp->screen_info, sizeof(Bp->screen_info));
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID*) &Gop
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = SetupGraphicsFromGop (&Bp->screen_info, Gop);
+ if (!EFI_ERROR (Status)) {
+ FreePool (HandleBuffer);
+ return EFI_SUCCESS;
+ }
+ }
+
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+STATIC
+EFI_STATUS
+SetupLinuxBootParams (
+ IN OUT struct boot_params *Bp
+ )
+{
+ SetupGraphics (Bp);
+
+ SetupLinuxMemmap (Bp);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinux (
+ IN VOID *Kernel,
+ IN OUT VOID *KernelSetup
+ )
+{
+ EFI_STATUS Status;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params *) KernelSetup;
+
+ if (Bp->hdr.version < 0x205 || !Bp->hdr.relocatable_kernel) {
+ //
+ // We only support relocatable kernels
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ InitLinuxDescriptorTables ();
+
+ Bp->hdr.code32_start = (UINT32)(UINTN) Kernel;
+ if (Bp->hdr.version >= 0x20c && Bp->hdr.handover_offset &&
+ (Bp->hdr.xloadflags & (sizeof (UINTN) == 4 ? BIT2 : BIT3))) {
+ DEBUG ((EFI_D_INFO, "Jumping to kernel EFI handover point at ofs %x\n", Bp->hdr.handover_offset));
+
+ DisableInterrupts ();
+ JumpToUefiKernel ((VOID*) gImageHandle, (VOID*) gST, KernelSetup, Kernel);
+ }
+
+ //
+ // Old kernels without EFI handover protocol
+ //
+ SetupLinuxBootParams (KernelSetup);
+
+ DEBUG ((EFI_D_INFO, "Jumping to kernel\n"));
+ DisableInterrupts ();
+ SetLinuxDescriptorTables ();
+ JumpToKernel (Kernel, (VOID*) KernelSetup);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
new file mode 100644
index 0000000000..fda185e3d7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LinuxGdt.c
@@ -0,0 +1,175 @@
+/** @file
+ Initialize GDT for Linux.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "LoadLinuxLib.h"
+
+
+//
+// Local structure definitions
+//
+
+#pragma pack (1)
+
+//
+// Global Descriptor Entry structures
+//
+
+typedef struct _GDT_ENTRY {
+ UINT16 Limit15_0;
+ UINT16 Base15_0;
+ UINT8 Base23_16;
+ UINT8 Type;
+ UINT8 Limit19_16_and_flags;
+ UINT8 Base31_24;
+} GDT_ENTRY;
+
+typedef
+struct _GDT_ENTRIES {
+ GDT_ENTRY Null;
+ GDT_ENTRY Null2;
+ GDT_ENTRY Linear;
+ GDT_ENTRY LinearCode;
+ GDT_ENTRY TaskSegment;
+ GDT_ENTRY Spare4;
+ GDT_ENTRY Spare5;
+} GDT_ENTRIES;
+
+#pragma pack ()
+
+STATIC GDT_ENTRIES *mGdt = NULL;
+
+//
+// Global descriptor table (GDT) Template
+//
+STATIC GDT_ENTRIES GdtTemplate = {
+ //
+ // Null
+ //
+ {
+ 0x0, // limit 15:0
+ 0x0, // base 15:0
+ 0x0, // base 23:16
+ 0x0, // type
+ 0x0, // limit 19:16, flags
+ 0x0, // base 31:24
+ },
+ //
+ // Null2
+ //
+ {
+ 0x0, // limit 15:0
+ 0x0, // base 15:0
+ 0x0, // base 23:16
+ 0x0, // type
+ 0x0, // limit 19:16, flags
+ 0x0, // base 31:24
+ },
+ //
+ // Linear
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09A, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // LinearCode
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x092, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // TaskSegment
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x089, // ?
+ 0x080, // ?
+ 0x0,
+ },
+ //
+ // Spare4
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // Spare5
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+};
+
+/**
+ Initialize Global Descriptor Table.
+
+**/
+VOID
+InitLinuxDescriptorTables (
+ VOID
+ )
+{
+ //
+ // Allocate Runtime Data for the GDT
+ //
+ mGdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+ ASSERT (mGdt != NULL);
+ mGdt = ALIGN_POINTER (mGdt, 8);
+
+ //
+ // Initialize all GDT entries
+ //
+ CopyMem (mGdt, &GdtTemplate, sizeof (GdtTemplate));
+
+}
+
+/**
+ Initialize Global Descriptor Table.
+
+**/
+VOID
+SetLinuxDescriptorTables (
+ VOID
+ )
+{
+ IA32_DESCRIPTOR GdtPtr;
+ IA32_DESCRIPTOR IdtPtr;
+
+ //
+ // Write GDT register
+ //
+ GdtPtr.Base = (UINT32)(UINTN)(VOID*) mGdt;
+ GdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
+ AsmWriteGdtr (&GdtPtr);
+
+ IdtPtr.Base = (UINT32) 0;
+ IdtPtr.Limit = (UINT16) 0;
+ AsmWriteIdtr (&IdtPtr);
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
new file mode 100644
index 0000000000..3d98291410
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/FsAccess.c
@@ -0,0 +1,507 @@
+/** @file
+ File System Access for NvVarsFileLib
+
+ Copyright (c) 2004 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "NvVarsFileLib.h"
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+
+/**
+ Open the NvVars file for reading or writing
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+ @param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing
+ @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
+ with the opened NvVars file.
+
+ @return EFI_SUCCESS if the file was opened
+
+**/
+EFI_STATUS
+GetNvVarsFile (
+ IN EFI_HANDLE FsHandle,
+ IN BOOLEAN ReadingFile,
+ OUT EFI_FILE_HANDLE *NvVarsFile
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+ EFI_FILE_HANDLE Root;
+
+ //
+ // Get the FileSystem protocol on that handle
+ //
+ Status = gBS->HandleProtocol (
+ FsHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **)&Fs
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the volume (the root directory)
+ //
+ Status = Fs->OpenVolume (Fs, &Root);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Attempt to open the NvVars file in the root directory
+ //
+ Status = Root->Open (
+ Root,
+ NvVarsFile,
+ L"NvVars",
+ ReadingFile ?
+ EFI_FILE_MODE_READ :
+ (
+ EFI_FILE_MODE_CREATE |
+ EFI_FILE_MODE_READ |
+ EFI_FILE_MODE_WRITE
+ ),
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ Open the NvVars file for reading or writing
+
+ @param[in] File - The file to inspect
+ @param[out] Exists - Returns whether the file exists
+ @param[out] Size - Returns the size of the file
+ (0 if the file does not exist)
+
+**/
+VOID
+NvVarsFileReadCheckup (
+ IN EFI_FILE_HANDLE File,
+ OUT BOOLEAN *Exists,
+ OUT UINTN *Size
+ )
+{
+ EFI_FILE_INFO *FileInfo;
+
+ *Exists = FALSE;
+ *Size = 0;
+
+ FileInfo = FileHandleGetInfo (File);
+ if (FileInfo == NULL) {
+ return;
+ }
+
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
+ FreePool (FileInfo);
+ return;
+ }
+
+ *Exists = TRUE;
+ *Size = (UINTN) FileInfo->FileSize;
+
+ FreePool (FileInfo);
+}
+
+
+/**
+ Open the NvVars file for reading or writing
+
+ @param[in] File - The file to inspect
+ @param[out] Exists - Returns whether the file exists
+ @param[out] Size - Returns the size of the file
+ (0 if the file does not exist)
+
+**/
+EFI_STATUS
+FileHandleEmpty (
+ IN EFI_FILE_HANDLE File
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+
+ //
+ // Retrieve the FileInfo structure
+ //
+ FileInfo = FileHandleGetInfo (File);
+ if (FileInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If the path is a directory, then return an error
+ //
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
+ FreePool (FileInfo);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If the file size is already 0, then it is empty, so
+ // we can return success.
+ //
+ if (FileInfo->FileSize == 0) {
+ FreePool (FileInfo);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Set the file size to 0.
+ //
+ FileInfo->FileSize = 0;
+ Status = FileHandleSetInfo (File, FileInfo);
+
+ FreePool (FileInfo);
+
+ return Status;
+}
+
+
+/**
+ Reads a file to a newly allocated buffer
+
+ @param[in] File - The file to read
+ @param[in] ReadSize - The size of data to read from the file
+
+ @return Pointer to buffer allocated to hold the file
+ contents. NULL if an error occurred.
+
+**/
+VOID*
+FileHandleReadToNewBuffer (
+ IN EFI_FILE_HANDLE FileHandle,
+ IN UINTN ReadSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN ActualReadSize;
+ VOID *FileContents;
+
+ ActualReadSize = ReadSize;
+ FileContents = AllocatePool (ReadSize);
+ if (FileContents != NULL) {
+ Status = FileHandleRead (
+ FileHandle,
+ &ReadSize,
+ FileContents
+ );
+ if (EFI_ERROR (Status) || (ActualReadSize != ReadSize)) {
+ FreePool (FileContents);
+ return NULL;
+ }
+ }
+
+ return FileContents;
+}
+
+
+/**
+ Reads the contents of the NvVars file on the file system
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of the file read
+
+**/
+EFI_STATUS
+ReadNvVarsFile (
+ IN EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE File;
+ UINTN FileSize;
+ BOOLEAN FileExists;
+ VOID *FileContents;
+ EFI_HANDLE SerializedVariables;
+
+ Status = GetNvVarsFile (FsHandle, TRUE, &File);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "FsAccess.c: Could not open NV Variables file on this file system\n"));
+ return Status;
+ }
+
+ NvVarsFileReadCheckup (File, &FileExists, &FileSize);
+ if (FileSize == 0) {
+ FileHandleClose (File);
+ return EFI_UNSUPPORTED;
+ }
+
+ FileContents = FileHandleReadToNewBuffer (File, FileSize);
+ if (FileContents == NULL) {
+ FileHandleClose (File);
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((
+ EFI_D_INFO,
+ "FsAccess.c: Read %Lu bytes from NV Variables file\n",
+ (UINT64)FileSize
+ ));
+
+ Status = SerializeVariablesNewInstanceFromBuffer (
+ &SerializedVariables,
+ FileContents,
+ FileSize
+ );
+ if (!RETURN_ERROR (Status)) {
+ Status = SerializeVariablesSetSerializedVariables (SerializedVariables);
+ }
+
+ FreePool (FileContents);
+ FileHandleClose (File);
+
+ return Status;
+}
+
+
+/**
+ Writes a variable to indicate that the NV variables
+ have been loaded from the file system.
+
+**/
+STATIC
+VOID
+SetNvVarsVariable (
+ VOID
+ )
+{
+ BOOLEAN VarData;
+ UINTN Size;
+
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ Size = sizeof (VarData);
+ VarData = TRUE;
+ gRT->SetVariable (
+ L"NvVars",
+ &gEfiSimpleFileSystemProtocolGuid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID*) &VarData
+ );
+}
+
+
+/**
+ Loads the non-volatile variables from the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+LoadNvVarsFromFs (
+ EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN VarData;
+ UINTN Size;
+
+ DEBUG ((EFI_D_INFO, "FsAccess.c: LoadNvVarsFromFs\n"));
+
+ //
+ // We write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading.
+ //
+ // This is relevant if the non-volatile variable have been
+ // able to survive a reboot operation. In that case, we don't
+ // want to re-load the file as it would overwrite newer changes
+ // made to the variables.
+ //
+ Size = sizeof (VarData);
+ VarData = TRUE;
+ Status = gRT->GetVariable (
+ L"NvVars",
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &Size,
+ (VOID*) &VarData
+ );
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "NV Variables were already loaded\n"));
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Attempt to restore the variables from the NvVars file.
+ //
+ Status = ReadNvVarsFile (FsHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Error while restoring NV variable data\n"));
+ return Status;
+ }
+
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ SetNvVarsVariable();
+
+ DEBUG ((
+ EFI_D_INFO,
+ "FsAccess.c: Read NV Variables file (size=%Lu)\n",
+ (UINT64)Size
+ ));
+
+ return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackAddAllNvVariables (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_HANDLE Instance;
+
+ Instance = (EFI_HANDLE) Context;
+
+ //
+ // Only save non-volatile variables
+ //
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ return RETURN_SUCCESS;
+ }
+
+ return SerializeVariablesAddVariable (
+ Instance,
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+}
+
+
+/**
+ Saves the non-volatile variables into the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+SaveNvVarsToFs (
+ EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE File;
+ UINTN WriteSize;
+ UINTN VariableDataSize;
+ VOID *VariableData;
+ EFI_HANDLE SerializedVariables;
+
+ SerializedVariables = NULL;
+
+ Status = SerializeVariablesNewInstance (&SerializedVariables);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SerializeVariablesIterateSystemVariables (
+ IterateVariablesCallbackAddAllNvVariables,
+ (VOID*) SerializedVariables
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VariableData = NULL;
+ VariableDataSize = 0;
+ Status = SerializeVariablesToBuffer (
+ SerializedVariables,
+ NULL,
+ &VariableDataSize
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ VariableData = AllocatePool (VariableDataSize);
+ if (VariableData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = SerializeVariablesToBuffer (
+ SerializedVariables,
+ VariableData,
+ &VariableDataSize
+ );
+ }
+ }
+
+ SerializeVariablesFreeInstance (SerializedVariables);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the NvVars file for writing.
+ //
+ Status = GetNvVarsFile (FsHandle, FALSE, &File);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "FsAccess.c: Unable to open file to saved NV Variables\n"));
+ return Status;
+ }
+
+ //
+ // Empty the starting file contents.
+ //
+ Status = FileHandleEmpty (File);
+ if (EFI_ERROR (Status)) {
+ FileHandleClose (File);
+ return Status;
+ }
+
+ WriteSize = VariableDataSize;
+ Status = FileHandleWrite (File, &WriteSize, VariableData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileHandleClose (File);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ SetNvVarsVariable();
+
+ DEBUG ((EFI_D_INFO, "Saved NV Variables to NvVars file\n"));
+ }
+
+ return Status;
+}
+
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
new file mode 100644
index 0000000000..2e9618455d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.c
@@ -0,0 +1,77 @@
+/** @file
+ Save Non-Volatile Variables to a file system.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "NvVarsFileLib.h"
+#include <Library/DebugLib.h>
+#include <Library/NvVarsFileLib.h>
+
+EFI_HANDLE mNvVarsFileLibFsHandle = NULL;
+
+
+/**
+ Attempts to connect the NvVarsFileLib to the specified file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return The EFI_STATUS while attempting to connect the NvVarsFileLib
+ to the file system instance.
+ @retval EFI_SUCCESS - The given file system was connected successfully
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectNvVarsToFileSystem (
+ IN EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // We might fail to load the variable, since the file system initially
+ // will not have the NvVars file.
+ //
+ LoadNvVarsFromFs (FsHandle);
+
+ //
+ // We must be able to save the variables successfully to the file system
+ // to have connected successfully.
+ //
+ Status = SaveNvVarsToFs (FsHandle);
+ if (!EFI_ERROR (Status)) {
+ mNvVarsFileLibFsHandle = FsHandle;
+ }
+
+ return Status;
+}
+
+
+/**
+ Update non-volatile variables stored on the file system.
+
+ @return The EFI_STATUS while attempting to update the variable on
+ the connected file system.
+ @retval EFI_SUCCESS - The non-volatile variables were saved to the disk
+ @retval EFI_NOT_STARTED - A file system has not been connected
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateNvVarsOnFileSystem (
+ )
+{
+ if (mNvVarsFileLibFsHandle == NULL) {
+ //
+ // A file system had not been connected to the library.
+ //
+ return EFI_NOT_STARTED;
+ } else {
+ return SaveNvVarsToFs (mNvVarsFileLibFsHandle);
+ }
+}
+
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
new file mode 100644
index 0000000000..3b71c8ae97
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -0,0 +1,419 @@
+/** @file
+ SIMICS QSP's instance of the PCI Host Bridge Library.
+
+ Copyright (C) 2016, Red Hat, Inc.
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <Register/X58Ich10.h>
+
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Library/PciLib.h>
+#include "PciHostBridge.h"
+
+
+#pragma pack(1)
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+ L"Mem", L"I/O", L"Bus"
+};
+
+
+STATIC
+CONST
+OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A03), // HID
+ 0 // UID
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
+
+/**
+ Initialize a PCI_ROOT_BRIDGE structure.
+
+ @param[in] Supports Supported attributes.
+
+ @param[in] Attributes Initial attributes.
+
+ @param[in] AllocAttributes Allocation attributes.
+
+ @param[in] RootBusNumber The bus number to store in RootBus.
+
+ @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
+ assigned to any subordinate bus found behind any
+ PCI bridge hanging off this root bus.
+
+ The caller is repsonsible for ensuring that
+ RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then the
+ root bus has no room for subordinate buses.
+
+ @param[in] Io IO aperture.
+
+ @param[in] Mem MMIO aperture.
+
+ @param[in] MemAbove4G MMIO aperture above 4G.
+
+ @param[in] PMem Prefetchable MMIO aperture.
+
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
+
+ @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the
+ caller) that should be filled in by this
+ function.
+
+ @retval EFI_SUCCESS Initialization successful. A device path
+ consisting of an ACPI device path node, with
+ UID = RootBusNumber, has been allocated and
+ linked into RootBus.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+**/
+EFI_STATUS
+InitRootBridge (
+ IN UINT64 Supports,
+ IN UINT64 Attributes,
+ IN UINT64 AllocAttributes,
+ IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
+ IN PCI_ROOT_BRIDGE_APERTURE *Io,
+ IN PCI_ROOT_BRIDGE_APERTURE *Mem,
+ IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMem,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
+ OUT PCI_ROOT_BRIDGE *RootBus
+ )
+{
+ OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
+
+ //
+ // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
+ //
+ ZeroMem (RootBus, sizeof *RootBus);
+
+ RootBus->Segment = 0;
+
+ RootBus->Supports = Supports;
+ RootBus->Attributes = Attributes;
+
+ RootBus->DmaAbove4G = FALSE;
+
+ RootBus->AllocationAttributes = AllocAttributes;
+ RootBus->Bus.Base = RootBusNumber;
+ RootBus->Bus.Limit = MaxSubBusNumber;
+ CopyMem (&RootBus->Io, Io, sizeof (*Io));
+ CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
+ CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
+ CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
+ CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
+
+ RootBus->NoExtendedConfigSpace = (PcdGet16 (PcdSimicsX58HostBridgePciDevId) !=
+ INTEL_ICH10_DEVICE_ID);
+
+ DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
+ &mRootBridgeDevicePathTemplate);
+ if (DevicePath == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DevicePath->AcpiDevicePath.UID = RootBusNumber;
+ RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
+
+ DEBUG ((EFI_D_INFO,
+ "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
+ __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().
+
+ param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
+ initialized with InitRootBridge(), that should be
+ uninitialized. This function doesn't free RootBus.
+**/
+STATIC
+VOID
+UninitRootBridge (
+ IN PCI_ROOT_BRIDGE *RootBus
+ )
+{
+ FreePool (RootBus->DevicePath);
+}
+
+
+/**
+ Return all the root bridge instances in an array.
+
+ @param Count Return the count of root bridge instances.
+
+ @return All the root bridge instances in an array.
+ The array should be passed into PciHostBridgeFreeRootBridges()
+ when it's not used.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeGetRootBridges (
+ UINTN *Count
+ )
+{
+ EFI_STATUS Status;
+ UINT64 ExtraRootBridges;
+ PCI_ROOT_BRIDGE *Bridges;
+ UINTN Initialized;
+ UINTN LastRootBridgeNumber;
+ UINTN RootBridgeNumber;
+ UINT64 Attributes;
+ UINT64 AllocationAttributes;
+ PCI_ROOT_BRIDGE_APERTURE Io;
+ PCI_ROOT_BRIDGE_APERTURE Mem;
+ PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
+
+ ZeroMem (&Io, sizeof (Io));
+ ZeroMem (&Mem, sizeof (Mem));
+ ZeroMem (&MemAbove4G, sizeof (MemAbove4G));
+
+ Attributes = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
+ EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 |
+ EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY |
+ EFI_PCI_ATTRIBUTE_VGA_IO_16 |
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
+
+ AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;
+ if (PcdGet64 (PcdPciMmio64Size) > 0) {
+ AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
+ MemAbove4G.Base = PcdGet64 (PcdPciMmio64Base);
+ MemAbove4G.Limit = PcdGet64 (PcdPciMmio64Base) +
+ PcdGet64 (PcdPciMmio64Size) - 1;
+ } else {
+ CopyMem (&MemAbove4G, &mNonExistAperture, sizeof (mNonExistAperture));
+ }
+
+ Io.Base = PcdGet64 (PcdPciIoBase);
+ Io.Limit = PcdGet64 (PcdPciIoBase) + (PcdGet64 (PcdPciIoSize) - 1);
+ Mem.Base = PcdGet64 (PcdPciMmio32Base);
+ Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);
+
+ *Count = 0;
+ ExtraRootBridges = 0;
+
+ //
+ // Allocate the "main" root bridge, and any extra root bridges.
+ //
+ Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
+ if (Bridges == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
+ return NULL;
+ }
+ Initialized = 0;
+
+ //
+ // The "main" root bus is always there.
+ //
+ LastRootBridgeNumber = 0;
+
+ //
+ // Scan all other root buses. If function 0 of any device on a bus returns a
+ // VendorId register value different from all-bits-one, then that bus is
+ // alive.
+ //
+ for (RootBridgeNumber = 1;
+ RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;
+ ++RootBridgeNumber) {
+ UINTN Device;
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
+ if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
+ PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
+ break;
+ }
+ }
+ if (Device <= PCI_MAX_DEVICE) {
+ //
+ // Found the next root bus. We can now install the *previous* one,
+ // because now we know how big a bus number range *that* one has, for any
+ // subordinate buses that might exist behind PCI bridges hanging off it.
+ //
+ Status = InitRootBridge (
+ Attributes,
+ Attributes,
+ AllocationAttributes,
+ (UINT8) LastRootBridgeNumber,
+ (UINT8) (RootBridgeNumber - 1),
+ &Io,
+ &Mem,
+ &MemAbove4G,
+ &mNonExistAperture,
+ &mNonExistAperture,
+ &Bridges[Initialized]
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeBridges;
+ }
+ ++Initialized;
+ LastRootBridgeNumber = RootBridgeNumber;
+ }
+ }
+
+ //
+ // Install the last root bus (which might be the only, ie. main, root bus, if
+ // we've found no extra root buses).
+ //
+ Status = InitRootBridge (
+ Attributes,
+ Attributes,
+ AllocationAttributes,
+ (UINT8) LastRootBridgeNumber,
+ PCI_MAX_BUS,
+ &Io,
+ &Mem,
+ &MemAbove4G,
+ &mNonExistAperture,
+ &mNonExistAperture,
+ &Bridges[Initialized]
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeBridges;
+ }
+ ++Initialized;
+
+ *Count = Initialized;
+ return Bridges;
+
+FreeBridges:
+ while (Initialized > 0) {
+ --Initialized;
+ UninitRootBridge (&Bridges[Initialized]);
+ }
+
+ FreePool (Bridges);
+ return NULL;
+}
+
+
+/**
+ Free the root bridge instances array returned from
+ PciHostBridgeGetRootBridges().
+
+ @param The root bridge instances array.
+ @param The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeFreeRootBridges (
+ PCI_ROOT_BRIDGE *Bridges,
+ UINTN Count
+ )
+{
+ if (Bridges == NULL && Count == 0) {
+ return;
+ }
+ ASSERT (Bridges != NULL && Count > 0);
+
+ do {
+ --Count;
+ UninitRootBridge (&Bridges[Count]);
+ } while (Count > 0);
+
+ FreePool (Bridges);
+}
+
+
+/**
+ Inform the platform that the resource conflict happens.
+
+ @param HostBridgeHandle Handle of the Host Bridge.
+ @param Configuration Pointer to PCI I/O and PCI memory resource
+ descriptors. The Configuration contains the resources
+ for all the root bridges. The resource for each root
+ bridge is terminated with END descriptor and an
+ additional END is appended indicating the end of the
+ entire resources. The resource descriptor field
+ values follow the description in
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ .SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeResourceConflict (
+ EFI_HANDLE HostBridgeHandle,
+ VOID *Configuration
+ )
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+ UINTN RootBridgeIndex;
+ DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
+
+ RootBridgeIndex = 0;
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+ while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
+ for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
+ ASSERT (Descriptor->ResType <
+ (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
+ sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
+ )
+ );
+ DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
+ mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
+ Descriptor->AddrLen, Descriptor->AddrRangeMax
+ ));
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((EFI_D_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
+ Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
+ ((Descriptor->SpecificFlag &
+ EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
+ ) != 0) ? L" (Prefetchable)" : L""
+ ));
+ }
+ }
+ //
+ // Skip the END descriptor for root bridge
+ //
+ ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
+ (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
+ );
+ }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
new file mode 100644
index 0000000000..4e3762465a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/Fv.c
@@ -0,0 +1,100 @@
+/** @file
+ Build FV related hobs for platform.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PiPei.h"
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+BOOLEAN mS3Supported = TRUE;
+
+/**
+ Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+ and DXE know about them.
+
+ @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.
+
+**/
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ )
+{
+ BOOLEAN SecureS3Needed;
+
+ DEBUG ((EFI_D_INFO, "Platform PEI Firmware Volume Initialization\n"));
+
+ DEBUG (
+ (EFI_D_ERROR, "Firmware Volume HOB: 0x%x 0x%x\n",
+ PcdGet32 (PcdSimicsPeiMemFvBase),
+ PcdGet32 (PcdSimicsPeiMemFvSize)
+ )
+ );
+ //
+ // Create a memory allocation HOB for the PEI FV.
+ //
+ // Allocate as ACPI NVS is S3 is supported
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdSimicsPeiMemFvBase),
+ PcdGet32 (PcdSimicsPeiMemFvSize),
+ mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+
+ //
+ // Let DXE know about the DXE FV
+ //
+ BuildFvHob (PcdGet32 (PcdSimicsDxeMemFvBase), PcdGet32 (PcdSimicsDxeMemFvSize));
+
+ SecureS3Needed = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire);
+
+ //
+ // Create a memory allocation HOB for the DXE FV.
+ //
+ // If "secure" S3 is needed, then SEC will decompress both PEI and DXE
+ // firmware volumes at S3 resume too, hence we need to keep away the OS from
+ // DXEFV as well. Otherwise we only need to keep away DXE itself from the
+ // DXEFV area.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdSimicsDxeMemFvBase),
+ PcdGet32 (PcdSimicsDxeMemFvSize),
+ SecureS3Needed ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+
+ //
+ // Additionally, said decompression will use temporary memory above the end
+ // of DXEFV, so let's keep away the OS from there too.
+ //
+ if (SecureS3Needed) {
+ UINT32 DxeMemFvEnd;
+
+ DxeMemFvEnd = PcdGet32 (PcdSimicsDxeMemFvBase) +
+ PcdGet32 (PcdSimicsDxeMemFvSize);
+ BuildMemoryAllocationHob (
+ DxeMemFvEnd,
+ PcdGet32 (PcdSimicsDecompressionScratchEnd) - DxeMemFvEnd,
+ EfiACPIMemoryNVS
+ );
+ }
+
+ //
+ // Let PEI know about the DXE FV so it can find the DXE Core
+ //
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ (VOID *)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBase),
+ PcdGet32 (PcdSimicsDxeMemFvSize),
+ NULL,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
new file mode 100644
index 0000000000..bb5a060b8e
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.c
@@ -0,0 +1,119 @@
+/** @file
+ Source code file for Report Firmware Volume (FV) library
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ReportFvLib.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Library/IoLib.h>
+#include <Register/X58Ich10.h>
+
+EFI_STATUS
+PeiFvInitialization(
+ VOID
+);
+
+VOID
+ReportPreMemFv (
+ VOID
+ )
+{
+ if (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) != 0x5) { // not S3 resume
+ PeiFvInitialization();
+ }
+
+ DEBUG ((DEBUG_INFO, "Install FlashFvSecurity - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvSecurityBase), PcdGet32 (PcdFlashFvSecuritySize)));
+ PeiServicesInstallFvInfo2Ppi (
+ &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvSecurityBase))->FileSystemGuid),
+ (VOID *) (UINTN) PcdGet32 (PcdFlashFvSecurityBase),
+ PcdGet32 (PcdFlashFvSecuritySize),
+ NULL,
+ NULL,
+ 0
+ );
+ DEBUG ((DEBUG_INFO, "Install FlashFvAdvanced - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvAdvancedBase), PcdGet32 (PcdFlashFvAdvancedSize)));
+ PeiServicesInstallFvInfo2Ppi (
+ &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvAdvancedBase))->FileSystemGuid),
+ (VOID *) (UINTN) PcdGet32 (PcdFlashFvAdvancedBase),
+ PcdGet32 (PcdFlashFvAdvancedSize),
+ NULL,
+ NULL,
+ 0
+ );
+}
+
+VOID
+ReportPostMemFv (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Build HOB for DXE
+ ///
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ ///
+ /// Prepare the recovery service
+ ///
+ } else {
+ DEBUG ((DEBUG_INFO, "Install FlashFvPostMemory - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvPostMemoryBase), PcdGet32 (PcdFlashFvPostMemorySize)));
+ PeiServicesInstallFvInfo2Ppi (
+ &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvPostMemoryBase))->FileSystemGuid),
+ (VOID *) (UINTN) PcdGet32 (PcdFlashFvPostMemoryBase),
+ PcdGet32 (PcdFlashFvPostMemorySize),
+ NULL,
+ NULL,
+ 0
+ );
+ DEBUG ((DEBUG_INFO, "Install FlashFvUefiBoot - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvUefiBootBase), PcdGet32 (PcdFlashFvUefiBootSize)));
+ PeiServicesInstallFvInfo2Ppi (
+ &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvUefiBootBase))->FileSystemGuid),
+ (VOID *) (UINTN) PcdGet32 (PcdFlashFvUefiBootBase),
+ PcdGet32 (PcdFlashFvUefiBootSize),
+ NULL,
+ NULL,
+ 0
+ );
+ DEBUG ((DEBUG_INFO, "Install FlashFvOsBoot - 0x%x, 0x%x\n", PcdGet32 (PcdFlashFvOsBootBase), PcdGet32 (PcdFlashFvOsBootSize)));
+ PeiServicesInstallFvInfo2Ppi (
+ &(((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFlashFvOsBootBase))->FileSystemGuid),
+ (VOID *) (UINTN) PcdGet32 (PcdFlashFvOsBootBase),
+ PcdGet32 (PcdFlashFvOsBootSize),
+ NULL,
+ NULL,
+ 0
+ );
+ }
+
+ //
+ // Report resource HOB for flash FV
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
+ (UINTN) PcdGet32 (PcdFlashAreaSize)
+ );
+ BuildMemoryAllocationHob (
+ (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
+ (UINTN) PcdGet32 (PcdFlashAreaSize),
+ EfiMemoryMappedIO
+ );
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
new file mode 100644
index 0000000000..117c72b35f
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1553 @@
+/** @file
+ Platform BDS customizations.
+
+ Copyright (c) 2004 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#define LEGACY_8259_MASK_REGISTER_MASTER 0x21
+#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1
+#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER 0x4D0
+#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE 0x4D1
+
+//
+// Global data
+//
+
+VOID *mEfiDevPathNotifyReg;
+EFI_EVENT mEfiDevPathEvent;
+VOID *mEmuVariableEventReg;
+EFI_EVENT mEmuVariableEvent;
+BOOLEAN mDetectVgaOnly;
+UINT16 mHostBridgeDevId;
+
+//
+// Table of host IRQs matching PCI IRQs A-D
+// (for configuring PCI Interrupt Line register)
+//
+CONST UINT8 PciHostIrqs[] = {
+ 0x0a, 0x0a, 0x0b, 0x0b
+};
+
+//
+// Type definitions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+/**
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ );
+
+
+//
+// Function prototypes
+//
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+VisitAllPciInstancesOfProtocol (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ );
+
+VOID
+InstallDevicePathCallback (
+ VOID
+ );
+
+VOID
+PlatformRegisterFvBootOption (
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ UINT32 Attributes
+ )
+{
+ EFI_STATUS Status;
+ INTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+ ASSERT (DevicePath != NULL);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ ASSERT (DevicePath != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &NewOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ Attributes,
+ Description,
+ DevicePath,
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DevicePath);
+
+ BootOptions = EfiBootManagerGetLoadOptions (
+ &BootOptionCount, LoadOptionTypeBoot
+ );
+
+ OptionIndex = EfiBootManagerFindLoadOption (
+ &NewOption, BootOptions, BootOptionCount
+ );
+
+ if (OptionIndex == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
+ ASSERT_EFI_ERROR (Status);
+ }
+ EfiBootManagerFreeLoadOption (&NewOption);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+/**
+ Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
+ whose device paths do not resolve exactly to an FvFile in the system.
+
+ This removes any boot options that point to binaries built into the firmware
+ and have become stale due to any of the following:
+ - DXEFV's base address or size changed (historical),
+ - DXEFV's FvNameGuid changed,
+ - the FILE_GUID of the pointed-to binary changed,
+ - the referenced binary is no longer built into the firmware.
+
+ EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
+ avoids exact duplicates.
+**/
+VOID
+RemoveStaleFvFileOptions (
+ VOID
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
+ LoadOptionTypeBoot);
+
+ for (Index = 0; Index < BootOptionCount; ++Index) {
+ EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+ EFI_STATUS Status;
+ EFI_HANDLE FvHandle;
+
+ //
+ // If the device path starts with neither MemoryMapped(...) nor Fv(...),
+ // then keep the boot option.
+ //
+ Node1 = BootOptions[Index].FilePath;
+ if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
+ !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+ continue;
+ }
+
+ //
+ // If the second device path node is not FvFile(...), then keep the boot
+ // option.
+ //
+ Node2 = NextDevicePathNode (Node1);
+ if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+ continue;
+ }
+
+ //
+ // Locate the Firmware Volume2 protocol instance that is denoted by the
+ // boot option. If this lookup fails (i.e., the boot option references a
+ // firmware volume that doesn't exist), then we'll proceed to delete the
+ // boot option.
+ //
+ SearchNode = Node1;
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
+ &SearchNode, &FvHandle);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // The firmware volume was found; now let's see if it contains the FvFile
+ // identified by GUID.
+ //
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+ UINTN BufferSize;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINT32 AuthenticationStatus;
+
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **)&FvProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
+ //
+ // Buffer==NULL means we request metadata only: BufferSize, FoundType,
+ // FileAttributes.
+ //
+ Status = FvProtocol->ReadFile (
+ FvProtocol,
+ &FvFileNode->FvFileName, // NameGuid
+ NULL, // Buffer
+ &BufferSize,
+ &FoundType,
+ &FileAttributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The FvFile was found. Keep the boot option.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Delete the boot option.
+ //
+ Status = EfiBootManagerDeleteLoadOptionVariable (
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ DEBUG_CODE (
+ CHAR16 *DevicePathString;
+
+ DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
+ FALSE, FALSE);
+ DEBUG ((
+ EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE,
+ "%a: removing stale Boot#%04x %s: %r\n",
+ __FUNCTION__,
+ (UINT32)BootOptions[Index].OptionNumber,
+ DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+ Status
+ ));
+ if (DevicePathString != NULL) {
+ FreePool (DevicePathString);
+ }
+ );
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+VOID
+PlatformRegisterOptionsAndKeys (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Enter;
+ EFI_INPUT_KEY F2;
+ EFI_INPUT_KEY Esc;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+
+ //
+ // Register ENTER as CONTINUE key
+ //
+ Enter.ScanCode = SCAN_NULL;
+ Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Map F2 to Boot Manager Menu
+ //
+ F2.ScanCode = SCAN_F2;
+ F2.UnicodeChar = CHAR_NULL;
+ Esc.ScanCode = SCAN_ESC;
+ Esc.UnicodeChar = CHAR_NULL;
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ ASSERT_EFI_ERROR (Status);
+ Status = EfiBootManagerAddKeyOptionVariable (
+ NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
+ );
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+ Status = EfiBootManagerAddKeyOptionVariable (
+ NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
+ );
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+STATIC
+VOID
+SaveS3BootScript (
+ VOID
+ );
+
+//
+// BDS Platform Functions
+//
+/**
+ Do the platform init, can be customized by OEM/IBV
+
+ Possible things that can be done in PlatformBootManagerBeforeConsole:
+
+ > Update console variable: 1. include hot-plug devices;
+ > 2. Clear ConIn and add SOL for AMT
+ > Register new Driver#### or Boot####
+ > Register new Key####: e.g.: F12
+ > Signal ReadyToLock event
+ > Authentication action: 1. connect Auth devices;
+ > 2. Identify auto logon user.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+// EFI_HANDLE Handle;
+// EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
+ InstallDevicePathCallback ();
+
+ VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
+ ConnectRootBridge, NULL);
+ //
+ // Enable LPC
+ //
+ PciOr16(POWER_MGMT_REGISTER_ICH10(0x04),
+ BIT0 | BIT1 | BIT2);
+ //
+ // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
+ // the preparation of S3 system information. That logic has a hard dependency
+ // on the presence of the FACS ACPI table. Since our ACPI tables are only
+ // installed after PCI enumeration completes, we must not trigger the S3 save
+ // earlier, hence we can't signal End-of-Dxe earlier.
+ //
+ EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+
+ PlatformInitializeConsole (gPlatformConsole);
+
+ PlatformRegisterOptionsAndKeys ();
+}
+
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make the PCI bus driver connect the root bridge, non-recursively. This
+ // will produce a number of child handles with PciIo on them.
+ //
+ Status = gBS->ConnectController (
+ RootBridgeHandle, // ControllerHandle
+ NULL, // DriverImageHandle
+ NULL, // RemainingDevicePath -- produce all
+ // children
+ FALSE // Recursive
+ );
+ return Status;
+}
+
+
+/**
+ Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the LPC Bridge device.
+
+ @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
+ ConOut, ConIn, and ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ CHAR16 *DevPathStr;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TempDevicePath = DevicePath;
+
+ //
+ // Register Keyboard
+ //
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+
+ //
+ // Register COM1
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 0;
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ EFI_D_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ //
+ // Register COM2
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 1;
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ EFI_D_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetGopDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE PciDeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
+ UINTN GopHandleCount;
+ EFI_HANDLE *GopHandleBuffer;
+
+ if (PciDevicePath == NULL || GopDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the GopDevicePath to be PciDevicePath
+ //
+ *GopDevicePath = PciDevicePath;
+ TempPciDevicePath = PciDevicePath;
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempPciDevicePath,
+ &PciDeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Try to connect this handle, so that GOP driver could start on this
+ // device and create child handles with GraphicsOutput Protocol installed
+ // on them, then we get device paths of these child handles and select
+ // them as possible console device.
+ //
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ &GopHandleCount,
+ &GopHandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add all the child handles as possible Console Device
+ //
+ for (Index = 0; Index < GopHandleCount; Index++) {
+ Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (CompareMem (
+ PciDevicePath,
+ TempDevicePath,
+ GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+ ) == 0) {
+ //
+ // In current implementation, we only enable one of the child handles
+ // as console device, i.e. sotre one of the child handle's device
+ // path to variable "ConOut"
+ // In future, we could select all child handles to be console device
+ //
+
+ *GopDevicePath = TempDevicePath;
+
+ //
+ // Delete the PCI device's path that added by
+ // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
+ //
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
+ }
+ }
+ gBS->FreePool (GopHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add PCI display to ConOut.
+
+ @param[in] DeviceHandle Handle of the PCI display device.
+
+ @retval EFI_SUCCESS The PCI display device has been added to ConOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciDisplayDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ DevicePath = NULL;
+ GopDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GetGopDevicePath (DevicePath, &GopDevicePath);
+ DevicePath = GopDevicePath;
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add PCI Serial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the PCI serial device.
+
+ @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
+ ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ VOID *Instance;
+
+ //
+ // Start to check all the PciIo to find all possible device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Id,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = (*CallBackFunction) (
+ HandleBuffer[Index],
+ Instance,
+ Context
+ );
+ }
+
+ gBS->FreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingAPciInstance (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+
+ //
+ // Check for all PCI device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
+ Handle,
+ PciIo,
+ &Pci
+ );
+
+}
+
+
+
+EFI_STATUS
+VisitAllPciInstances (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ )
+{
+ return VisitAllInstancesOfProtocol (
+ &gEfiPciIoProtocolGuid,
+ VisitingAPciInstance,
+ (VOID*)(UINTN) CallBackFunction
+ );
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to
+ ConOut, ConIn, ErrOut.
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update
+ successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!mDetectVgaOnly) {
+ //
+ // Here we decide whether it is LPC Bridge
+ //
+ if ((IS_PCI_LPC (Pci)) ||
+ ((IS_PCI_ISA_PDECODE (Pci)) &&
+ (Pci->Hdr.VendorId == 0x8086) &&
+ (Pci->Hdr.DeviceId == 0x7000)
+ )
+ ) {
+ //
+ // Add IsaKeyboard to ConIn,
+ // add IsaSerial to ConOut, ConIn, ErrOut
+ //
+ DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
+ PrepareLpcBridgeDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ //
+ // Here we decide which Serial device to enable in PCI bus
+ //
+ if (IS_PCI_16550SERIAL (Pci)) {
+ //
+ // Add them to ConOut, ConIn, ErrOut.
+ //
+ DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
+ PreparePciSerialDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Here we decide which display device to enable in PCI bus
+ //
+ if (IS_PCI_DISPLAY (Pci)) {
+ //
+ // Add them to ConOut.
+ //
+ DEBUG ((EFI_D_INFO, "Found PCI display device\n"));
+ PreparePciDisplayDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+
+ @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+DetectAndPreparePlatformPciDevicePaths (
+ BOOLEAN DetectVgaOnly
+ )
+{
+ mDetectVgaOnly = DetectVgaOnly;
+ return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+}
+
+/**
+ Connect the predefined platform default console device.
+
+ Always try to find and enable PCI display devices.
+
+ @param[in] PlatformConsole Predefined platform default console device array.
+**/
+VOID
+PlatformInitializeConsole (
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+{
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *VarConout;
+ EFI_DEVICE_PATH_PROTOCOL *VarConin;
+
+ //
+ // Connect RootBridge
+ //
+ GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
+ GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
+
+ if (VarConout == NULL || VarConin == NULL) {
+ //
+ // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+ //
+ DetectAndPreparePlatformPciDevicePaths (FALSE);
+ DetectAndPreparePlatformPciDevicePaths(TRUE);
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimue device group
+ // the platform should support
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+ //
+ // Update the console variable with the connect type
+ //
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+ } else {
+ //
+ // Only detect VGA device and add them to ConOut
+ //
+ DetectAndPreparePlatformPciDevicePaths (TRUE);
+ }
+}
+
+
+/**
+ Configure PCI Interrupt Line register for applicable devices
+ Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] PciHdr - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPciIntLine (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *PciHdr
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ UINTN RootSlot;
+ UINTN Idx;
+ UINT8 IrqLine;
+ EFI_STATUS Status;
+ UINT32 RootBusNumber;
+
+ Status = EFI_SUCCESS;
+
+ if (PciHdr->Device.InterruptPin != 0) {
+
+ DevPathNode = DevicePathFromHandle (Handle);
+ ASSERT (DevPathNode != NULL);
+ DevPath = DevPathNode;
+
+ RootBusNumber = 0;
+ if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == ACPI_DP &&
+ ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+ RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
+ }
+
+ //
+ // Compute index into PciHostIrqs[] table by walking
+ // the device path and adding up all device numbers
+ //
+ Status = EFI_NOT_FOUND;
+ RootSlot = 0;
+ Idx = PciHdr->Device.InterruptPin - 1;
+ while (!IsDevicePathEnd (DevPathNode)) {
+ if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == HW_PCI_DP) {
+
+ Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+
+ //
+ // Unlike SeaBIOS, which starts climbing from the leaf device
+ // up toward the root, we traverse the device path starting at
+ // the root moving toward the leaf node.
+ // The slot number of the top-level parent bridge is needed
+ // with more than 24 slots on the root bus.
+ //
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+ }
+ }
+
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RootBusNumber == 0 && RootSlot == 0) {
+ return Status; //bugbug: workaround; need SIMICS change B0/D0/F0 PCI_IntPin reg(0x3D) = 0X0
+// DEBUG((
+// EFI_D_ERROR,
+// "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
+// __FUNCTION__
+// ));
+// ASSERT (FALSE);
+ }
+
+ //
+ // Final PciHostIrqs[] index calculation depends on the platform
+ // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
+ //
+ switch (mHostBridgeDevId) {
+ case INTEL_82441_DEVICE_ID:
+ Idx -= 1;
+ break;
+ case INTEL_ICH10_DEVICE_ID:
+ //
+ // SeaBIOS contains the following comment:
+ // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
+ // with a different starting index.
+ //
+ // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
+ //
+ if (RootSlot > 24) {
+ //
+ // in this case, subtract back out RootSlot from Idx
+ // (SeaBIOS never adds it to begin with, but that would make our
+ // device path traversal loop above too awkward)
+ //
+ Idx -= RootSlot;
+ }
+ break;
+ default:
+ ASSERT (FALSE); // should never get here
+ }
+ Idx %= ARRAY_SIZE (PciHostIrqs);
+ IrqLine = PciHostIrqs[Idx];
+
+ DEBUG_CODE_BEGIN ();
+ {
+ CHAR16 *DevPathString;
+ STATIC CHAR16 Fallback[] = L"<failed to convert>";
+ UINTN Segment, Bus, Device, Function;
+
+ DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
+ if (DevPathString == NULL) {
+ DevPathString = Fallback;
+ }
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
+ (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
+ IrqLine));
+
+ if (DevPathString != Fallback) {
+ FreePool (DevPathString);
+ }
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
+ //
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_INT_LINE_OFFSET,
+ 1,
+ &IrqLine
+ );
+ }
+
+ return Status;
+}
+
+/**
+Write to mask and edge/level triggered registers of master and slave 8259 PICs.
+
+@param[in] Mask low byte for master PIC mask register,
+high byte for slave PIC mask register.
+@param[in] EdgeLevel low byte for master PIC edge/level triggered register,
+high byte for slave PIC edge/level triggered register.
+
+**/
+VOID
+Interrupt8259WriteMask(
+ IN UINT16 Mask,
+ IN UINT16 EdgeLevel
+)
+{
+ IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
+ IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
+ IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8)EdgeLevel);
+ IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8)(EdgeLevel >> 8));
+}
+
+VOID
+PciAcpiInitialization (
+ )
+{
+ UINTN Pmba;
+
+ //
+ // Query Host Bridge DID to determine platform type
+ //
+ mHostBridgeDevId = PcdGet16 (PcdSimicsX58HostBridgePciDevId);
+ switch (mHostBridgeDevId) {
+ case INTEL_82441_DEVICE_ID:
+ Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+ //
+ // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+ break;
+ case INTEL_ICH10_DEVICE_ID:
+ Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
+ //
+ // 00:1f.0 LPC Bridge LNK routing targets
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+ break;
+ default:
+ DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__, mHostBridgeDevId));
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
+ //
+ VisitAllPciInstances (SetPciIntLine);
+
+ //
+ // Set ACPI SCI_EN bit in PMCNTRL
+ //
+ IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
+ //
+ // Set all 8259 interrupts to edge triggered and disabled
+ //
+ Interrupt8259WriteMask(0xFFFF, 0x0000);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRecursivelyIfPciMassStorage (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *Instance,
+ IN PCI_TYPE00 *PciHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CHAR16 *DevPathStr;
+
+ //
+ // Recognize PCI Mass Storage
+ //
+ if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ EFI_D_INFO,
+ "Found Mass Storage device: %s\n",
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This notification function is invoked when the
+ EMU Variable FVB has been changed.
+
+ @param Event The event that occurred
+ @param Context For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+EmuVariablesUpdatedCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
+ UpdateNvVarsOnFileSystem ();
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingFileSystemInstance (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ STATIC BOOLEAN ConnectedToFileSystem = FALSE;
+
+ if (ConnectedToFileSystem) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = ConnectNvVarsToFileSystem (Handle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ConnectedToFileSystem = TRUE;
+ mEmuVariableEvent =
+ EfiCreateProtocolNotifyEvent (
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ EmuVariablesUpdatedCallback,
+ NULL,
+ &mEmuVariableEventReg
+ );
+ PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+PlatformBdsRestoreNvVarsFromHardDisk (
+ )
+{
+ VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
+ VisitAllInstancesOfProtocol (
+ &gEfiSimpleFileSystemProtocolGuid,
+ VisitingFileSystemInstance,
+ NULL
+ );
+
+}
+
+/**
+ Connect with predefined platform connect sequence.
+
+ The OEM/IBV can customize with their own connect sequence.
+**/
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+{
+ UINTN Index;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
+
+ Index = 0;
+
+ //
+ // Here we can get the customized platform connect sequence
+ // Notes: we can connect with new variable which record the
+ // last time boots connect device path sequence
+ //
+ while (gPlatformConnectSequence[Index] != NULL) {
+ //
+ // Build the platform boot option
+ //
+ EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
+ Index++;
+ }
+
+ //
+ // Just use the simple policy to connect all devices
+ //
+ DEBUG ((EFI_D_INFO, "EfiBootManagerConnectAll\n"));
+ EfiBootManagerConnectAll ();
+
+ PciAcpiInitialization ();
+}
+
+/**
+ Save the S3 boot script.
+
+ Note that DxeSmmReadyToLock must be signaled after this function returns;
+ otherwise the script wouldn't be saved actually.
+**/
+STATIC
+VOID
+SaveS3BootScript (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
+ STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+
+ Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
+ (VOID **) &BootScript);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Despite the opcode documentation in the PI spec, the protocol
+ // implementation embeds a deep copy of the info in the boot script, rather
+ // than storing just a pointer to runtime or NVS storage.
+ //
+ Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
+ (UINT32) sizeof Info,
+ (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+ Do the platform specific action after the console is ready
+
+ Possible things that can be done in PlatformBootManagerAfterConsole:
+
+ > Console post action:
+ > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
+ > Signal console ready platform customized event
+ > Run diagnostics like memory testing
+ > Connect certain devices
+ > Dispatch aditional option roms
+ > Special boot: e.g.: USB boot, enter UI
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+ VOID
+ )
+{
+ EFI_BOOT_MODE BootMode;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
+
+ //
+ // Prevent further changes to LockBoxes or SMRAM.
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface(&Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
+ DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
+ "from disk since flash variables appear to be supported.\n"));
+ } else {
+ //
+ // Try to restore variables from the hard disk early so
+ // they can be used for the other BDS connect operations.
+ //
+ PlatformBdsRestoreNvVarsFromHardDisk ();
+ }
+
+ //
+ // Get current Boot Mode
+ //
+ BootMode = GetBootModeHob ();
+ DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
+
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+ //
+ // Logo show
+ //
+ EnableBootLogo(PcdGetPtr(PcdLogoFile));
+
+ EfiBootManagerRefreshAllBootOption ();
+
+ //
+ // Register UEFI Shell
+ //
+ PlatformRegisterFvBootOption (
+ PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
+ );
+
+ RemoveStaleFvFileOptions ();
+}
+
+/**
+ This notification function is invoked when an instance of the
+ EFI_DEVICE_PATH_PROTOCOL is produced.
+
+ @param Event The event that occurred
+ @param Context For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+NotifyDevPath (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ ATAPI_DEVICE_PATH *Atapi;
+
+ //
+ // Examine all new handles
+ //
+ for (;;) {
+ //
+ // Get the next handle
+ //
+ BufferSize = sizeof (Handle);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mEfiDevPathNotifyReg,
+ &BufferSize,
+ &Handle
+ );
+
+ //
+ // If not found, we're done
+ //
+ if (EFI_NOT_FOUND == Status) {
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get the DevicePath protocol on that handle
+ //
+ Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
+ ASSERT_EFI_ERROR (Status);
+
+ while (!IsDevicePathEnd (DevPathNode)) {
+ //
+ // Find the handler to dump this device path node
+ //
+ if (
+ (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
+ (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
+ ) {
+ Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
+ PciOr16 (
+ PCI_LIB_ADDRESS (
+ 0,
+ 1,
+ 1,
+ (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
+ ),
+ BIT15
+ );
+ }
+
+ //
+ // Next device path node
+ //
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+ }
+
+ return;
+}
+
+
+VOID
+InstallDevicePathCallback (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
+ mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ NotifyDevPath,
+ NULL,
+ &mEfiDevPathNotifyReg
+ );
+}
+
+/**
+ This function is called each second during the boot manager waits the
+ timeout.
+
+ @param TimeoutRemain The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
+ UINT16 Timeout;
+
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+
+ Black.Raw = 0x00000000;
+ White.Raw = 0x00FFFFFF;
+
+ BootLogoUpdateProgress (
+ White.Pixel,
+ Black.Pixel,
+ L"Start boot option",
+ White.Pixel,
+ (Timeout - TimeoutRemain) * 100 / Timeout,
+ 0
+ );
+}
+
+/**
+ The function is called when no boot option could be launched,
+ including platform recovery options and options pointing to applications
+ built into firmware volumes.
+
+ If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+ VOID
+ )
+{
+ // BUGBUG- will do it if need
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100644
index 0000000000..768843a8bf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformData.c
@@ -0,0 +1,35 @@
+/** @file
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+ Copyright (c) 2004 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "BdsPlatform.h"
+
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH gUartDeviceNode = gUart;
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
+
+//
+// Platform specific keyboard device path
+//
+
+//
+// Predefined platform default console device path
+//
+PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ {
+ NULL,
+ 0
+ }
+};
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
new file mode 100644
index 0000000000..be619c838a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
@@ -0,0 +1,869 @@
+/** @file
+ Serialize Variables Library implementation
+
+ Copyright (c) 2004 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SerializeVariablesLib.h"
+
+/**
+ Serialization format:
+
+ The SerializeVariablesLib interface does not specify a format
+ for the serialization of the variable data. This library uses
+ a packed array of a non-uniformly sized data structure elements.
+
+ Each variable is stored (packed) as:
+ UINT32 VendorNameSize; // Name size in bytes
+ CHAR16 VendorName[?]; // The variable unicode name including the
+ // null terminating character.
+ EFI_GUID VendorGuid; // The variable GUID
+ UINT32 DataSize; // The size of variable data in bytes
+ UINT8 Data[?]; // The variable data
+
+**/
+
+
+/**
+ Unpacks the next variable from the buffer
+
+ @param[in] Buffer - Buffer pointing to the next variable instance
+ On subsequent calls, the pointer should be incremented
+ by the returned SizeUsed value.
+ @param[in] MaxSize - Max allowable size for the variable data
+ On subsequent calls, this should be decremented
+ by the returned SizeUsed value.
+ @param[out] Name - Variable name string (address in Buffer)
+ @param[out] NameSize - Size of Name in bytes
+ @param[out] Guid - GUID of variable (address in Buffer)
+ @param[out] Attributes - Attributes of variable
+ @param[out] Data - Buffer containing Data for variable (address in Buffer)
+ @param[out] DataSize - Size of Data in bytes
+ @param[out] SizeUsed - Total size used for this variable instance in Buffer
+
+ @return EFI_STATUS based on the success or failure of the operation
+
+**/
+STATIC
+EFI_STATUS
+UnpackVariableFromBuffer (
+ IN VOID *Buffer,
+ IN UINTN MaxSize,
+ OUT CHAR16 **Name,
+ OUT UINT32 *NameSize,
+ OUT EFI_GUID **Guid,
+ OUT UINT32 *Attributes,
+ OUT UINT32 *DataSize,
+ OUT VOID **Data,
+ OUT UINTN *SizeUsed
+ )
+{
+ UINT8 *BytePtr;
+ UINTN Offset;
+
+ BytePtr = (UINT8*)Buffer;
+ Offset = 0;
+
+ *NameSize = *(UINT32*) (BytePtr + Offset);
+ Offset = Offset + sizeof (UINT32);
+
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Name = (CHAR16*) (BytePtr + Offset);
+ Offset = Offset + *(UINT32*)BytePtr;
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Guid = (EFI_GUID*) (BytePtr + Offset);
+ Offset = Offset + sizeof (EFI_GUID);
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Attributes = *(UINT32*) (BytePtr + Offset);
+ Offset = Offset + sizeof (UINT32);
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DataSize = *(UINT32*) (BytePtr + Offset);
+ Offset = Offset + sizeof (UINT32);
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Data = (VOID*) (BytePtr + Offset);
+ Offset = Offset + *DataSize;
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *SizeUsed = Offset;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Iterates through the variables in the buffer, and calls a callback
+ function for each variable found.
+
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+ @param[in] Buffer - Buffer containing serialized variables
+ @param[in] MaxSize - Size of Buffer in bytes
+
+ @return EFI_STATUS based on the success or failure of the operation
+
+**/
+STATIC
+EFI_STATUS
+IterateVariablesInBuffer (
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *CallbackContext,
+ IN VOID *Buffer,
+ IN UINTN MaxSize
+ )
+{
+ RETURN_STATUS Status;
+ UINTN TotalSizeUsed;
+ UINTN SizeUsed;
+
+ CHAR16 *Name;
+ UINT32 NameSize;
+ CHAR16 *AlignedName;
+ UINT32 AlignedNameMaxSize;
+ EFI_GUID *Guid;
+ UINT32 Attributes;
+ UINT32 DataSize;
+ VOID *Data;
+
+ SizeUsed = 0;
+ AlignedName = NULL;
+ AlignedNameMaxSize = 0;
+ Name = NULL;
+ Guid = NULL;
+ Attributes = 0;
+ DataSize = 0;
+ Data = NULL;
+
+ for (
+ Status = EFI_SUCCESS, TotalSizeUsed = 0;
+ !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize);
+ ) {
+ Status = UnpackVariableFromBuffer (
+ (VOID*) ((UINT8*) Buffer + TotalSizeUsed),
+ (MaxSize - TotalSizeUsed),
+ &Name,
+ &NameSize,
+ &Guid,
+ &Attributes,
+ &DataSize,
+ &Data,
+ &SizeUsed
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // We copy the name to a separately allocated buffer,
+ // to be sure it is 16-bit aligned.
+ //
+ if (NameSize > AlignedNameMaxSize) {
+ if (AlignedName != NULL) {
+ FreePool (AlignedName);
+ }
+ AlignedName = AllocatePool (NameSize);
+ }
+ if (AlignedName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (AlignedName, Name, NameSize);
+
+ TotalSizeUsed = TotalSizeUsed + SizeUsed;
+
+ //
+ // Run the callback function
+ //
+ Status = (*CallbackFunction) (
+ CallbackContext,
+ AlignedName,
+ Guid,
+ Attributes,
+ DataSize,
+ Data
+ );
+
+ }
+
+ if (AlignedName != NULL) {
+ FreePool (AlignedName);
+ }
+
+ //
+ // Make sure the entire buffer was used, or else return an error
+ //
+ if (TotalSizeUsed != MaxSize) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "Deserialize variables error: TotalSizeUsed(%Lu) != MaxSize(%Lu)\n",
+ (UINT64)TotalSizeUsed,
+ (UINT64)MaxSize
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackNop (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackSetInInstance (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_HANDLE Instance;
+
+ Instance = (EFI_HANDLE) Context;
+
+ return SerializeVariablesAddVariable (
+ Instance,
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackSetSystemVariable (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_STATUS Status;
+ STATIC CONST UINT32 AuthMask =
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+ Status = gRT->SetVariable (
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+
+ if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) {
+ DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" "
+ "failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__,
+ VariableName));
+ Status = EFI_SUCCESS;
+ } else if (Status == EFI_WRITE_PROTECTED) {
+ DEBUG ((DEBUG_WARN, "%a: setting ReadOnly variable \"%s\" "
+ "failed with EFI_WRITE_PROTECTED, ignoring\n", __FUNCTION__,
+ VariableName));
+ Status = EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EnsureExtraBufferSpace (
+ IN SV_INSTANCE *Instance,
+ IN UINTN Size
+ )
+{
+ VOID *NewBuffer;
+ UINTN NewSize;
+
+ NewSize = Instance->DataSize + Size;
+ if (NewSize <= Instance->BufferSize) {
+ return RETURN_SUCCESS;
+ }
+
+ //
+ // Double the required size to lessen the need to re-allocate in the future
+ //
+ NewSize = 2 * NewSize;
+
+ NewBuffer = AllocatePool (NewSize);
+ if (NewBuffer == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ if (Instance->BufferPtr != NULL) {
+ CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize);
+ FreePool (Instance->BufferPtr);
+ }
+
+ Instance->BufferPtr = NewBuffer;
+ Instance->BufferSize = NewSize;
+
+ return RETURN_SUCCESS;
+}
+
+
+STATIC
+VOID
+AppendToBuffer (
+ IN SV_INSTANCE *Instance,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ UINTN NewSize;
+
+ ASSERT (Instance != NULL);
+ ASSERT (Data != NULL);
+
+ NewSize = Instance->DataSize + Size;
+ ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
+
+ CopyMem (
+ (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize),
+ Data,
+ Size
+ );
+
+ Instance->DataSize = NewSize;
+}
+
+
+/**
+ Creates a new variable serialization instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully created.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstance (
+ OUT EFI_HANDLE *Handle
+ )
+{
+ SV_INSTANCE *New;
+
+ New = AllocateZeroPool (sizeof (*New));
+ if (New == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ New->Signature = SV_SIGNATURE;
+
+ *Handle = (EFI_HANDLE) New;
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Free memory associated with a variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully freed.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesFreeInstance (
+ IN EFI_HANDLE Handle
+ )
+{
+ SV_INSTANCE *Instance;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if (Instance->Signature != SV_SIGNATURE) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Instance->Signature = 0;
+
+ if (Instance->BufferPtr != NULL) {
+ FreePool (Instance->BufferPtr);
+ }
+
+ FreePool (Instance);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Creates a new variable serialization instance using the given
+ binary representation of the variables to fill the new instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+ @param[in] Buffer - A buffer with the serialized representation
+ of the variables. Must be the same format as produced
+ by SerializeVariablesToBuffer.
+ @param[in] Size - This is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ imported into a new variable serialization instance
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the new variable serialization instance
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstanceFromBuffer (
+ OUT EFI_HANDLE *Handle,
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+{
+ RETURN_STATUS Status;
+
+ Status = SerializeVariablesNewInstance (Handle);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = IterateVariablesInBuffer (
+ IterateVariablesCallbackNop,
+ NULL,
+ Buffer,
+ Size
+ );
+ if (RETURN_ERROR (Status)) {
+ SerializeVariablesFreeInstance (*Handle);
+ return Status;
+ }
+
+ Status = IterateVariablesInBuffer (
+ IterateVariablesCallbackSetInInstance,
+ (VOID*) *Handle,
+ Buffer,
+ Size
+ );
+ if (RETURN_ERROR (Status)) {
+ SerializeVariablesFreeInstance (*Handle);
+ return Status;
+ }
+
+ return Status;
+}
+
+
+/**
+ Iterates all variables found with RuntimeServices GetNextVariableName
+
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateSystemVariables (
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ )
+{
+ RETURN_STATUS Status;
+ UINTN VariableNameBufferSize;
+ UINTN VariableNameSize;
+ CHAR16 *VariableName;
+ EFI_GUID VendorGuid;
+ UINTN VariableDataBufferSize;
+ UINTN VariableDataSize;
+ VOID *VariableData;
+ UINT32 VariableAttributes;
+ VOID *NewBuffer;
+
+ //
+ // Initialize the variable name and data buffer variables.
+ //
+ VariableNameBufferSize = sizeof (CHAR16);
+ VariableName = AllocateZeroPool (VariableNameBufferSize);
+
+ VariableDataBufferSize = 0;
+ VariableData = NULL;
+
+ for (;;) {
+ //
+ // Get the next variable name and guid
+ //
+ VariableNameSize = VariableNameBufferSize;
+ Status = gRT->GetNextVariableName (
+ &VariableNameSize,
+ VariableName,
+ &VendorGuid
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // The currently allocated VariableName buffer is too small,
+ // so we allocate a larger buffer, and copy the old buffer
+ // to it.
+ //
+ NewBuffer = AllocatePool (VariableNameSize);
+ if (NewBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
+ if (VariableName != NULL) {
+ FreePool (VariableName);
+ }
+ VariableName = NewBuffer;
+ VariableNameBufferSize = VariableNameSize;
+
+ //
+ // Try to get the next variable name again with the larger buffer.
+ //
+ Status = gRT->GetNextVariableName (
+ &VariableNameSize,
+ VariableName,
+ &VendorGuid
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+ break;
+ }
+
+ //
+ // Get the variable data and attributes
+ //
+ VariableDataSize = VariableDataBufferSize;
+ Status = gRT->GetVariable (
+ VariableName,
+ &VendorGuid,
+ &VariableAttributes,
+ &VariableDataSize,
+ VariableData
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // The currently allocated VariableData buffer is too small,
+ // so we allocate a larger buffer.
+ //
+ if (VariableDataBufferSize != 0) {
+ FreePool (VariableData);
+ VariableData = NULL;
+ VariableDataBufferSize = 0;
+ }
+ VariableData = AllocatePool (VariableDataSize);
+ if (VariableData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ VariableDataBufferSize = VariableDataSize;
+
+ //
+ // Try to read the variable again with the larger buffer.
+ //
+ Status = gRT->GetVariable (
+ VariableName,
+ &VendorGuid,
+ &VariableAttributes,
+ &VariableDataSize,
+ VariableData
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Run the callback function
+ //
+ Status = (*CallbackFunction) (
+ Context,
+ VariableName,
+ &VendorGuid,
+ VariableAttributes,
+ VariableDataSize,
+ VariableData
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ }
+
+ if (VariableName != NULL) {
+ FreePool (VariableName);
+ }
+
+ if (VariableData != NULL) {
+ FreePool (VariableData);
+ }
+
+ return Status;
+}
+
+
+/**
+ Iterates all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateInstanceVariables (
+ IN EFI_HANDLE Handle,
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ )
+{
+ SV_INSTANCE *Instance;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
+ return IterateVariablesInBuffer (
+ CallbackFunction,
+ Context,
+ Instance->BufferPtr,
+ Instance->DataSize
+ );
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+
+/**
+ Sets all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ set all the variables
+ @return Any of RETURN_ERROR indicates an error reading the variables
+ or in attempting to set a variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesSetSerializedVariables (
+ IN EFI_HANDLE Handle
+ )
+{
+ return SerializeVariablesIterateInstanceVariables (
+ Handle,
+ IterateVariablesCallbackSetSystemVariable,
+ NULL
+ );
+}
+
+
+/**
+ Adds a variable to the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] VariableName - Refer to RuntimeServices GetVariable
+ @param[in] VendorGuid - Refer to RuntimeServices GetVariable
+ @param[in] Attributes - Refer to RuntimeServices GetVariable
+ @param[in] DataSize - Refer to RuntimeServices GetVariable
+ @param[in] Data - Refer to RuntimeServices GetVariable
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ add the variable
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance or
+ VariableName, VariableGuid or Data are NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesAddVariable (
+ IN EFI_HANDLE Handle,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ RETURN_STATUS Status;
+ SV_INSTANCE *Instance;
+ UINT32 SerializedNameSize;
+ UINT32 SerializedDataSize;
+ UINTN SerializedSize;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if ((Instance->Signature != SV_SIGNATURE) ||
+ (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
+ }
+
+ SerializedNameSize = (UINT32) StrSize (VariableName);
+
+ SerializedSize =
+ sizeof (SerializedNameSize) +
+ SerializedNameSize +
+ sizeof (*VendorGuid) +
+ sizeof (Attributes) +
+ sizeof (SerializedDataSize) +
+ DataSize;
+
+ Status = EnsureExtraBufferSpace (
+ Instance,
+ SerializedSize
+ );
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Add name size (UINT32)
+ //
+ AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize));
+
+ //
+ // Add variable unicode name string
+ //
+ AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize);
+
+ //
+ // Add variable GUID
+ //
+ AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid));
+
+ //
+ // Add variable attributes
+ //
+ AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes));
+
+ //
+ // Add variable data size (UINT32)
+ //
+ SerializedDataSize = (UINT32) DataSize;
+ AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize));
+
+ //
+ // Add variable data
+ //
+ AppendToBuffer (Instance, Data, DataSize);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Serializes the variables known to this instance into the
+ provided buffer.
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[out] Buffer - A buffer to store the binary representation
+ of the variables.
+ @param[in,out] Size - On input this is the size of the buffer.
+ On output this is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ completed and returned in the buffer.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ save the variables to the buffer.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance or
+ Size or Buffer were NULL.
+ @retval RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by
+ the Size parameter was too small for the serialized
+ variable data. Size is returned with the required size.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesToBuffer (
+ IN EFI_HANDLE Handle,
+ OUT VOID *Buffer,
+ IN OUT UINTN *Size
+ )
+{
+ SV_INSTANCE *Instance;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if (Size == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (*Size < Instance->DataSize) {
+ *Size = Instance->DataSize;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ if (Buffer == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Size = Instance->DataSize;
+ CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
+
+ return RETURN_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
new file mode 100644
index 0000000000..383501898d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.c
@@ -0,0 +1,108 @@
+/** @file
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Performs silicon pre-mem policy initialization.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The returned data must be used as input data for SiliconPolicyDonePreMem(),
+ and SiliconPolicyUpdateLib.SiliconPolicyUpdatePreMem().
+
+ 1) In FSP path, the input Policy should be FspmUpd.
+ Value of FspmUpd has been initialized by FSP binary default value.
+ Only a subset of FspmUpd needs to be updated for different silicon sku.
+ The return data is same FspmUpd.
+
+ 2) In non-FSP path, the input policy could be NULL.
+ The return data is the initialized policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPreMem (
+ IN OUT VOID *Policy OPTIONAL
+ )
+{
+ return Policy;
+}
+
+/*
+ The silicon pre-mem policy is finalized.
+ Silicon code can do initialization based upon the policy data.
+
+ The input Policy must be returned by SiliconPolicyInitPreMem().
+
+ @param[in] Policy Pointer to policy.
+
+ @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+*/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePreMem (
+ IN VOID *Policy
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+/**
+ Performs silicon post-mem policy initialization.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The returned data must be used as input data for SiliconPolicyDonePostMem(),
+ and SiliconPolicyUpdateLib.SiliconPolicyUpdatePostMem().
+
+ 1) In FSP path, the input Policy should be FspsUpd.
+ Value of FspsUpd has been initialized by FSP binary default value.
+ Only a subset of FspsUpd needs to be updated for different silicon sku.
+ The return data is same FspsUpd.
+
+ 2) In non-FSP path, the input policy could be NULL.
+ The return data is the initialized policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the initialized policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyInitPostMem (
+ IN OUT VOID *Policy OPTIONAL
+ )
+{
+ return Policy;
+}
+
+/*
+ The silicon post-mem policy is finalized.
+ Silicon code can do initialization based upon the policy data.
+
+ The input Policy must be returned by SiliconPolicyInitPostMem().
+
+ @param[in] Policy Pointer to policy.
+
+ @retval RETURN_SUCCESS The policy is handled consumed by silicon code.
+*/
+RETURN_STATUS
+EFIAPI
+SiliconPolicyDonePostMem (
+ IN VOID *Policy
+ )
+{
+ return RETURN_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
new file mode 100644
index 0000000000..3b207a4e78
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.c
@@ -0,0 +1,70 @@
+/** @file
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/PeiServicesLib.h>
+
+/**
+ Performs silicon pre-mem policy update.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The input Policy must be returned by SiliconPolicyDonePreMem().
+
+ 1) In FSP path, the input Policy should be FspmUpd.
+ A platform may use this API to update the FSPM UPD policy initialized
+ by the silicon module or the default UPD data.
+ The output of FSPM UPD data from this API is the final UPD data.
+
+ 2) In non-FSP path, the board may use additional way to get
+ the silicon policy data field based upon the input Policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the updated policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyUpdatePreMem (
+ IN OUT VOID *Policy
+ )
+{
+ return Policy;
+}
+
+/**
+ Performs silicon post-mem policy update.
+
+ The meaning of Policy is defined by silicon code.
+ It could be the raw data, a handle, a PPI, etc.
+
+ The input Policy must be returned by SiliconPolicyDonePostMem().
+
+ 1) In FSP path, the input Policy should be FspsUpd.
+ A platform may use this API to update the FSPS UPD policy initialized
+ by the silicon module or the default UPD data.
+ The output of FSPS UPD data from this API is the final UPD data.
+
+ 2) In non-FSP path, the board may use additional way to get
+ the silicon policy data field based upon the input Policy.
+
+ @param[in, out] Policy Pointer to policy.
+
+ @return the updated policy.
+**/
+VOID *
+EFIAPI
+SiliconPolicyUpdatePostMem (
+ IN OUT VOID *Policy
+ )
+{
+ return Policy;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
new file mode 100644
index 0000000000..5cbb47687b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.c
@@ -0,0 +1,956 @@
+/** @file
+ Main SEC phase code. Transitions to PEI.
+
+ Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiCpuLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/ExtractGuidedSectionLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/PciCf8Lib.h>
+
+#include <Ppi/TemporaryRamSupport.h>
+#include <Register/X58Ich10.h>
+
+#define SEC_IDT_ENTRY_COUNT 34
+
+typedef struct _SEC_IDT_TABLE {
+ EFI_PEI_SERVICES *PeiService;
+ IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];
+} SEC_IDT_TABLE;
+
+VOID
+EFIAPI
+SecStartupPhase2 (
+ IN VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
+ TemporaryRamMigration
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamSupportPpiGuid,
+ &mTemporaryRamSupportPpi
+ },
+};
+
+//
+// Template of an IDT entry pointing to 10:FFFFFFE4h.
+//
+IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {
+ { // Bits
+ 0xffe4, // OffsetLow
+ 0x10, // Selector
+ 0x0, // Reserved_0
+ IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType
+ 0xffff // OffsetHigh
+ }
+};
+
+/**
+ Locates the main boot firmware volume.
+
+ @param[in,out] BootFv On input, the base of the BootFv
+ On output, the decompressed main firmware volume
+
+ @retval EFI_SUCCESS The main firmware volume was located and decompressed
+ @retval EFI_NOT_FOUND The main firmware volume was not found
+
+**/
+EFI_STATUS
+FindMainFv (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *Fv;
+ UINTN Distance;
+
+ ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);
+
+ Fv = *BootFv;
+ Distance = (UINTN) (*BootFv)->FvLength;
+ do {
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);
+ Distance += EFI_PAGE_SIZE;
+ if (Distance > SIZE_32MB) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Fv->Signature != EFI_FVH_SIGNATURE) {
+ continue;
+ }
+
+ if ((UINTN) Fv->FvLength > Distance) {
+ continue;
+ }
+
+ *BootFv = Fv;
+ return EFI_SUCCESS;
+
+ } while (TRUE);
+}
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ The Instance parameter indicates which instance of the section
+ type to return. (0 is first instance, 1 is second...)
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[in] Instance The section instance number
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInstance (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfSections;
+ EFI_COMMON_SECTION_HEADER *Section;
+ EFI_PHYSICAL_ADDRESS EndOfSection;
+
+ //
+ // Loop through the FFS file sections within the PEI Core FFS file
+ //
+ EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;
+ EndOfSections = EndOfSection + SizeOfSections;
+ for (;;) {
+ if (EndOfSection == EndOfSections) {
+ break;
+ }
+ CurrentAddress = (EndOfSection + 3) & ~(3ULL);
+ if (CurrentAddress >= EndOfSections) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
+ DEBUG ((EFI_D_VERBOSE, "Section->Type: 0x%x\n", Section->Type));
+
+ Size = SECTION_SIZE (Section);
+ if (Size < sizeof (*Section)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ EndOfSection = CurrentAddress + Size;
+ if (EndOfSection > EndOfSections) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // Look for the requested section type
+ //
+ if (Section->Type == SectionType) {
+ if (Instance == 0) {
+ *FoundSection = Section;
+ return EFI_SUCCESS;
+ } else {
+ Instance--;
+ }
+ }
+ DEBUG ((EFI_D_VERBOSE, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInSections (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ return FindFfsSectionInstance (
+ Sections,
+ SizeOfSections,
+ SectionType,
+ 0,
+ FoundSection
+ );
+}
+
+/**
+ Locates a FFS file with the specified file type and a section
+ within that file with the specified section type.
+
+ @param[in] Fv The firmware volume to search
+ @param[in] FileType The file type to locate
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsFileAndSection (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+
+ if (Fv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;
+ EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
+
+ //
+ // Loop through the FFS files in the Boot Firmware Volume
+ //
+ for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
+
+ CurrentAddress = (EndOfFile + 7) & ~(7ULL);
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
+ Size = *(UINT32*) File->Size & 0xffffff;
+ if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ DEBUG ((EFI_D_VERBOSE, "File->Type: 0x%x\n", File->Type));
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // Look for the request file type
+ //
+ if (File->Type != FileType) {
+ DEBUG ((EFI_D_VERBOSE, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));
+ continue;
+ }
+
+ Status = FindFfsSectionInSections (
+ (VOID*) (File + 1),
+ (UINTN) EndOfFile - (UINTN) (File + 1),
+ SectionType,
+ FoundSection
+ );
+ if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
+ return Status;
+ }
+ }
+}
+
+/**
+ Locates the compressed main firmware volume and decompresses it.
+
+ @param[in,out] Fv On input, the firmware volume to search
+ On output, the decompressed BOOT/PEI FV
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+DecompressMemFvs (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID_DEFINED_SECTION *Section;
+ UINT32 OutputBufferSize;
+ UINT32 ScratchBufferSize;
+ UINT16 SectionAttribute;
+ UINT32 AuthenticationStatus;
+ VOID *OutputBuffer;
+ VOID *ScratchBuffer;
+ EFI_COMMON_SECTION_HEADER *FvSection;
+ EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;
+ UINT32 FvHeaderSize;
+ UINT32 FvSectionSize;
+
+ FvSection = (EFI_COMMON_SECTION_HEADER*) NULL;
+
+ DEBUG ((EFI_D_VERBOSE, "Find and decompress FV image.\n"));
+ Status = FindFfsFileAndSection (
+ *Fv,
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
+ EFI_SECTION_GUID_DEFINED,
+ (EFI_COMMON_SECTION_HEADER**) &Section
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));
+ return Status;
+ }
+
+ Status = ExtractGuidedSectionGetInfo (
+ Section,
+ &OutputBufferSize,
+ &ScratchBufferSize,
+ &SectionAttribute
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));
+ return Status;
+ }
+
+ OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBase) + SIZE_1MB);
+ ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
+
+ DEBUG ((EFI_D_VERBOSE, "PcdSimicsDxeMemFvBase: 0x%x\n", PcdGet32 (PcdSimicsDxeMemFvBase)));
+ DEBUG ((EFI_D_VERBOSE, "OutputBuffer: 0x%x\n", OutputBuffer));
+ DEBUG ((EFI_D_VERBOSE, "OutputBufferSize: 0x%x\n", OutputBufferSize));
+ DEBUG ((EFI_D_VERBOSE, "ScratchBuffer: 0x%x\n", ScratchBuffer));
+ DEBUG ((EFI_D_VERBOSE, "ScratchBufferSize: 0x%x\n", ScratchBufferSize));
+ DEBUG ((EFI_D_VERBOSE, "PcdSimicsDecompressionScratchEnd: 0x%x\n", PcdGet32 (PcdSimicsDecompressionScratchEnd)));
+
+ DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
+ "PcdSimicsDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer,
+ OutputBufferSize, ScratchBuffer, ScratchBufferSize,
+ PcdGet32 (PcdSimicsDecompressionScratchEnd)));
+ ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize ==
+ PcdGet32 (PcdSimicsDecompressionScratchEnd));
+
+ Status = ExtractGuidedSectionDecode (
+ Section,
+ &OutputBuffer,
+ ScratchBuffer,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));
+ return Status;
+ }
+
+ Status = FindFfsSectionInstance (
+ OutputBuffer,
+ OutputBufferSize,
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+ 0,
+ &FvSection
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));
+ return Status;
+ }
+
+ ASSERT (SECTION_SIZE (FvSection) ==
+ (PcdGet32 (PcdSimicsPeiMemFvSize) + sizeof (*FvSection)));
+ ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+ PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsPeiMemFvBase);
+ CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdSimicsPeiMemFvSize));
+
+ if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));
+ CpuDeadLoop ();
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ Status = FindFfsSectionInstance (
+ OutputBuffer,
+ OutputBufferSize,
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+ 1,
+ &FvSection
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));
+ return Status;
+ }
+
+ ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+ if (IS_SECTION2 (FvSection)) {
+ FvSectionSize = SECTION2_SIZE (FvSection);
+ FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+ } else {
+ FvSectionSize = SECTION_SIZE (FvSection);
+ FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
+ }
+
+ ASSERT (FvSectionSize == (PcdGet32 (PcdSimicsDxeMemFvSize) + FvHeaderSize));
+
+ DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBase);
+ CopyMem (DxeMemFv, (VOID*) ((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdSimicsDxeMemFvSize));
+
+ if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));
+ CpuDeadLoop ();
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ *Fv = PeiMemFv;
+ return EFI_SUCCESS;
+}
+
+/**
+ Locates the PEI Core entry point address
+
+ @param[in] Fv The firmware volume to search
+ @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindPeiCoreImageBaseInFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *Section;
+
+ DEBUG ((EFI_D_VERBOSE, "Find PEI Core image.\n"));
+ Status = FindFfsFileAndSection (
+ Fv,
+ EFI_FV_FILETYPE_PEI_CORE,
+ EFI_SECTION_PE32,
+ &Section
+ );
+ if (EFI_ERROR (Status)) {
+ Status = FindFfsFileAndSection (
+ Fv,
+ EFI_FV_FILETYPE_PEI_CORE,
+ EFI_SECTION_TE,
+ &Section
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));
+ return Status;
+ }
+ }
+
+ *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+ DEBUG ((EFI_D_VERBOSE, "PEI core image base 0x%016LX.\n", *PeiCoreImageBase));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads 8-bits of CMOS data.
+
+ Reads the 8-bits of CMOS data at the location specified by Index.
+ The 8-bit read value is returned.
+
+ @param Index The CMOS location to read.
+
+ @return The value read.
+
+**/
+STATIC
+UINT8
+CmosRead8 (
+ IN UINTN Index
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ return IoRead8 (0x71);
+}
+
+
+STATIC
+BOOLEAN
+IsS3Resume (
+ VOID
+ )
+{
+ DEBUG((EFI_D_VERBOSE, "modeValue = %x\n", IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12)));
+ return (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) == 0x5);
+}
+
+
+STATIC
+EFI_STATUS
+GetS3ResumePeiFv (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv
+ )
+{
+ *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsPeiMemFvBase);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Locates the PEI Core entry point address
+
+ @param[in,out] Fv The firmware volume to search
+ @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+VOID
+FindPeiCoreImageBase (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ )
+{
+ BOOLEAN S3Resume;
+
+ *PeiCoreImageBase = 0;
+
+ S3Resume = IsS3Resume ();
+ if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // A malicious runtime OS may have injected something into our previously
+ // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
+ //
+ DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));
+ GetS3ResumePeiFv (BootFv);
+ } else {
+ //
+ // We're either not resuming, or resuming "securely" -- we'll decompress
+ // both PEI FV and DXE FV from pristine flash.
+ //
+ DEBUG ((EFI_D_VERBOSE, "SEC: %a\n",
+ S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"));
+ FindMainFv (BootFv);
+
+ DecompressMemFvs (BootFv);
+ }
+
+ FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
+}
+
+/**
+ Find core image base.
+
+**/
+EFI_STATUS
+FindImageBase (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
+ OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+ EFI_COMMON_SECTION_HEADER *Section;
+ EFI_PHYSICAL_ADDRESS EndOfSection;
+
+ *SecCoreImageBase = 0;
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
+ EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
+
+ //
+ // Loop through the FFS files in the Boot Firmware Volume
+ //
+ for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
+
+ CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ return EFI_NOT_FOUND;
+ }
+
+ File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
+ Size = *(UINT32*) File->Size & 0xffffff;
+ if (Size < sizeof (*File)) {
+ return EFI_NOT_FOUND;
+ }
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Look for SEC Core
+ //
+ if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
+ continue;
+ }
+
+ //
+ // Loop through the FFS file sections within the FFS file
+ //
+ EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);
+ for (;;) {
+ CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
+ Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
+
+ Size = *(UINT32*) Section->Size & 0xffffff;
+ if (Size < sizeof (*Section)) {
+ return EFI_NOT_FOUND;
+ }
+
+ EndOfSection = CurrentAddress + Size;
+ if (EndOfSection > EndOfFile) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Look for executable sections
+ //
+ if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
+ if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
+ *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);
+ }
+ break;
+ }
+ }
+
+ //
+ // SEC Core image found
+ //
+ if (*SecCoreImageBase != 0) {
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+/*
+ Find and return Pei Core entry point.
+
+ It also find SEC and PEI Core file debug information. It will report them if
+ remote debug is enabled.
+
+**/
+VOID
+FindAndReportEntryPoints (
+ IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
+ OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS SecCoreImageBase;
+ EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ //
+ // Find SEC Core and PEI Core image base
+ //
+ Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
+ ASSERT_EFI_ERROR (Status);
+
+ FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
+
+ ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+ //
+ // Report SEC Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = SecCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Report PEI Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Find PEI Core entry point
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
+ if (EFI_ERROR (Status)) {
+ *PeiCoreEntryPoint = 0;
+ }
+
+ return;
+}
+
+VOID
+EFIAPI
+SecCoreStartupWithStack (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
+ IN VOID *TopOfCurrentStack
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ SEC_IDT_TABLE IdtTableInStack;
+ IA32_DESCRIPTOR IdtDescriptor;
+ UINT32 Index;
+ volatile UINT8 *Table;
+
+ //
+ // Initialize floating point operating environment
+ // to be compliant with UEFI spec.
+ //
+ InitializeFloatingPointUnits ();
+
+ //
+ // Initialize the PCIe Configuration base register.
+ //
+ PciCf8Write32 (PCI_CF8_LIB_ADDRESS (0xFF, 0, 1, 0x50), 0xE0000001);
+
+ //
+ // To ensure SMM can't be compromised on S3 resume, we must force re-init of
+ // the BaseExtractGuidedSectionLib. Since this is before library contructors
+ // are called, we must use a loop rather than SetMem.
+ //
+ Table = (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
+ for (Index = 0;
+ Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
+ ++Index) {
+ Table[Index] = 0;
+ }
+
+ ProcessLibraryConstructorList (NULL, NULL);
+
+ DEBUG ((EFI_D_INFO,
+ "SecCoreStartupWithStack(0x%x, 0x%x)\n",
+ (UINT32)(UINTN)BootFv,
+ (UINT32)(UINTN)TopOfCurrentStack
+ ));
+
+ //
+ // Initialize IDT
+ //
+ IdtTableInStack.PeiService = NULL;
+ for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
+ CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
+ }
+
+ IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
+ IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+#if defined (MDE_CPU_X64)
+ //
+ // ASSERT that the Page Tables were set by the reset vector code to
+ // the address we expect.
+ //
+ ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdSimicsSecPageTablesBase));
+#endif
+
+ //
+ // |-------------| <-- TopOfCurrentStack
+ // | Stack | 32k
+ // |-------------|
+ // | Heap | 32k
+ // |-------------| <-- SecCoreData.TemporaryRamBase
+ //
+
+ ASSERT ((UINTN) (PcdGet32 (PcdSimicsSecPeiTempRamBase) +
+ PcdGet32 (PcdSimicsSecPeiTempRamSize)) ==
+ (UINTN) TopOfCurrentStack);
+
+ //
+ // Initialize SEC hand-off state
+ //
+ SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
+
+ SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdSimicsSecPeiTempRamSize);
+ SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
+
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
+
+ SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
+ SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
+
+ SecCoreData.BootFirmwareVolumeBase = BootFv;
+ SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
+
+ //
+ // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
+ //
+ IoWrite8 (0x21, 0xff);
+ IoWrite8 (0xA1, 0xff);
+
+ //
+ // Initialize Local APIC Timer hardware and disable Local APIC Timer
+ // interrupts before initializing the Debug Agent and the debug timer is
+ // enabled.
+ //
+ InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
+ DisableApicTimerInterrupt ();
+
+ //
+ // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
+}
+
+/**
+ Caller provided function to be invoked at the end of InitializeDebugAgent().
+
+ Entry point to the C language phase of SEC. After the SEC assembly
+ code has initialized some temporary memory and set up the stack,
+ the control is transferred to this function.
+
+ @param[in] Context The first input parameter of InitializeDebugAgent().
+
+**/
+VOID
+EFIAPI
+SecStartupPhase2(
+ IN VOID *Context
+ )
+{
+ EFI_SEC_PEI_HAND_OFF *SecCoreData;
+ EFI_FIRMWARE_VOLUME_HEADER *BootFv;
+ EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
+
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
+
+ //
+ // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
+ // is enabled.
+ //
+ BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
+ FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
+ SecCoreData->BootFirmwareVolumeBase = BootFv;
+ SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
+
+ //
+ // Transfer the control to the PEI core
+ //
+ (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
+
+ //
+ // If we get here then the PEI Core returned, which is not recoverable.
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ IA32_DESCRIPTOR IdtDescriptor;
+ VOID *OldHeap;
+ VOID *NewHeap;
+ VOID *OldStack;
+ VOID *NewStack;
+ DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
+ BOOLEAN OldStatus;
+ BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
+
+ DEBUG ((EFI_D_INFO,
+ "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
+ TemporaryMemoryBase,
+ PermanentMemoryBase,
+ (UINT64)CopySize
+ ));
+
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
+
+ OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
+ NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+ DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
+ DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
+
+ OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
+ InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
+
+ //
+ // Migrate Heap
+ //
+ CopyMem (NewHeap, OldHeap, CopySize >> 1);
+
+ //
+ // Migrate Stack
+ //
+ CopyMem (NewStack, OldStack, CopySize >> 1);
+
+ //
+ // Rebase IDT table in permanent memory
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+ //
+ // Use SetJump()/LongJump() to switch to a new stack.
+ //
+ if (SetJump (&JumpBuffer) == 0) {
+#if defined (MDE_CPU_IA32)
+ JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
+#endif
+#if defined (MDE_CPU_X64)
+ JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
+#endif
+ LongJump (&JumpBuffer, (UINTN)-1);
+ }
+
+ SaveAndSetDebugTimerInterrupt (OldStatus);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
new file mode 100644
index 0000000000..b7fd4d1f6d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.c
@@ -0,0 +1,865 @@
+/** @file
+ This driver effectuates QSP platform configuration settings and exposes
+ them via HII.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/SimicsBoardConfig.h>
+
+#include "Platform.h"
+#include "PlatformConfig.h"
+#include <Library/DxeServicesTableLib.h>
+//
+// The HiiAddPackages() library function requires that any controller (or
+// image) handle, to be associated with the HII packages under installation, be
+// "decorated" with a device path. The tradition seems to be a vendor device
+// path.
+//
+// We'd like to associate our HII packages with the driver's image handle. The
+// first idea is to use the driver image's device path. Unfortunately, loaded
+// images only come with an EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL (not the
+// usual EFI_DEVICE_PATH_PROTOCOL), ie. a different GUID. In addition, even the
+// EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL interface may be NULL, if the image
+// has been loaded from an "unnamed" memory source buffer.
+//
+// Hence let's just stick with the tradition -- use a dedicated vendor device
+// path, with the driver's FILE_GUID.
+//
+#pragma pack(1)
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PKG_DEVICE_PATH;
+#pragma pack()
+
+STATIC PKG_DEVICE_PATH mPkgDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH) ),
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH) >> 8)
+ }
+ },
+ EFI_CALLER_ID_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH ),
+ (UINT8) (END_DEVICE_PATH_LENGTH >> 8)
+ }
+ }
+};
+
+//
+// The configuration interface between the HII engine (form display etc) and
+// this driver.
+//
+STATIC EFI_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess;
+
+//
+// The handle representing our list of packages after installation.
+//
+STATIC EFI_HII_HANDLE mInstalledPackages;
+
+//
+// The arrays below constitute our HII package list. They are auto-generated by
+// the VFR compiler and linked into the driver image during the build.
+//
+// - The strings package receives its C identifier from the driver's BASE_NAME,
+// plus "Strings".
+//
+// - The forms package receives its C identifier from the VFR file's basename,
+// plus "Bin".
+//
+//
+extern UINT8 SimicsDxeStrings[];
+extern UINT8 PlatformFormsBin[];
+
+//
+// We want to be notified about GOP installations until we find one GOP
+// interface that lets us populate the form.
+//
+STATIC EFI_EVENT mGopEvent;
+
+//
+// The registration record underneath this pointer allows us to iterate through
+// the GOP instances one by one.
+//
+STATIC VOID *mGopTracker;
+
+//
+// Cache the resolutions we get from the GOP.
+//
+typedef struct {
+ UINT32 X;
+ UINT32 Y;
+} GOP_MODE;
+
+STATIC UINTN mNumGopModes;
+STATIC GOP_MODE *mGopModes;
+
+
+/**
+ Load the persistent platform configuration and translate it to binary form
+ state.
+
+ If the platform configuration is missing, then the function fills in a
+ default state.
+
+ @param[out] MainFormState Binary form/widget state after translation.
+
+ @retval EFI_SUCCESS Form/widget state ready.
+ @return Error codes from underlying functions.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PlatformConfigToFormState (
+ OUT MAIN_FORM_STATE *MainFormState
+ )
+{
+ EFI_STATUS Status;
+ PLATFORM_CONFIG PlatformConfig;
+ UINT64 OptionalElements;
+ UINTN ModeNumber;
+
+ ZeroMem (MainFormState, sizeof *MainFormState);
+
+ Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);
+ switch (Status) {
+ case EFI_SUCCESS:
+ if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {
+ //
+ // Format the preferred resolution as text.
+ //
+ UnicodeSPrintAsciiFormat (
+ (CHAR16 *) MainFormState->CurrentPreferredResolution,
+ sizeof MainFormState->CurrentPreferredResolution,
+ "%Ldx%Ld",
+ (INT64) PlatformConfig.HorizontalResolution,
+ (INT64) PlatformConfig.VerticalResolution);
+
+ //
+ // Try to locate it in the drop-down list too. This may not succeed, but
+ // that's fine.
+ //
+ for (ModeNumber = 0; ModeNumber < mNumGopModes; ++ModeNumber) {
+ if (mGopModes[ModeNumber].X == PlatformConfig.HorizontalResolution &&
+ mGopModes[ModeNumber].Y == PlatformConfig.VerticalResolution) {
+ MainFormState->NextPreferredResolution = (UINT32) ModeNumber;
+ break;
+ }
+ }
+
+ break;
+ }
+ //
+ // fall through otherwise
+ //
+
+ case EFI_NOT_FOUND:
+ UnicodeSPrintAsciiFormat (
+ (CHAR16 *) MainFormState->CurrentPreferredResolution,
+ sizeof MainFormState->CurrentPreferredResolution,
+ "Unset");
+ break;
+
+ default:
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is called by the HII machinery when it fetches the form state.
+
+ See the precise documentation in the UEFI spec.
+
+ @param[in] This The Config Access Protocol instance.
+
+ @param[in] Request A <ConfigRequest> format UCS-2 string describing the
+ query.
+
+ @param[out] Progress A pointer into Request on output, identifying the query
+ element where processing failed.
+
+ @param[out] Results A <MultiConfigAltResp> format UCS-2 string that has
+ all values filled in for the names in the Request
+ string.
+
+ @retval EFI_SUCCESS Extraction of form state in <MultiConfigAltResp>
+ encoding successful.
+ @return Status codes from underlying functions.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+)
+{
+ MAIN_FORM_STATE MainFormState;
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_VERBOSE, "%a: Request=\"%s\"\n", __FUNCTION__, Request));
+
+ Status = PlatformConfigToFormState (&MainFormState);
+ if (EFI_ERROR (Status)) {
+ *Progress = Request;
+ return Status;
+ }
+
+ //
+ // Answer the textual request keying off the binary form state.
+ //
+ Status = gHiiConfigRouting->BlockToConfig (gHiiConfigRouting, Request,
+ (VOID *) &MainFormState, sizeof MainFormState,
+ Results, Progress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: BlockToConfig(): %r, Progress=\"%s\"\n",
+ __FUNCTION__, Status, (Status == EFI_DEVICE_ERROR) ? NULL : *Progress));
+ } else {
+ DEBUG ((EFI_D_VERBOSE, "%a: Results=\"%s\"\n", __FUNCTION__, *Results));
+ }
+ return Status;
+}
+
+
+/**
+ Interpret the binary form state and save it as persistent platform
+ configuration.
+
+ @param[in] MainFormState Binary form/widget state to verify and save.
+
+ @retval EFI_SUCCESS Platform configuration saved.
+ @return Error codes from underlying functions.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FormStateToPlatformConfig (
+ IN CONST MAIN_FORM_STATE *MainFormState
+ )
+{
+ EFI_STATUS Status;
+ PLATFORM_CONFIG PlatformConfig;
+ CONST GOP_MODE *GopMode;
+
+ //
+ // There's nothing to do with the textual CurrentPreferredResolution field.
+ // We verify and translate the selection in the drop-down list.
+ //
+ if (MainFormState->NextPreferredResolution >= mNumGopModes) {
+ return EFI_INVALID_PARAMETER;
+ }
+ GopMode = mGopModes + MainFormState->NextPreferredResolution;
+
+ ZeroMem (&PlatformConfig, sizeof PlatformConfig);
+ PlatformConfig.HorizontalResolution = GopMode->X;
+ PlatformConfig.VerticalResolution = GopMode->Y;
+
+ Status = PlatformConfigSave (&PlatformConfig);
+ return Status;
+}
+
+
+/**
+ This function is called by the HII machinery when it wants the driver to
+ interpret and persist the form state.
+
+ See the precise documentation in the UEFI spec.
+
+ @param[in] This The Config Access Protocol instance.
+
+ @param[in] Configuration A <ConfigResp> format UCS-2 string describing the
+ form state.
+
+ @param[out] Progress A pointer into Configuration on output,
+ identifying the element where processing failed.
+
+ @retval EFI_SUCCESS Configuration verified, state permanent.
+
+ @return Status codes from underlying functions.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+RouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+)
+{
+ MAIN_FORM_STATE MainFormState;
+ UINTN BlockSize;
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_VERBOSE, "%a: Configuration=\"%s\"\n", __FUNCTION__,
+ Configuration));
+
+ //
+ // the "read" step in RMW
+ //
+ Status = PlatformConfigToFormState (&MainFormState);
+ if (EFI_ERROR (Status)) {
+ *Progress = Configuration;
+ return Status;
+ }
+
+ //
+ // the "modify" step in RMW
+ //
+ // (Update the binary form state. This update may be partial, which is why in
+ // general we must pre-load the form state from the platform config.)
+ //
+ BlockSize = sizeof MainFormState;
+ Status = gHiiConfigRouting->ConfigToBlock (gHiiConfigRouting, Configuration,
+ (VOID *) &MainFormState, &BlockSize, Progress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: ConfigToBlock(): %r, Progress=\"%s\"\n",
+ __FUNCTION__, Status,
+ (Status == EFI_BUFFER_TOO_SMALL) ? NULL : *Progress));
+ return Status;
+ }
+
+ //
+ // the "write" step in RMW
+ //
+ Status = FormStateToPlatformConfig (&MainFormState);
+ if (EFI_ERROR (Status)) {
+ *Progress = Configuration;
+ }
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+Callback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN OUT EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ DEBUG ((EFI_D_VERBOSE, "%a: Action=0x%Lx QuestionId=%d Type=%d\n",
+ __FUNCTION__, (UINT64) Action, QuestionId, Type));
+
+ if (Action != EFI_BROWSER_ACTION_CHANGED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (QuestionId) {
+ case QUESTION_SAVE_EXIT:
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+ break;
+
+ case QUESTION_DISCARD_EXIT:
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Query and save all resolutions supported by the GOP.
+
+ @param[in] Gop The Graphics Output Protocol instance to query.
+
+ @param[out] NumGopModes The number of modes supported by the GOP. On output,
+ this parameter will be positive.
+
+ @param[out] GopModes On output, a dynamically allocated array containing
+ the resolutions returned by the GOP. The caller is
+ responsible for freeing the array after use.
+
+ @retval EFI_UNSUPPORTED No modes found.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate GopModes.
+ @return Error codes from Gop->QueryMode().
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+QueryGopModes (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
+ OUT UINTN *NumGopModes,
+ OUT GOP_MODE **GopModes
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ModeNumber;
+
+ if (Gop->Mode->MaxMode == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ *NumGopModes = Gop->Mode->MaxMode;
+
+ *GopModes = AllocatePool (Gop->Mode->MaxMode * sizeof **GopModes);
+ if (*GopModes == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (ModeNumber = 0; ModeNumber < Gop->Mode->MaxMode; ++ModeNumber) {
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ UINTN SizeOfInfo;
+
+ Status = Gop->QueryMode (Gop, ModeNumber, &SizeOfInfo, &Info);
+ if (EFI_ERROR (Status)) {
+ goto FreeGopModes;
+ }
+
+ (*GopModes)[ModeNumber].X = Info->HorizontalResolution;
+ (*GopModes)[ModeNumber].Y = Info->VerticalResolution;
+ FreePool (Info);
+ }
+
+ return EFI_SUCCESS;
+
+FreeGopModes:
+ FreePool (*GopModes);
+
+ return Status;
+}
+
+
+/**
+ Create a set of "one-of-many" (ie. "drop down list") option IFR opcodes,
+ based on available GOP resolutions, to be placed under a "one-of-many" (ie.
+ "drop down list") opcode.
+
+ @param[in] PackageList The package list with the formset and form for
+ which the drop down options are produced. Option
+ names are added as new strings to PackageList.
+
+ @param[out] OpCodeBuffer On output, a dynamically allocated opcode buffer
+ with drop down list options corresponding to GOP
+ resolutions. The caller is responsible for freeing
+ OpCodeBuffer with HiiFreeOpCodeHandle() after use.
+
+ @param[in] NumGopModes Number of entries in GopModes.
+
+ @param[in] GopModes Array of resolutions retrieved from the GOP.
+
+ @retval EFI_SUCESS Opcodes have been successfully produced.
+
+ @return Status codes from underlying functions. PackageList may
+ have been extended with new strings. OpCodeBuffer is
+ unchanged.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CreateResolutionOptions (
+ IN EFI_HII_HANDLE *PackageList,
+ OUT VOID **OpCodeBuffer,
+ IN UINTN NumGopModes,
+ IN GOP_MODE *GopModes
+ )
+{
+ EFI_STATUS Status;
+ VOID *OutputBuffer;
+ UINTN ModeNumber;
+
+ OutputBuffer = HiiAllocateOpCodeHandle ();
+ if (OutputBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (ModeNumber = 0; ModeNumber < NumGopModes; ++ModeNumber) {
+ CHAR16 Desc[MAXSIZE_RES_CUR];
+ EFI_STRING_ID NewString;
+ VOID *OpCode;
+
+ UnicodeSPrintAsciiFormat (Desc, sizeof Desc, "%Ldx%Ld",
+ (INT64) GopModes[ModeNumber].X, (INT64) GopModes[ModeNumber].Y);
+ NewString = HiiSetString (PackageList, 0 /* new string */, Desc,
+ NULL /* for all languages */);
+ if (NewString == 0) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeOutputBuffer;
+ }
+ OpCode = HiiCreateOneOfOptionOpCode (OutputBuffer, NewString,
+ 0 /* Flags */, EFI_IFR_NUMERIC_SIZE_4, ModeNumber);
+ if (OpCode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeOutputBuffer;
+ }
+ }
+
+ *OpCodeBuffer = OutputBuffer;
+ return EFI_SUCCESS;
+
+FreeOutputBuffer:
+ HiiFreeOpCodeHandle (OutputBuffer);
+
+ return Status;
+}
+
+
+/**
+ Populate the form identified by the (PackageList, FormSetGuid, FormId)
+ triplet.
+
+ The drop down list of video resolutions is generated from (NumGopModes,
+ GopModes).
+
+ @retval EFI_SUCESS Form successfully updated.
+ @return Status codes from underlying functions.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PopulateForm (
+ IN EFI_HII_HANDLE *PackageList,
+ IN EFI_GUID *FormSetGuid,
+ IN EFI_FORM_ID FormId,
+ IN UINTN NumGopModes,
+ IN GOP_MODE *GopModes
+ )
+{
+ EFI_STATUS Status;
+ VOID *OpCodeBuffer;
+ VOID *OpCode;
+ EFI_IFR_GUID_LABEL *Anchor;
+ VOID *OpCodeBuffer2;
+
+ OpCodeBuffer2 = NULL;
+
+ //
+ // 1. Allocate an empty opcode buffer.
+ //
+ OpCodeBuffer = HiiAllocateOpCodeHandle ();
+ if (OpCodeBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // 2. Create a label opcode (which is a Tiano extension) inside the buffer.
+ // The label's number must match the "anchor" label in the form.
+ //
+ OpCode = HiiCreateGuidOpCode (OpCodeBuffer, &gEfiIfrTianoGuid,
+ NULL /* optional copy origin */, sizeof *Anchor);
+ if (OpCode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeOpCodeBuffer;
+ }
+ Anchor = OpCode;
+ Anchor->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ Anchor->Number = LABEL_RES_NEXT;
+
+ //
+ // 3. Create the opcodes inside the buffer that are to be inserted into the
+ // form.
+ //
+ // 3.1. Get a list of resolutions.
+ //
+ Status = CreateResolutionOptions (PackageList, &OpCodeBuffer2,
+ NumGopModes, GopModes);
+ if (EFI_ERROR (Status)) {
+ goto FreeOpCodeBuffer;
+ }
+
+ //
+ // 3.2. Create a one-of-many question with the above options.
+ //
+ OpCode = HiiCreateOneOfOpCode (
+ OpCodeBuffer, // create opcode inside this
+ // opcode buffer,
+ QUESTION_RES_NEXT, // ID of question,
+ FORMSTATEID_MAIN_FORM, // identifies form state
+ // storage,
+ (UINT16) OFFSET_OF (MAIN_FORM_STATE, // value of question stored
+ NextPreferredResolution), // at this offset,
+ STRING_TOKEN (STR_RES_NEXT), // Prompt,
+ STRING_TOKEN (STR_RES_NEXT_HELP), // Help,
+ 0, // QuestionFlags,
+ EFI_IFR_NUMERIC_SIZE_4, // see sizeof
+ // NextPreferredResolution,
+ OpCodeBuffer2, // buffer with possible
+ // choices,
+ NULL // DEFAULT opcodes
+ );
+ if (OpCode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeOpCodeBuffer2;
+ }
+
+ //
+ // 4. Update the form with the opcode buffer.
+ //
+ Status = HiiUpdateForm (PackageList, FormSetGuid, FormId,
+ OpCodeBuffer, // buffer with head anchor, and new contents to be
+ // inserted at it
+ NULL // buffer with tail anchor, for deleting old
+ // contents up to it
+ );
+
+FreeOpCodeBuffer2:
+ HiiFreeOpCodeHandle (OpCodeBuffer2);
+
+FreeOpCodeBuffer:
+ HiiFreeOpCodeHandle (OpCodeBuffer);
+
+ return Status;
+}
+
+
+/**
+ Load and execute the platform configuration.
+
+ @retval EFI_SUCCESS Configuration loaded and executed.
+ @return Status codes from PlatformConfigLoad().
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ExecutePlatformConfig (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PLATFORM_CONFIG PlatformConfig;
+ UINT64 OptionalElements;
+
+ Status = PlatformConfigLoad (&PlatformConfig, &OptionalElements);
+ if (EFI_ERROR (Status)) {
+ DEBUG (((Status == EFI_NOT_FOUND) ? EFI_D_VERBOSE : EFI_D_ERROR,
+ "%a: failed to load platform config: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ if (OptionalElements & PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION) {
+ //
+ // Pass the preferred resolution to GraphicsConsoleDxe via dynamic PCDs.
+ //
+ PcdSet32 (PcdVideoHorizontalResolution,
+ PlatformConfig.HorizontalResolution);
+ PcdSet32 (PcdVideoVerticalResolution,
+ PlatformConfig.VerticalResolution);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Notification callback for GOP interface installation.
+
+ @param[in] Event Event whose notification function is being invoked.
+
+ @param[in] Context The pointer to the notification function's context, which
+ is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+GopInstalled (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+ ASSERT (Event == mGopEvent);
+
+ //
+ // Check further GOPs.
+ //
+ for (;;) {
+ mNumGopModes = 0;
+ mGopModes = NULL;
+
+ Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, mGopTracker,
+ (VOID **) &Gop);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = QueryGopModes (Gop, &mNumGopModes, &mGopModes);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = PopulateForm (mInstalledPackages, &gSimicsBoardConfigGuid,
+ FORMID_MAIN_FORM, mNumGopModes, mGopModes);
+ if (EFI_ERROR (Status)) {
+ FreePool (mGopModes);
+ continue;
+ }
+
+ break;
+ }
+
+ //
+ // Success -- so uninstall this callback. Closing the event removes all
+ // pending notifications and all protocol registrations.
+ //
+ Status = gBS->CloseEvent (mGopEvent);
+ ASSERT_EFI_ERROR (Status);
+ mGopEvent = NULL;
+ mGopTracker = NULL;
+}
+
+
+/**
+ Entry point for this driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS Driver has loaded successfully.
+ @retval EFI_OUT_OF_RESOURCES Failed to install HII packages.
+ @return Error codes from lower level functions.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ExecutePlatformConfig ();
+
+ mConfigAccess.ExtractConfig = &ExtractConfig;
+ mConfigAccess.RouteConfig = &RouteConfig;
+ mConfigAccess.Callback = &Callback;
+
+ //
+ // Declare ourselves suitable for HII communication.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+ &gEfiDevicePathProtocolGuid, &mPkgDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Publish the HII package list to HII Database.
+ //
+ mInstalledPackages = HiiAddPackages (
+ &gEfiCallerIdGuid, // PackageListGuid
+ ImageHandle, // associated DeviceHandle
+ SimicsDxeStrings, // 1st package
+ PlatformFormsBin, // 2nd package
+ NULL // terminator
+ );
+ if (mInstalledPackages == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UninstallProtocols;
+ }
+
+ Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, &GopInstalled,
+ NULL /* Context */, &mGopEvent);
+ if (EFI_ERROR (Status)) {
+ goto RemovePackages;
+ }
+
+ Status = gBS->RegisterProtocolNotify (&gEfiGraphicsOutputProtocolGuid,
+ mGopEvent, &mGopTracker);
+ if (EFI_ERROR (Status)) {
+ goto CloseGopEvent;
+ }
+
+ //
+ // Check already installed GOPs.
+ //
+ Status = gBS->SignalEvent (mGopEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+
+CloseGopEvent:
+ gBS->CloseEvent (mGopEvent);
+
+RemovePackages:
+ HiiRemovePackages (mInstalledPackages);
+
+UninstallProtocols:
+ gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
+ &gEfiDevicePathProtocolGuid, &mPkgDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,
+ NULL);
+ return Status;
+}
+
+/**
+ Unload the driver.
+
+ @param[in] ImageHandle Handle that identifies the image to evict.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+**/
+EFI_STATUS
+EFIAPI
+PlatformUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ if (mGopEvent == NULL) {
+ //
+ // The GOP callback ran successfully and unregistered itself. Release the
+ // resources allocated there.
+ //
+ ASSERT (mGopModes != NULL);
+ FreePool (mGopModes);
+ } else {
+ //
+ // Otherwise we need to unregister the callback.
+ //
+ ASSERT (mGopModes == NULL);
+ gBS->CloseEvent (mGopEvent);
+ }
+
+ //
+ // Release resources allocated by the entry point.
+ //
+ HiiRemovePackages (mInstalledPackages);
+ gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
+ &gEfiDevicePathProtocolGuid, &mPkgDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid, &mConfigAccess,
+ NULL);
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
new file mode 100644
index 0000000000..09929e830a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.c
@@ -0,0 +1,124 @@
+/** @file
+ Utility functions for serializing (persistently storing) and deserializing
+ SIMICS QSP's platform configuration.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/SimicsBoardConfig.h>
+
+#include "PlatformConfig.h"
+
+//
+// Name of the UEFI variable that we use for persistent storage.
+//
+STATIC CHAR16 mVariableName[] = L"PlatformConfig";
+
+
+/**
+ Serialize and persistently save platform configuration.
+
+ @param[in] PlatformConfig The platform configuration to serialize and save.
+
+ @return Status codes returned by gRT->SetVariable().
+**/
+EFI_STATUS
+EFIAPI
+PlatformConfigSave (
+ IN PLATFORM_CONFIG *PlatformConfig
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // We could implement any kind of translation here, as part of serialization.
+ // For example, we could expose the platform configuration in separate
+ // variables with human-readable contents, allowing other tools to access
+ // them more easily. For now, just save a binary dump.
+ //
+ Status = gRT->SetVariable (mVariableName, &gSimicsBoardConfigGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof *PlatformConfig, PlatformConfig);
+ return Status;
+}
+
+
+/**
+ Load and deserialize platform configuration.
+
+ When the function fails, output parameters are indeterminate.
+
+ @param[out] PlatformConfig The platform configuration to receive the
+ loaded data.
+
+ @param[out] OptionalElements This bitmap describes the presence of optional
+ configuration elements that have been loaded.
+ PLATFORM_CONFIG_F_DOWNGRADE means that some
+ unknown elements, present in the wire format,
+ have been ignored.
+
+ @retval EFI_SUCCESS Loading & deserialization successful.
+ @return Error codes returned by GetVariable2().
+**/
+EFI_STATUS
+EFIAPI
+PlatformConfigLoad (
+ OUT PLATFORM_CONFIG *PlatformConfig,
+ OUT UINT64 *OptionalElements
+ )
+{
+ VOID *Data;
+ UINTN DataSize;
+ EFI_STATUS Status;
+
+ //
+ // Any translation done in PlatformConfigSave() would have to be mirrored
+ // here. For now, just load the binary dump.
+ //
+ // Versioning of the binary wire format is implemented based on size
+ // (only incremental changes, ie. new fields), and on GUID.
+ // (Incompatible changes require a GUID change.)
+ //
+ Status = GetVariable2 (mVariableName, &gSimicsBoardConfigGuid, &Data,
+ &DataSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *OptionalElements = 0;
+ if (DataSize > sizeof *PlatformConfig) {
+ //
+ // Handle firmware downgrade -- keep only leading part.
+ //
+ CopyMem (PlatformConfig, Data, sizeof *PlatformConfig);
+ *OptionalElements |= PLATFORM_CONFIG_F_DOWNGRADE;
+ } else {
+ CopyMem (PlatformConfig, Data, DataSize);
+
+ //
+ // Handle firmware upgrade -- zero out missing fields.
+ //
+ ZeroMem ((UINT8 *)PlatformConfig + DataSize,
+ sizeof *PlatformConfig - DataSize);
+ }
+
+ //
+ // Based on DataSize, report the optional features that we recognize.
+ //
+ if (DataSize >= (OFFSET_OF (PLATFORM_CONFIG, VerticalResolution) +
+ sizeof PlatformConfig->VerticalResolution)) {
+ *OptionalElements |= PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION;
+ }
+
+ FreePool (Data);
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
new file mode 100644
index 0000000000..b34ba9283b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.c
@@ -0,0 +1,57 @@
+/** @file
+ PC/AT CMOS access routines
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Cmos.h"
+#include "Library/IoLib.h"
+
+/**
+ Reads 8-bits of CMOS data.
+
+ Reads the 8-bits of CMOS data at the location specified by Index.
+ The 8-bit read value is returned.
+
+ @param Index The CMOS location to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+ IN UINTN Index
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ return IoRead8 (0x71);
+}
+
+
+/**
+ Writes 8-bits of CMOS data.
+
+ Writes 8-bits of CMOS data to the location specified by Index
+ with the value specified by Value and returns Value.
+
+ @param Index The CMOS location to write.
+ @param Value The value to write to CMOS.
+
+ @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+ IN UINTN Index,
+ IN UINT8 Value
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ IoWrite8 (0x71, Value);
+ return Value;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
new file mode 100644
index 0000000000..9d2fc65a14
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/FeatureControl.c
@@ -0,0 +1,115 @@
+/** @file
+ Install a callback when necessary for setting the Feature Control MSR on all
+ processors.
+
+ Copyright (C) 2016, Red Hat, Inc.
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/MpServices.h>
+#include <Register/Intel/Msr/Core2Msr.h>
+
+#include "Platform.h"
+
+//
+// The value to be written to the Feature Control MSR, retrieved from fw_cfg.
+//
+STATIC UINT64 mFeatureControlValue = 0x00000005;
+
+/**
+ Write the Feature Control MSR on an Application Processor or the Boot
+ Processor.
+
+ All APs execute this function in parallel. The BSP executes the function
+ separately.
+
+ @param[in,out] WorkSpace Pointer to the input/output argument workspace
+ shared by all processors.
+**/
+STATIC
+VOID
+EFIAPI
+WriteFeatureControl (
+ IN OUT VOID *WorkSpace
+ )
+{
+ AsmWriteMsr64 (MSR_CORE2_FEATURE_CONTROL, mFeatureControlValue);
+}
+
+/**
+ Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
+
+ @param[in] PeiServices Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor Address of the notification descriptor data
+ structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @return Status of the notification. The status code returned from this
+ function is ignored.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+OnMpServicesAvailable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_PEI_MP_SERVICES_PPI *MpServices;
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
+ //
+ // Write the MSR on all the APs in parallel.
+ //
+ MpServices = Ppi;
+ Status = MpServices->StartupAllAPs (
+ (CONST EFI_PEI_SERVICES **)PeiServices,
+ MpServices,
+ WriteFeatureControl, // Procedure
+ FALSE, // SingleThread
+ 0, // TimeoutInMicroSeconds: inf.
+ NULL // ProcedureArgument
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
+ DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ //
+ // Now write the MSR on the BSP too.
+ //
+ WriteFeatureControl (NULL);
+
+ return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EFI_PEI_MP_SERVICES_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiMpServicesPpiGuid, // Guid
+ OnMpServicesAvailable // Notify
+};
+
+VOID
+InstallFeatureControlCallback (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesNotifyPpi (&mMpServicesNotify);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: failed to set up MP Services callback: %r\n",
+ __FUNCTION__, Status));
+ }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
new file mode 100644
index 0000000000..90e6d1d3cf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/MemDetect.c
@@ -0,0 +1,568 @@
+/** @file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/MtrrLib.h>
+#include <SimicsPlatforms.h>
+#include <Guid/SmramMemoryReserve.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+UINT8 mPhysMemAddressWidth;
+
+STATIC UINT32 mS3AcpiReservedMemoryBase;
+STATIC UINT32 mS3AcpiReservedMemorySize;
+
+STATIC UINT16 mX58TsegMbytes;
+
+VOID
+X58TsegMbytesInitialization(
+ VOID
+)
+{
+
+ if (mHostBridgeDevId != INTEL_ICH10_DEVICE_ID) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
+ "only DID=0x%04x (X58) is supported\n",
+ __FUNCTION__,
+ mHostBridgeDevId,
+ INTEL_ICH10_DEVICE_ID
+ ));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ //
+ // Check if QEMU offers an extended TSEG.
+ //
+ // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TSEG_MB
+ // register, and reading back the register.
+ //
+ // On a QEMU machine type that does not offer an extended TSEG, the initial
+ // write overwrites whatever value a malicious guest OS may have placed in
+ // the (unimplemented) register, before entering S3 or rebooting.
+ // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.
+ //
+ // On a QEMU machine type that offers an extended TSEG, the initial write
+ // triggers an update to the register. Subsequently, the value read back
+ // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us the
+ // number of megabytes.
+ //
+ mX58TsegMbytes = FixedPcdGet8(PcdX58TsegMbytes);
+ return;
+}
+
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+ VOID
+ )
+{
+ UINT8 Cmos0x34;
+ UINT8 Cmos0x35;
+
+ //
+ // CMOS 0x34/0x35 specifies the system memory above 16 MB.
+ // * CMOS(0x35) is the high byte
+ // * CMOS(0x34) is the low byte
+ // * The size is specified in 64kb chunks
+ // * Since this is memory above 16MB, the 16MB must be added
+ // into the calculation to get the total memory size.
+ //
+
+ Cmos0x34 = (UINT8) CmosRead8 (0x34);
+ Cmos0x35 = (UINT8) CmosRead8 (0x35);
+
+ return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+}
+
+
+STATIC
+UINT64
+GetSystemMemorySizeAbove4gb (
+ )
+{
+ UINT32 Size;
+ UINTN CmosIndex;
+
+ //
+ // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
+ // * CMOS(0x5d) is the most significant size byte
+ // * CMOS(0x5c) is the middle size byte
+ // * CMOS(0x5b) is the least significant size byte
+ // * The size is specified in 64kb chunks
+ //
+
+ Size = 0;
+ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+ Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
+ }
+
+ return LShiftU64 (Size, 16);
+}
+
+
+/**
+ Return the highest address that DXE could possibly use, plus one.
+**/
+STATIC
+UINT64
+GetFirstNonAddress (
+ VOID
+ )
+{
+ UINT64 FirstNonAddress;
+ UINT64 Pci64Base, Pci64Size;
+
+ FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();
+
+ //
+ // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
+ // resources to 32-bit anyway. See DegradeResource() in
+ // "PciResourceSupport.c".
+ //
+#ifdef MDE_CPU_IA32
+ if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ return FirstNonAddress;
+ }
+#endif
+
+ //
+ // Otherwise, in order to calculate the highest address plus one, we must
+ // consider the 64-bit PCI host aperture too. Fetch the default size.
+ //
+ Pci64Size = PcdGet64 (PcdPciMmio64Size);
+
+ if (Pci64Size == 0) {
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ DEBUG ((EFI_D_INFO, "%a: disabling 64-bit PCI host aperture\n",
+ __FUNCTION__));
+ PcdSet64 (PcdPciMmio64Size, 0);
+ }
+
+ //
+ // There's nothing more to do; the amount of memory above 4GB fully
+ // determines the highest address plus one. The memory hotplug area (see
+ // below) plays no role for the firmware in this case.
+ //
+ return FirstNonAddress;
+ }
+
+ //
+ // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
+ // that the host can map it with 1GB hugepages. Follow suit.
+ //
+ Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
+ Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);
+
+ //
+ // The 64-bit PCI host aperture should also be "naturally" aligned. The
+ // alignment is determined by rounding the size of the aperture down to the
+ // next smaller or equal power of two. That is, align the aperture by the
+ // largest BAR size that can fit into it.
+ //
+ Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ //
+ // The core PciHostBridgeDxe driver will automatically add this range to
+ // the GCD memory space map through our PciHostBridgeLib instance; here we
+ // only need to set the PCDs.
+ //
+ PcdSet64 (PcdPciMmio64Base, Pci64Base);
+ PcdSet64 (PcdPciMmio64Size, Pci64Size);
+ DEBUG ((EFI_D_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",
+ __FUNCTION__, Pci64Base, Pci64Size));
+ }
+
+ //
+ // The useful address space ends with the 64-bit PCI host aperture.
+ //
+ FirstNonAddress = Pci64Base + Pci64Size;
+ return FirstNonAddress;
+}
+
+
+/**
+ Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
+**/
+VOID
+AddressWidthInitialization (
+ VOID
+ )
+{
+ UINT64 FirstNonAddress;
+
+ //
+ // As guest-physical memory size grows, the permanent PEI RAM requirements
+ // are dominated by the identity-mapping page tables built by the DXE IPL.
+ // The DXL IPL keys off of the physical address bits advertized in the CPU
+ // HOB. To conserve memory, we calculate the minimum address width here.
+ //
+ FirstNonAddress = GetFirstNonAddress ();
+ mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
+
+ //
+ // If FirstNonAddress is not an integral power of two, then we need an
+ // additional bit.
+ //
+ if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
+ ++mPhysMemAddressWidth;
+ }
+
+ //
+ // The minimum address width is 36 (covers up to and excluding 64 GB, which
+ // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
+ // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
+ // can simply assert that here, since 48 bits are good enough for 256 TB.
+ //
+ if (mPhysMemAddressWidth <= 36) {
+ mPhysMemAddressWidth = 36;
+ }
+ ASSERT (mPhysMemAddressWidth <= 48);
+}
+
+
+/**
+ Calculate the cap for the permanent PEI memory.
+**/
+STATIC
+UINT32
+GetPeiMemoryCap (
+ VOID
+ )
+{
+ BOOLEAN Page1GSupport;
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINT32 Pml4Entries;
+ UINT32 PdpEntries;
+ UINTN TotalPages;
+
+ //
+ // If DXE is 32-bit, then just return the traditional 64 MB cap.
+ //
+#ifdef MDE_CPU_IA32
+ if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ return SIZE_64MB;
+ }
+#endif
+
+ //
+ // Dependent on physical address width, PEI memory allocations can be
+ // dominated by the page tables built for 64-bit DXE. So we key the cap off
+ // of those. The code below is based on CreateIdentityMappingPageTables() in
+ // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".
+ //
+ Page1GSupport = FALSE;
+ if (PcdGetBool (PcdUse1GPageTable)) {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+ }
+
+ if (mPhysMemAddressWidth <= 39) {
+ Pml4Entries = 1;
+ PdpEntries = 1 << (mPhysMemAddressWidth - 30);
+ ASSERT (PdpEntries <= 0x200);
+ } else {
+ Pml4Entries = 1 << (mPhysMemAddressWidth - 39);
+ ASSERT (Pml4Entries <= 0x200);
+ PdpEntries = 512;
+ }
+
+ TotalPages = Page1GSupport ? Pml4Entries + 1 :
+ (PdpEntries + 1) * Pml4Entries + 1;
+ ASSERT (TotalPages <= 0x40201);
+
+ //
+ // Add 64 MB for miscellaneous allocations. Note that for
+ // mPhysMemAddressWidth values close to 36, the cap will actually be
+ // dominated by this increment.
+ //
+ return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);
+}
+
+
+/**
+ Publish PEI core memory
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MemoryBase;
+ UINT64 MemorySize;
+ UINT32 LowerMemorySize;
+ UINT32 PeiMemoryCap;
+
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // TSEG is chipped from the end of low RAM
+ //
+ LowerMemorySize -= mX58TsegMbytes * SIZE_1MB;
+ }
+
+ //
+ // If S3 is supported, then the S3 permanent PEI memory is placed next,
+ // downwards. Its size is primarily dictated by CpuMpPei. The formula below
+ // is an approximation.
+ //
+ if (mS3Supported) {
+ mS3AcpiReservedMemorySize = SIZE_512KB +
+ mMaxCpuCount *
+ PcdGet32 (PcdCpuApStackSize);
+ mS3AcpiReservedMemoryBase = LowerMemorySize - mS3AcpiReservedMemorySize;
+ LowerMemorySize = mS3AcpiReservedMemoryBase;
+ }
+
+ if (mBootMode == BOOT_ON_S3_RESUME) {
+ MemoryBase = mS3AcpiReservedMemoryBase;
+ MemorySize = mS3AcpiReservedMemorySize;
+ } else {
+ PeiMemoryCap = GetPeiMemoryCap ();
+ DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",
+ __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));
+
+ //
+ // Determine the range of memory to use during PEI
+ //
+ // Technically we could lay the permanent PEI RAM over SEC's temporary
+ // decompression and scratch buffer even if "secure S3" is needed, since
+ // their lifetimes don't overlap. However, PeiFvInitialization() will cover
+ // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory
+ // allocation HOB, and other allocations served from the permanent PEI RAM
+ // shouldn't overlap with that HOB.
+ //
+ MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?
+ PcdGet32 (PcdSimicsDecompressionScratchEnd) :
+ PcdGet32 (PcdSimicsDxeMemFvBase) + PcdGet32 (PcdSimicsDxeMemFvSize);
+ MemorySize = LowerMemorySize - MemoryBase;
+ }
+ DEBUG((EFI_D_INFO, "MemoryBase=0x%lx MemorySize=0x%lx\n", MemoryBase, MemorySize));
+ //
+ // Publish this memory to the PEI Core
+ //
+ Status = PublishSystemMemory(MemoryBase, MemorySize);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ Peform Memory Detection for QEMU / KVM
+
+**/
+STATIC
+VOID
+QemuInitializeRam (
+ VOID
+ )
+{
+ UINT64 LowerMemorySize;
+ UINT64 UpperMemorySize;
+ UINTN BufferSize;
+ UINT8 SmramIndex;
+ UINT8 SmramRanges;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+ UINT8 Index;
+
+ DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));
+
+ //
+ // Determine total memory size available
+ //
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+ UpperMemorySize = GetSystemMemorySizeAbove4gb ();
+
+ if (mBootMode == BOOT_ON_S3_RESUME) {
+ //
+ // Create the following memory HOB as an exception on the S3 boot path.
+ //
+ // Normally we'd create memory HOBs only on the normal boot path. However,
+ // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
+ // well, for "borrowing" a subset of it temporarily, for the AP startup
+ // vector.
+ //
+ // CpuMpPei saves the original contents of the borrowed area in permanent
+ // PEI RAM, in a backup buffer allocated with the normal PEI services.
+ // CpuMpPei restores the original contents ("returns" the borrowed area) at
+ // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
+ // transferring control to the OS's wakeup vector in the FACS.
+ //
+ // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
+ // restore the original contents. Furthermore, we expect all such PEIMs
+ // (CpuMpPei included) to claim the borrowed areas by producing memory
+ // allocation HOBs, and to honor preexistent memory allocation HOBs when
+ // looking for an area to borrow.
+ //
+ AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+ } else {
+ //
+ // Create memory HOBs
+ //
+ AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ UINT32 TsegSize;
+
+ TsegSize = mX58TsegMbytes * SIZE_1MB;
+ AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
+ AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,
+ TRUE);
+
+ BufferSize = sizeof(EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);
+ SmramRanges = 1;
+
+ Hob.Raw = BuildGuidHob(
+ &gEfiSmmPeiSmramMemoryReserveGuid,
+ BufferSize
+ );
+ ASSERT(Hob.Raw);
+
+ SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)(Hob.Raw);
+ SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;
+
+ SmramIndex = 0;
+ for (Index = 0; Index < SmramRanges; Index++) {
+ //
+ // This is an SMRAM range, create an SMRAM descriptor
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = LowerMemorySize - TsegSize;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = LowerMemorySize - TsegSize;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = TsegSize;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+ SmramIndex++;
+ }
+
+ } else {
+ AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
+ }
+
+ //
+ // If QEMU presents an E820 map, then create memory HOBs for the >=4GB RAM
+ // entries. Otherwise, create a single memory HOB with the flat >=4GB
+ // memory size read from the CMOS.
+ //
+ if (UpperMemorySize != 0) {
+ AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
+ }
+ }
+}
+
+/**
+ Publish system RAM and reserve memory regions
+
+**/
+VOID
+InitializeRamRegions (
+ VOID
+ )
+{
+ QemuInitializeRam ();
+
+ if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) {
+ //
+ // This is the memory range that will be used for PEI on S3 resume
+ //
+ BuildMemoryAllocationHob (
+ mS3AcpiReservedMemoryBase,
+ mS3AcpiReservedMemorySize,
+ EfiACPIMemoryNVS
+ );
+
+ //
+ // Cover the initial RAM area used as stack and temporary PEI heap.
+ //
+ // This is reserved as ACPI NVS so it can be used on S3 resume.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdSimicsSecPeiTempRamBase),
+ PcdGet32 (PcdSimicsSecPeiTempRamSize),
+ EfiACPIMemoryNVS
+ );
+
+ //
+ // SEC stores its table of GUIDed section handlers here.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet64 (PcdGuidedExtractHandlerTableAddress),
+ PcdGet32 (PcdGuidedExtractHandlerTableSize),
+ EfiACPIMemoryNVS
+ );
+
+ }
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // Reserve the lock box storage area
+ //
+ // Since this memory range will be used on S3 resume, it must be
+ // reserved as ACPI NVS.
+ //
+ // If S3 is unsupported, then various drivers might still write to the
+ // LockBox area. We ought to prevent DXE from serving allocation requests
+ // such that they would overlap the LockBox storage.
+ //
+ ZeroMem (
+ (VOID*)(UINTN) PcdGet32 (PcdSimicsLockBoxStorageBase),
+ (UINTN) PcdGet32 (PcdSimicsLockBoxStorageSize)
+ );
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdSimicsLockBoxStorageBase),
+ (UINT64)(UINTN) PcdGet32 (PcdSimicsLockBoxStorageSize),
+ mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+ }
+
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ UINT32 TsegSize;
+
+ //
+ // Make sure the TSEG area that we reported as a reserved memory resource
+ // cannot be used for reserved memory allocations.
+ //
+ TsegSize = mX58TsegMbytes * SIZE_1MB;
+ BuildMemoryAllocationHob (
+ GetSystemMemorySizeBelow4gb() - TsegSize,
+ TsegSize,
+ EfiReservedMemoryType
+ );
+ }
+ }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
new file mode 100644
index 0000000000..2fe34b02c4
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.c
@@ -0,0 +1,630 @@
+/** @file
+ Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Ppi/MasterBootMode.h>
+#include <IndustryStandard/Pci22.h>
+#include <SimicsPlatforms.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+ { EfiACPIMemoryNVS, 0x004 },
+ { EfiACPIReclaimMemory, 0x008 },
+ { EfiReservedMemoryType, 0x004 },
+ { EfiRuntimeServicesData, 0x024 },
+ { EfiRuntimeServicesCode, 0x030 },
+ { EfiBootServicesCode, 0x180 },
+ { EfiBootServicesData, 0xF00 },
+ { EfiMaxMemoryType, 0x000 }
+};
+
+
+EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+ }
+};
+
+
+UINT16 mHostBridgeDevId;
+
+EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+BOOLEAN mS3Supported = FALSE;
+
+UINT32 mMaxCpuCount;
+
+VOID
+AddIoMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize,
+ BOOLEAN Cacheable
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ (Cacheable ?
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :
+ 0
+ ) |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+VOID
+AddIoMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+AddUntestedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+
+VOID
+AddUntestedMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddUntestedMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+VOID
+AddFlashDeviceRange (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_FIRMWARE_DEVICE,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ MemoryBase,
+ MemorySize
+ );
+
+ BuildMemoryAllocationHob (
+ MemoryBase,
+ MemorySize,
+ EfiMemoryMappedIO
+ );
+}
+
+VOID
+MemMapInitialization (
+ VOID
+ )
+{
+ UINT64 PciIoBase;
+ UINT64 PciIoSize;
+
+ UINT32 TopOfLowRam;
+ UINT64 PciExBarBase;
+ UINT32 PciBase;
+ UINT32 PciSize;
+
+ PciIoBase = 0xC000;
+ PciIoSize = 0x4000;
+
+ //
+ // Create Memory Type Information HOB
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultMemoryTypeInformation,
+ sizeof(mDefaultMemoryTypeInformation)
+ );
+
+ //
+ // Video memory + Legacy BIOS region
+ //
+ AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
+
+ TopOfLowRam = GetSystemMemorySizeBelow4gb ();
+ PciExBarBase = 0;
+ if (mHostBridgeDevId == INTEL_ICH10_DEVICE_ID) {
+ //
+ // The MMCONFIG area is expected to fall between the top of low RAM and
+ // the base of the 32-bit PCI host aperture.
+ //
+ PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
+ ASSERT (TopOfLowRam <= PciExBarBase);
+ ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
+ PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
+ } else {
+ PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
+ }
+
+ //
+ // address purpose size
+ // ------------ -------- -------------------------
+ // 0x00000000 TopOfLowRam 0xDF000000
+ // 0xDF000000 Tseg+UMA 0x01000000
+ // 0xE0000000 PciExBarBase 0x10000000
+ // 0xF0000000 PciBase 0x0C000000
+ // -------------------------------------------------
+ // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
+ // 0xFC000000 gap 44 MB
+ // 0xFEC00000 IO-APIC 4 KB
+ // 0xFEC01000 gap 1020 KB
+ // 0xFED00000 HPET 1 KB
+ // 0xFED00400 gap 111 KB
+ // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
+ // 0xFED20000 gap 896 KB
+ // 0xFEE00000 LAPIC 1 MB
+ //
+ PciSize = 0xFC000000 - PciBase;
+ AddIoMemoryBaseSizeHob (PciBase, PciSize);
+ PcdSet64 (PcdPciMmio32Base, PciBase);
+ PcdSet64 (PcdPciMmio32Size, PciSize);
+ AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
+ AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
+ if (mHostBridgeDevId == INTEL_ICH10_DEVICE_ID) {
+ AddIoMemoryBaseSizeHob (ICH10_ROOT_COMPLEX_BASE, SIZE_16KB);
+ //
+ // Note: there should be an
+ //
+ // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
+ // BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB, EfiMemoryMappedIO);
+ //
+ // call below, just like the one above for RCBA. However, Linux insists
+ // that the MMCONFIG area be marked in the E820 or UEFI memory map as
+ // "reserved memory" -- Linux does not content itself with a simple gap
+ // in the memory map wherever the MCFG ACPI table points to.
+ //
+ // This appears to be a safety measure. The PCI Firmware Specification
+ // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
+ // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
+ // [...]". (Emphasis added here.)
+ //
+ // Normally we add memory resource descriptor HOBs in
+ // QemuInitializeRam(), and pre-allocate from those with memory
+ // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
+ // is most definitely not RAM; so, as an exception, cover it with
+ // uncacheable reserved memory right here.
+ //
+ AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
+ BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
+ EfiReservedMemoryType);
+ }
+ AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
+
+ // Add PCI IO Port space available for PCI resource allocations.
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_IO,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
+ PciIoBase,
+ PciIoSize
+ );
+ PcdSet64 (PcdPciIoBase, PciIoBase);
+ PcdSet64 (PcdPciIoSize, PciIoSize);
+
+ //
+ // Add flash range.
+ //
+ AddFlashDeviceRange (PcdGet32(PcdFlashAreaBaseAddress), PcdGet32(PcdFlashAreaSize));
+ //
+ // Video memory / ABSEG
+ //
+ AddIoMemoryBaseSizeHob (0x0A0000, 0x20000);
+ //
+ // Legacy BIOS region.
+ //
+ AddReservedMemoryBaseSizeHob (0xC0000, 0x40000, TRUE);
+}
+
+VOID
+MiscInitialization (
+ VOID
+ )
+{
+ UINTN PmCmd;
+ UINTN Pmba;
+ UINT32 PmbaAndVal;
+ UINT32 PmbaOrVal;
+ UINTN AcpiCtlReg;
+ UINT8 AcpiEnBit;
+
+ //
+ // Disable A20 Mask
+ //
+ IoOr8 (0x92, BIT1);
+
+ //
+ // Build the CPU HOB with guest RAM size dependent address width and 16-bits
+ // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
+ // S3 resume as well, so we build it unconditionally.)
+ //
+ BuildCpuHob (mPhysMemAddressWidth, 16);
+
+ //
+ // Determine platform type and save Host Bridge DID to PCD
+ //
+ switch (mHostBridgeDevId) {
+ case INTEL_82441_DEVICE_ID:
+ PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
+ Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+ PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
+ PmbaOrVal = PIIX4_PMBA_VALUE;
+ AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
+ AcpiEnBit = PIIX4_PMREGMISC_PMIOSE;
+ break;
+ case INTEL_ICH10_DEVICE_ID:
+ PmCmd = POWER_MGMT_REGISTER_ICH10 (PCI_COMMAND_OFFSET);
+ Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
+ PmbaAndVal = ~(UINT32)ICH10_PMBASE_MASK;
+ PmbaOrVal = ICH10_PMBASE_VALUE;
+ AcpiCtlReg = POWER_MGMT_REGISTER_ICH10 (ICH10_ACPI_CNTL);
+ AcpiEnBit = ICH10_ACPI_CNTL_ACPI_EN;
+ break;
+ default:
+ DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__, mHostBridgeDevId));
+ ASSERT (FALSE);
+ return;
+ }
+ PcdSet16 (PcdSimicsX58HostBridgePciDevId, mHostBridgeDevId);
+
+ //
+ // If the appropriate IOspace enable bit is set, assume the ACPI PMBA
+ // has been configured and skip the setup here.
+ // This matches the logic in AcpiTimerLibConstructor ().
+ //
+ if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
+ //
+ // The PEI phase should be exited with fully accessibe ACPI PM IO space:
+ // 1. set PMBA
+ //
+ PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
+
+ //
+ // 2. set PCICMD/IOSE
+ //
+ PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
+
+ //
+ // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
+ //
+ PciOr8 (AcpiCtlReg, AcpiEnBit);
+ }
+
+ if (mHostBridgeDevId == INTEL_ICH10_DEVICE_ID) {
+ //
+ // Set Root Complex Register Block BAR
+ //
+ PciWrite32 (
+ POWER_MGMT_REGISTER_ICH10 (ICH10_RCBA),
+ ICH10_ROOT_COMPLEX_BASE | ICH10_RCBA_EN
+ );
+
+ }
+ //
+ // Set the PM I/O base address to 0x400
+ //
+ PciAndThenOr32 (
+ PCI_LIB_ADDRESS (
+ 0,
+ 31,
+ 0,
+ 0x40
+ ),
+ (UINT32) ~0xfc0, ICH10_PMBASE_VALUE
+ );
+ //
+ // Enable AHCI and all ports on the SATA controller.
+ //
+ // Address MAP Reg, setting AHCI mode
+ //
+ PciOr16 (PCI_LIB_ADDRESS (0, 31, 2, 0x90), 0x0060);
+ //
+ //Enabling Ports 0-5
+ //
+ PciOr16 (PCI_LIB_ADDRESS (0, 31, 2, 0x92), 0x003F);
+ //
+ //Disabling Sata Controller 2, bit 25 = 1, bit 0 = 1
+ //
+ MmioWrite32(0xFED1F418, 0x02000001);
+ //
+ //Enable HPET at FED0_0000h – FED0_03FFh
+ //
+ MmioWrite8(ICH10_ROOT_COMPLEX_BASE + 0x3404, 0x80);
+ //
+ //Config and enable APIC
+ //
+ MmioWrite32(0xFEC00000 + 0X0, 0);
+ MmioWrite32(0xFEC00000 + 0X10, PcdGet8(PcdIoApicId)<<24);
+ MmioWrite8(ICH10_ROOT_COMPLEX_BASE + 0x31FF, 0x01);
+}
+
+
+VOID
+BootModeInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG((EFI_D_INFO, "modeValue = %x\n", IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12)));
+ if (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) == 0x5) {
+ mBootMode = BOOT_ON_S3_RESUME;
+ }
+
+ Status = PeiServicesSetBootMode (mBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesInstallPpi (mPpiBootMode);
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+VOID
+ReserveEmuVariableNvStore (
+ )
+{
+ EFI_PHYSICAL_ADDRESS VariableStore;
+
+ //
+ // Allocate storage for NV variables early on so it will be
+ // at a consistent address. Since VM memory is preserved
+ // across reboots, this allows the NV variable storage to survive
+ // a VM reboot.
+ //
+ VariableStore =
+ (EFI_PHYSICAL_ADDRESS)(UINTN)
+ AllocateRuntimePages (
+ EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
+ );
+ DEBUG ((EFI_D_INFO,
+ "Reserved variable store memory: 0x%lX; size: %dkb\n",
+ VariableStore,
+ (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
+ ));
+ PcdSet64 (PcdEmuVariableNvStoreReserved, VariableStore);
+}
+
+
+VOID
+SimicsVersionCheck(
+ VOID
+ )
+{
+
+ UINTN PciAddrPtr;
+ UINT8 CapOffset;
+ STATIC CHAR8 SimicsStr[0x100];
+ UINTN i;
+ UINT32 MajorVersion;
+ UINT32 MinorVersion;
+ UINT32 ModelNumber;
+
+ PciAddrPtr = PCI_LIB_ADDRESS(0, SIMICS_SIDEBANDPCI_DEV, SIMICS_SIDEBANDPCI_FUNC, 0);
+ CapOffset = PciRead8(PciAddrPtr + PCI_CAPBILITY_POINTER_OFFSET);
+ if (CapOffset != 0xFF) {
+ ModelNumber = PciRead32(PciAddrPtr + CapOffset + 4);
+ MajorVersion = PciRead32(PciAddrPtr + CapOffset + 8);
+ MinorVersion = PciRead32(PciAddrPtr + CapOffset + 0xc);
+ for (i = 0; i < 0x80; i++) {
+ SimicsStr[i] = PciRead8(PciAddrPtr + CapOffset + 0x10 + i);
+ }
+ DEBUG((EFI_D_INFO, "=============SIMICS Version info=============\n"));
+ DEBUG((EFI_D_INFO, "Model number = %d\n", ModelNumber));
+ DEBUG((EFI_D_INFO, "Major version = %d\n", MajorVersion));
+ DEBUG((EFI_D_INFO, "Minor version = %d\n", MinorVersion));
+ DEBUG((EFI_D_INFO, "%a\n", SimicsStr));
+ DEBUG((EFI_D_INFO, "=============================================\n"));
+ }
+}
+
+VOID
+DebugDumpCmos (
+ VOID
+ )
+{
+ UINT32 Loop;
+
+ DEBUG ((EFI_D_INFO, "CMOS:\n"));
+
+ for (Loop = 0; Loop < 0x80; Loop++) {
+ if ((Loop % 0x10) == 0) {
+ DEBUG ((EFI_D_INFO, "%02x:", Loop));
+ }
+ DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));
+ if ((Loop % 0x10) == 0xf) {
+ DEBUG ((EFI_D_INFO, "\n"));
+ }
+ }
+}
+
+
+/**
+ Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules.
+ Set the mMaxCpuCount variable.
+**/
+VOID
+MaxCpuCountInitialization (
+ VOID
+ )
+{
+ mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ return;
+}
+
+/**
+ Determine if S3 support is explicitly enabled.
+
+ @retval TRUE If S3 support is explicitly enabled. Other functions in this
+ library may be called (subject to their individual
+ restrictions).
+
+ FALSE Otherwise. This includes unavailability of the firmware
+ configuration interface. No other function in this library
+ must be called.
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgS3Enabled(
+ VOID
+)
+{
+ //TO DO IF NEEDED
+ return TRUE;
+}
+
+/**
+ Perform Platform PEI initialization.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatform (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n"));
+
+ SimicsVersionCheck ();
+ DebugDumpCmos ();
+
+ if (QemuFwCfgS3Enabled ()) {
+ DEBUG ((EFI_D_INFO, "S3 support was detected on SIMICS\n"));
+ mS3Supported = TRUE;
+ Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
+ ASSERT_EFI_ERROR (Status);
+ }
+ AddressWidthInitialization ();
+ MaxCpuCountInitialization ();
+
+ mHostBridgeDevId = PciRead16(SIMICS_HOSTBRIDGE_DID);
+
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ X58TsegMbytesInitialization ();
+ }
+
+ PublishPeiMemory ();
+
+ InitializeRamRegions ();
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+ ReserveEmuVariableNvStore ();
+ }
+ MemMapInitialization ();
+ }
+
+ MiscInitialization ();
+ InstallFeatureControlCallback ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
new file mode 100644
index 0000000000..7165c0a0c3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
@@ -0,0 +1,148 @@
+/** @file
+ This driver installs SMBIOS information for QSP
+
+ Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+ Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "SmbiosPlatformDxe.h"
+
+
+/**
+Reads 8-bits of CMOS data.
+
+Reads the 8-bits of CMOS data at the location specified by Index.
+The 8-bit read value is returned.
+
+@param Index The CMOS location to read.
+
+@return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8(
+ IN UINTN Index
+ )
+{
+ IoWrite8(0x70, (UINT8)Index);
+ return IoRead8(0x71);
+}
+
+UINT32
+GetSystemMemorySizeBelow4gb(
+ VOID
+ )
+{
+ UINT8 Cmos0x34;
+ UINT8 Cmos0x35;
+
+ //
+ // CMOS 0x34/0x35 specifies the system memory above 16 MB.
+ // * CMOS(0x35) is the high byte
+ // * CMOS(0x34) is the low byte
+ // * The size is specified in 64kb chunks
+ // * Since this is memory above 16MB, the 16MB must be added
+ // into the calculation to get the total memory size.
+ //
+
+ Cmos0x34 = (UINT8)CmosRead8(0x34);
+ Cmos0x35 = (UINT8)CmosRead8(0x35);
+
+ return (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+}
+
+STATIC
+UINT64
+GetSystemMemorySizeAbove4gb(
+ VOID
+)
+{
+ UINT32 Size;
+ UINTN CmosIndex;
+
+ //
+ // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
+ // * CMOS(0x5d) is the most significant size byte
+ // * CMOS(0x5c) is the middle size byte
+ // * CMOS(0x5b) is the least significant size byte
+ // * The size is specified in 64kb chunks
+ //
+
+ Size = 0;
+ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+ Size = (UINT32)(Size << 8) + (UINT32)CmosRead8(CmosIndex);
+ }
+
+ return LShiftU64(Size, 16);
+}
+
+/**
+ Installs SMBIOS information for SIMICS QSP
+
+ @param ImageHandle Module's image handle
+ @param SystemTable Pointer of EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS Smbios data successfully installed
+ @retval Other Smbios data was not installed
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosTablePublishEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ SMBIOS_TABLE_TYPE19 *Type19Record;
+ EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;
+ UINT8 NumSlots;
+ UINT64 TotalMemorySize;
+
+ //
+ // Find the SMBIOS protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiSmbiosProtocolGuid,
+ NULL,
+ (VOID**)&Smbios
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Generate Memory Array Mapped Address info
+ //
+ NumSlots = 2;
+ TotalMemorySize = 0;
+ TotalMemorySize = GetSystemMemorySizeBelow4gb();
+ Type19Record = AllocatePool(sizeof(SMBIOS_TABLE_TYPE19));
+ ZeroMem(Type19Record, sizeof(SMBIOS_TABLE_TYPE19));
+ Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
+ Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);
+ Type19Record->Hdr.Handle = 0;
+ Type19Record->StartingAddress = 0;
+ Type19Record->EndingAddress = (UINT32)RShiftU64(TotalMemorySize, 10) - 1;
+ Type19Record->MemoryArrayHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Type19Record->PartitionWidth = (UINT8)(NumSlots);
+
+ MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add(Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*)Type19Record);
+ ASSERT_EFI_ERROR(Status);
+
+ TotalMemorySize = GetSystemMemorySizeAbove4gb();
+ Type19Record->StartingAddress = 0xFFFFFFFF;
+ Type19Record->ExtendedStartingAddress = 0xFFFFFFFF;
+ Type19Record->ExtendedEndingAddress = TotalMemorySize + 0xFFFFFFFF - 1;
+
+ MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add(Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*)Type19Record);
+ FreePool(Type19Record);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h b/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
new file mode 100644
index 0000000000..acb2c4eee4
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Guid/SimicsBoardConfig.h
@@ -0,0 +1,18 @@
+/** @file
+ GUID for UEFI variables that are specific to Simics Board configuration.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SIMICS_BOARD_CONFIG_H__
+#define __SIMICS_BOARD_CONFIG_H__
+
+#define SIMICS_BOARD_CONFIG_GUID \
+{0x8a318e00, 0xfaf5, 0x499f, { 0x91,0x75, 0xce, 0x4d, 0x8d, 0xa6, 0x70, 0xae}}
+
+extern EFI_GUID gSimicsBoardConfigGuid;
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
new file mode 100644
index 0000000000..a2225493f7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/I440FxPiix4.h
@@ -0,0 +1,50 @@
+/** @file
+ Various register numbers and value bits based on the following publications:
+ - Intel(R) datasheet 290549-001
+ - Intel(R) datasheet 290562-001
+ - Intel(R) datasheet 297654-006
+ - Intel(R) datasheet 297738-017
+
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __I440FX_PIIX4_H__
+#define __I440FX_PIIX4_H__
+
+#include <Library/PciLib.h>
+
+//
+// Host Bridge Device ID (DID) value for I440FX
+//
+#define INTEL_82441_DEVICE_ID 0x1237
+
+//
+// B/D/F/Type: 0/0/0/PCI
+//
+#define PMC_REGISTER_PIIX4(Offset) PCI_LIB_ADDRESS (0, 0, 0, (Offset))
+
+#define PIIX4_PAM0 0x59
+#define PIIX4_PAM1 0x5A
+#define PIIX4_PAM2 0x5B
+#define PIIX4_PAM3 0x5C
+#define PIIX4_PAM4 0x5D
+#define PIIX4_PAM5 0x5E
+#define PIIX4_PAM6 0x5F
+
+//
+// B/D/F/Type: 0/1/3/PCI
+//
+#define POWER_MGMT_REGISTER_PIIX4(Offset) PCI_LIB_ADDRESS (0, 1, 3, (Offset))
+
+#define PIIX4_PMBA 0x40
+#define PIIX4_PMBA_MASK (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | \
+ BIT10 | BIT9 | BIT8 | BIT7 | BIT6)
+
+#define PIIX4_PMREGMISC 0x80
+#define PIIX4_PMREGMISC_PMIOSE BIT0
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
new file mode 100644
index 0000000000..2708b1891d
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/IndustryStandard/LinuxBzImage.h
@@ -0,0 +1,159 @@
+/** @file
+
+ Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LINUX_BZIMAGE_H__
+#define __LINUX_BZIMAGE_H__
+
+#define BOOTSIG 0x1FE
+#define SETUP_HDR 0x53726448 /* 0x53726448 == "HdrS" */
+
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3
+#define E820_NVS 4
+#define E820_UNUSABLE 5
+
+#pragma pack(1)
+
+struct setup_header {
+ UINT8 setup_secs; /* Sectors for setup code */
+ UINT16 root_flags;
+ UINT32 sys_size;
+ UINT16 ram_size;
+ UINT16 video_mode;
+ UINT16 root_dev;
+ UINT16 signature; /* Boot signature */
+ UINT16 jump;
+ UINT32 header;
+ UINT16 version;
+ UINT16 su_switch;
+ UINT16 setup_seg;
+ UINT16 start_sys;
+ UINT16 kernel_ver;
+ UINT8 loader_id;
+ UINT8 load_flags;
+ UINT16 movesize;
+ UINT32 code32_start; /* Start of code loaded high */
+ UINT32 ramdisk_start; /* Start of initial ramdisk */
+ UINT32 ramdisk_len; /* Length of initial ramdisk */
+ UINT32 bootsect_kludge;
+ UINT16 heap_end;
+ UINT8 ext_loader_ver; /* Extended boot loader version */
+ UINT8 ext_loader_type; /* Extended boot loader ID */
+ UINT32 cmd_line_ptr; /* 32-bit pointer to the kernel command line */
+ UINT32 ramdisk_max; /* Highest legal initrd address */
+ UINT32 kernel_alignment; /* Physical addr alignment required for kernel */
+ UINT8 relocatable_kernel; /* Whether kernel is relocatable or not */
+ UINT8 min_alignment;
+ UINT16 xloadflags;
+ UINT32 cmdline_size;
+ UINT32 hardware_subarch;
+ UINT64 hardware_subarch_data;
+ UINT32 payload_offset;
+ UINT32 payload_length;
+ UINT64 setup_data;
+ UINT64 pref_address;
+ UINT32 init_size;
+ UINT32 handover_offset;
+};
+
+struct efi_info {
+ UINT32 efi_loader_signature;
+ UINT32 efi_systab;
+ UINT32 efi_memdesc_size;
+ UINT32 efi_memdesc_version;
+ UINT32 efi_memmap;
+ UINT32 efi_memmap_size;
+ UINT32 efi_systab_hi;
+ UINT32 efi_memmap_hi;
+};
+
+struct e820_entry {
+ UINT64 addr; /* start of memory segment */
+ UINT64 size; /* size of memory segment */
+ UINT32 type; /* type of memory segment */
+};
+
+struct screen_info {
+ UINT8 orig_x; /* 0x00 */
+ UINT8 orig_y; /* 0x01 */
+ UINT16 ext_mem_k; /* 0x02 */
+ UINT16 orig_video_page; /* 0x04 */
+ UINT8 orig_video_mode; /* 0x06 */
+ UINT8 orig_video_cols; /* 0x07 */
+ UINT8 flags; /* 0x08 */
+ UINT8 unused2; /* 0x09 */
+ UINT16 orig_video_ega_bx;/* 0x0a */
+ UINT16 unused3; /* 0x0c */
+ UINT8 orig_video_lines; /* 0x0e */
+ UINT8 orig_video_isVGA; /* 0x0f */
+ UINT16 orig_video_points;/* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ UINT16 lfb_width; /* 0x12 */
+ UINT16 lfb_height; /* 0x14 */
+ UINT16 lfb_depth; /* 0x16 */
+ UINT32 lfb_base; /* 0x18 */
+ UINT32 lfb_size; /* 0x1c */
+ UINT16 cl_magic, cl_offset; /* 0x20 */
+ UINT16 lfb_linelength; /* 0x24 */
+ UINT8 red_size; /* 0x26 */
+ UINT8 red_pos; /* 0x27 */
+ UINT8 green_size; /* 0x28 */
+ UINT8 green_pos; /* 0x29 */
+ UINT8 blue_size; /* 0x2a */
+ UINT8 blue_pos; /* 0x2b */
+ UINT8 rsvd_size; /* 0x2c */
+ UINT8 rsvd_pos; /* 0x2d */
+ UINT16 vesapm_seg; /* 0x2e */
+ UINT16 vesapm_off; /* 0x30 */
+ UINT16 pages; /* 0x32 */
+ UINT16 vesa_attributes; /* 0x34 */
+ UINT32 capabilities; /* 0x36 */
+ UINT8 _reserved[6]; /* 0x3a */
+};
+
+struct boot_params {
+struct screen_info screen_info;
+ UINT8 apm_bios_info[0x14];
+ UINT8 _pad2[4];
+ UINT64 tboot_addr;
+ UINT8 ist_info[0x10];
+ UINT8 _pad3[16];
+ UINT8 hd0_info[16];
+ UINT8 hd1_info[16];
+ UINT8 sys_desc_table[0x10];
+ UINT8 olpc_ofw_header[0x10];
+ UINT8 _pad4[128];
+ UINT8 edid_info[0x80];
+ struct efi_info efi_info;
+ UINT32 alt_mem_k;
+ UINT32 scratch;
+ UINT8 e820_entries;
+ UINT8 eddbuf_entries;
+ UINT8 edd_mbr_sig_buf_entries;
+ UINT8 _pad6[6];
+ struct setup_header hdr;
+ UINT8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+ UINT32 edd_mbr_sig_buffer[16];
+ struct e820_entry e820_map[128];
+ UINT8 _pad8[48];
+ UINT8 eddbuf[0x1ec];
+ UINT8 _pad9[276];
+};
+
+typedef struct {
+ UINT16 limit;
+ UINT64 *base;
+} dt_addr_t;
+
+#pragma pack()
+
+extern EFI_STATUS setup_graphics(struct boot_params *buf);
+
+#endif /* __LINUX_BZIMAGE_H__ */
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
new file mode 100644
index 0000000000..483f8d4b9c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/LoadLinuxLib.h
@@ -0,0 +1,205 @@
+/** @file
+ Load/boot UEFI Linux.
+
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LOAD_LINUX_LIB__
+#define __LOAD_LINUX_LIB__
+
+
+/**
+ Verifies that the kernel setup image is valid and supported.
+ The kernel setup image should be checked before using other library
+ routines which take the kernel setup as an input.
+
+ @param[in] KernelSetup - The kernel setup image
+ @param[in] KernelSetupSize - The kernel setup size
+
+ @retval EFI_SUCCESS - The Linux kernel setup is valid and supported
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxCheckKernelSetup (
+ IN VOID *KernelSetup,
+ IN UINTN KernelSetupSize
+ );
+
+
+/**
+ Gets the initial runtime size of the Linux kernel image by examining
+ the kernel setup image.
+
+ @param[in] KernelSetup - The kernel setup image
+ @param[in] KernelSize - The kernel size on disk.
+
+ @retval 0 An error occurred
+ @retval !0 The initial size required by the kernel to
+ begin execution.
+
+**/
+UINTN
+EFIAPI
+LoadLinuxGetKernelSize (
+ IN VOID *KernelSetup,
+ IN UINTN KernelSize
+ );
+
+
+/**
+ Loads and boots UEFI Linux.
+
+ Note: If successful, then this routine will not return
+
+ @param[in] Kernel - The main kernel image
+ @param[in,out] KernelSetup - The kernel setup image
+
+ @retval EFI_NOT_FOUND - The Linux kernel was not found
+ @retval EFI_INVALID_PARAMETER - Kernel or KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The Linux kernel version is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinux (
+ IN VOID *Kernel,
+ IN OUT VOID *KernelSetup
+ );
+
+
+/**
+ Allocates pages for the kernel setup image.
+
+ @param[in] Pages - The number of pages
+
+ @retval NULL - Unable to allocate pages
+ @retval !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelSetupPages (
+ IN UINTN Pages
+ );
+
+
+/**
+ Clears the uninitialised space before and after the struct setup_header
+ in the kernel setup image. The kernel requires that these be zeroed
+ unless explicitly initialised, so this function should be called after
+ the setup_header has been copied in from a bzImage, before setting up
+ anything else.
+
+ @param[in] KernelSetup - The kernel setup image
+
+ @retval EFI_SUCCESS - The Linux kernel setup was successfully initialized
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxInitializeKernelSetup (
+ IN VOID *KernelSetup
+ );
+
+/**
+ Allocates pages for the kernel.
+
+ @param[in] KernelSetup - The kernel setup image
+ @param[in] Pages - The number of pages. (It is recommended to use the
+ size returned from LoadLinuxGetKernelSize.)
+
+ @retval NULL - Unable to allocate pages
+ @retval !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelPages (
+ IN VOID *KernelSetup,
+ IN UINTN Pages
+ );
+
+
+/**
+ Allocates pages for the kernel command line.
+
+ @param[in] Pages - The number of pages.
+
+ @retval NULL - Unable to allocate pages
+ @retval !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateCommandLinePages (
+ IN UINTN Pages
+ );
+
+
+/**
+ Allocates pages for the initrd image.
+
+ @param[in,out] KernelSetup - The kernel setup image
+ @param[in] Pages - The number of pages.
+
+ @retval NULL - Unable to allocate pages
+ @retval !NULL - The address of the pages allocated
+
+**/
+VOID*
+EFIAPI
+LoadLinuxAllocateInitrdPages (
+ IN VOID *KernelSetup,
+ IN UINTN Pages
+ );
+
+
+/**
+ Sets the kernel command line parameter within the setup image.
+
+ @param[in,out] KernelSetup - The kernel setup image
+ @param[in] CommandLine - The kernel command line
+
+ @retval EFI_SUCCESS - The Linux kernel setup is valid and supported
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxSetCommandLine (
+ IN OUT VOID *KernelSetup,
+ IN CHAR8 *CommandLine
+ );
+
+
+/**
+ Sets the kernel initial ram disk pointer within the setup image.
+
+ @param[in,out] KernelSetup - The kernel setup image
+ @param[in] Initrd - Pointer to the initial ram disk
+ @param[in] InitrdSize - The initial ram disk image size
+
+ @retval EFI_SUCCESS - The Linux kernel setup is valid and supported
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The Linux kernel is not supported
+
+**/
+EFI_STATUS
+EFIAPI
+LoadLinuxSetInitrd (
+ IN OUT VOID *KernelSetup,
+ IN VOID *Initrd,
+ IN UINTN InitrdSize
+ );
+
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
new file mode 100644
index 0000000000..c32f97d787
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/Library/SerializeVariablesLib.h
@@ -0,0 +1,224 @@
+/** @file
+ Serialize & Deserialize UEFI Variables
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __SERIALIZE_VARIABLES_LIB__
+#define __SERIALIZE_VARIABLES_LIB__
+
+
+/**
+ Callback function for each variable
+
+ @param[in] Context - Context as sent to the iteration function
+ @param[in] VariableName - Refer to RuntimeServices GetNextVariableName
+ @param[in] VendorGuid - Refer to RuntimeServices GetNextVariableName
+ @param[in] Attributes - Refer to RuntimeServices GetVariable
+ @param[in] DataSize - Refer to RuntimeServices GetVariable
+ @param[in] Data - Refer to RuntimeServices GetVariable
+
+ @retval RETURN_SUCCESS Continue iterating through the variables
+ @return Any RETURN_ERROR Stop iterating through the variables
+
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *VARIABLE_SERIALIZATION_ITERATION_CALLBACK)(
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+
+/**
+ Creates a new variable serialization instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully created.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstance (
+ OUT EFI_HANDLE *Handle
+ );
+
+
+/**
+ Free memory associated with a variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully freed.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesFreeInstance (
+ IN EFI_HANDLE Handle
+ );
+
+
+/**
+ Creates a new variable serialization instance using the given
+ binary representation of the variables to fill the new instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+ @param[in] Buffer - A buffer with the serialized representation
+ of the variables. Must be the same format as produced
+ by SerializeVariablesToBuffer.
+ @param[in] Size - This is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ imported into a new variable serialization instance
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the new variable serialization instance
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstanceFromBuffer (
+ OUT EFI_HANDLE *Handle,
+ IN VOID *Buffer,
+ IN UINTN Size
+ );
+
+
+/**
+ Iterates all variables found with RuntimeServices GetNextVariableName
+
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateSystemVariables (
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ );
+
+
+/**
+ Iterates all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateInstanceVariables (
+ IN EFI_HANDLE Handle,
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ );
+
+
+/**
+ Sets all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ set all the variables
+ @return Any of RETURN_ERROR indicates an error reading the variables
+ or in attempting to set a variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesSetSerializedVariables (
+ IN EFI_HANDLE Handle
+ );
+
+
+/**
+ Adds a variable to the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] VariableName - Refer to RuntimeServices GetVariable
+ @param[in] VendorGuid - Refer to RuntimeServices GetVariable
+ @param[in] Attributes - Refer to RuntimeServices GetVariable
+ @param[in] DataSize - Refer to RuntimeServices GetVariable
+ @param[in] Data - Refer to RuntimeServices GetVariable
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ add the variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesAddVariable (
+ IN EFI_HANDLE Handle,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+
+/**
+ Serializes the variables known to this instance into the
+ provided buffer.
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[out] Buffer - A buffer to store the binary representation
+ of the variables.
+ @param[in,out] Size - On input this is the size of the buffer.
+ On output this is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ completed and returned in the buffer.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ save the variables to the buffer.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance or
+ Size or Buffer were NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesToBuffer (
+ IN EFI_HANDLE Handle,
+ OUT VOID *Buffer,
+ IN OUT UINTN *Size
+ );
+
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h b/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
new file mode 100644
index 0000000000..67bb3af584
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Include/SimicsPlatforms.h
@@ -0,0 +1,55 @@
+/** @file
+ Simics Platform definitions
+
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SIMICS_PLATFORMS_H__
+#define __SIMICS_PLATFORMS_H__
+
+#include <Library/PciLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <Register/X58Ich10.h>
+#include <IndustryStandard/I440FxPiix4.h>
+
+//
+// Simics Host Bridge DID Address
+//
+#define SIMICS_HOSTBRIDGE_DID \
+ PCI_LIB_ADDRESS (0, 0, 0, PCI_DEVICE_ID_OFFSET)
+
+//
+// Simics SideBand PCI device registers
+//
+#define SIMICS_SIDEBANDPCI_DEV 0
+#define SIMICS_SIDEBANDPCI_FUNC 7
+#define SIMICS_SIDEBANDPCI_SVID \
+ PCI_LIB_ADDRESS (0, 0, 7, PCI_SVID_OFFSET)
+#define SIMICS_SIDEBANDPCI_SDID \
+ PCI_LIB_ADDRESS (0, 0, 7, PCI_SID_OFFSET)
+#define SIMICS_SIDEBANDPCI_CAP \
+ PCI_LIB_ADDRESS (0, 0, 7, PCI_CAPBILITY_POINTER_OFFSET)
+#define SIMICS_SIDEBANDPCI_CAP_Offset 0x40
+#define SIMICS_SIDEBANDPCI_CAP_ID 0xFF
+
+//
+// Values we program into the PM base address registers
+//
+#define PIIX4_PMBA_VALUE 0xB000
+#define ICH10_PMBASE_VALUE 0x0400
+
+//
+// Common bits in same-purpose registers
+//
+#define PMBA_RTE BIT0
+
+//
+// Common IO ports relative to the Power Management Base Address
+//
+#define ACPI_TIMER_OFFSET 0x8
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
new file mode 100644
index 0000000000..ff08c385b3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/DxeLogoLib.inf
@@ -0,0 +1,55 @@
+### @file
+# Module that show progress bar and title above it.
+#
+# General BDS defines and produce general interfaces for platform BDS driver including:
+# 1) BDS boot policy interface;
+# 2) BDS boot device connect interface;
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.
+#
+# Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = DxeLogoLib
+ FILE_GUID = F5AE5B5C-42E8-4A9B-829D-5B631CD5367A
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = LogoLib|DXE_DRIVER UEFI_APPLICATION
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+ BaseLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ PcdLib
+ DxeServicesLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+
+[FeaturePcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
+
+[Sources]
+ Logo.c
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiUgaDrawProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiUserManagerProtocolGuid ## CONSUMES
+ gEfiOemBadgingProtocolGuid ## CONSUMES
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
new file mode 100644
index 0000000000..d2c39c3dfc
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/DxeLogoLib/OemBadging.h
@@ -0,0 +1,83 @@
+/** @file
+ The OEM Badging Protocol defines the interface to get the OEM badging
+ image with the display attribute. This protocol can be produced based on OEM badging images.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EFI_OEM_BADGING_H__
+#define __EFI_OEM_BADGING_H__
+
+//
+// GUID for EFI OEM Badging Protocol
+//
+#define EFI_OEM_BADGING_PROTOCOL_GUID \
+ { 0x170e13c0, 0xbf1b, 0x4218, {0x87, 0x1d, 0x2a, 0xbd, 0xc6, 0xf8, 0x87, 0xbc } }
+
+
+typedef struct _EFI_OEM_BADGING_PROTOCOL EFI_OEM_BADGING_PROTOCOL;
+
+typedef enum {
+ EfiBadgingFormatBMP,
+ EfiBadgingFormatJPEG,
+ EfiBadgingFormatTIFF,
+ EfiBadgingFormatGIF,
+ EfiBadgingFormatUnknown
+} EFI_BADGING_FORMAT;
+
+typedef enum {
+ EfiBadgingDisplayAttributeLeftTop,
+ EfiBadgingDisplayAttributeCenterTop,
+ EfiBadgingDisplayAttributeRightTop,
+ EfiBadgingDisplayAttributeCenterRight,
+ EfiBadgingDisplayAttributeRightBottom,
+ EfiBadgingDisplayAttributeCenterBottom,
+ EfiBadgingDisplayAttributeLeftBottom,
+ EfiBadgingDisplayAttributeCenterLeft,
+ EfiBadgingDisplayAttributeCenter,
+ EfiBadgingDisplayAttributeCustomized
+} EFI_BADGING_DISPLAY_ATTRIBUTE;
+
+/**
+
+ Load an OEM badge image and return its data and attributes.
+
+ @param This The pointer to this protocol instance.
+ @param Instance The visible image instance is found.
+ @param Format The format of the image. Examples: BMP, JPEG.
+ @param ImageData The image data for the badge file. Currently only
+ supports the .bmp file format.
+ @param ImageSize The size of the image returned.
+ @param Attribute The display attributes of the image returned.
+ @param CoordinateX The X coordinate of the image.
+ @param CoordinateY The Y coordinate of the image.
+
+ @retval EFI_SUCCESS The image was fetched successfully.
+ @retval EFI_NOT_FOUND The specified image could not be found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_BADGING_GET_IMAGE)(
+ IN EFI_OEM_BADGING_PROTOCOL *This,
+ IN OUT UINT32 *Instance,
+ OUT EFI_BADGING_FORMAT *Format,
+ OUT UINT8 **ImageData,
+ OUT UINTN *ImageSize,
+ OUT EFI_BADGING_DISPLAY_ATTRIBUTE *Attribute,
+ OUT UINTN *CoordinateX,
+ OUT UINTN *CoordinateY
+);
+
+
+struct _EFI_OEM_BADGING_PROTOCOL {
+ EFI_BADGING_GET_IMAGE GetImage;
+};
+
+
+extern EFI_GUID gEfiOemBadgingProtocolGuid;
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
new file mode 100644
index 0000000000..cdefeebbdd
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/DxeLoadLinuxLib.inf
@@ -0,0 +1,42 @@
+## @file
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeLoadLinuxLib
+ FILE_GUID = 63CC8497-C9D0-46A8-AC08-49DF92A2FF62
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DxeLoadLinuxLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ Linux.c
+ LinuxGdt.c
+
+[Sources.IA32]
+ Ia32/JumpToKernel.nasm
+
+[Sources.X64]
+ X64/JumpToKernel.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MemoryAllocationLib
+ BaseMemoryLib
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
new file mode 100644
index 0000000000..c6f1c31a59
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.nasm
@@ -0,0 +1,41 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToKernel (
+; VOID *KernelStart,
+; VOID *KernelBootParams
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToKernel)
+ASM_PFX(JumpToKernel):
+
+ mov esi, [esp + 8]
+ call DWORD [esp + 4]
+ ret
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToUefiKernel (
+; EFI_HANDLE ImageHandle,
+; EFI_SYSTEM_TABLE *SystemTable,
+; VOID *KernelBootParams,
+; VOID *KernelStart
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToUefiKernel)
+ASM_PFX(JumpToUefiKernel):
+
+ mov eax, [esp + 12]
+ mov eax, [eax + 0x264]
+ add eax, [esp + 16]
+ jmp eax
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
new file mode 100644
index 0000000000..9c0ab80904
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/LoadLinuxLib.h
@@ -0,0 +1,52 @@
+/** @file
+ Boot UEFI Linux.
+
+ Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _LOAD_LINUX_LIB_INCLUDED_
+#define _LOAD_LINUX_LIB_INCLUDED_
+
+#include <Uefi.h>
+#include <Library/LoadLinuxLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <IndustryStandard/LinuxBzImage.h>
+
+#include <Protocol/GraphicsOutput.h>
+
+VOID
+EFIAPI
+JumpToKernel (
+ VOID *KernelStart,
+ VOID *KernelBootParams
+ );
+
+VOID
+EFIAPI
+JumpToUefiKernel (
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable,
+ VOID *KernelBootParams,
+ VOID *KernelStart
+ );
+
+VOID
+InitLinuxDescriptorTables (
+ VOID
+ );
+
+VOID
+SetLinuxDescriptorTables (
+ VOID
+ );
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
new file mode 100644
index 0000000000..2b5395f6f8
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/LoadLinuxLib/X64/JumpToKernel.nasm
@@ -0,0 +1,85 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+ DEFAULT REL
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToKernel (
+; VOID *KernelStart, // rcx
+; VOID *KernelBootParams // rdx
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToKernel)
+ASM_PFX(JumpToKernel):
+
+ ; Set up for executing kernel. BP in %esi, entry point on the stack
+ ; (64-bit when the 'ret' will use it as 32-bit, but we're little-endian)
+ mov rsi, rdx
+ push rcx
+
+ ; Jump into the compatibility mode CS
+ push 0x10
+ lea rax, [.0]
+ push rax
+ DB 0x48, 0xcb ; retfq
+
+.0:
+ ; Now in compatibility mode.
+
+ DB 0xb8, 0x18, 0x0, 0x0, 0x0 ; movl $0x18, %eax
+ DB 0x8e, 0xd8 ; movl %eax, %ds
+ DB 0x8e, 0xc0 ; movl %eax, %es
+ DB 0x8e, 0xe0 ; movl %eax, %fs
+ DB 0x8e, 0xe8 ; movl %eax, %gs
+ DB 0x8e, 0xd0 ; movl %eax, %ss
+
+ ; Disable paging
+ DB 0xf, 0x20, 0xc0 ; movl %cr0, %eax
+ DB 0xf, 0xba, 0xf8, 0x1f ; btcl $31, %eax
+ DB 0xf, 0x22, 0xc0 ; movl %eax, %cr0
+
+ ; Disable long mode in EFER
+ DB 0xb9, 0x80, 0x0, 0x0, 0xc0 ; movl $0x0c0000080, %ecx
+ DB 0xf, 0x32 ; rdmsr
+ DB 0xf, 0xba, 0xf8, 0x8 ; btcl $8, %eax
+ DB 0xf, 0x30 ; wrmsr
+
+ ; Disable PAE
+ DB 0xf, 0x20, 0xe0 ; movl %cr4, %eax
+ DB 0xf, 0xba, 0xf8, 0x5 ; btcl $5, %eax
+ DB 0xf, 0x22, 0xe0 ; movl %eax, %cr4
+
+ DB 0x31, 0xed ; xor %ebp, %ebp
+ DB 0x31, 0xff ; xor %edi, %edi
+ DB 0x31, 0xdb ; xor %ebx, %ebx
+ DB 0xc3 ; ret
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToUefiKernel (
+; EFI_HANDLE ImageHandle, // rcx
+; EFI_SYSTEM_TABLE *SystemTable, // rdx
+; VOID *KernelBootParams // r8
+; VOID *KernelStart, // r9
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(JumpToUefiKernel)
+ASM_PFX(JumpToUefiKernel):
+
+ mov rdi, rcx
+ mov rsi, rdx
+ mov rdx, r8
+ xor rax, rax
+ mov eax, [r8 + 0x264]
+ add r9, rax
+ add r9, 0x200
+ call r9
+ ret
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
new file mode 100644
index 0000000000..80776fd003
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.h
@@ -0,0 +1,55 @@
+/** @file
+ Save Non-Volatile Variables to a file system.
+
+ Copyright (c) 2009 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __NV_VARS_FILE_LIB_INSTANCE__
+#define __NV_VARS_FILE_LIB_INSTANCE__
+
+#include <Uefi.h>
+
+#include <Guid/FileInfo.h>
+
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Library/BaseLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/SerializeVariablesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+/**
+ Loads the non-volatile variables from the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+LoadNvVarsFromFs (
+ EFI_HANDLE FsHandle
+ );
+
+
+/**
+ Saves the non-volatile variables into the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+SaveNvVarsToFs (
+ EFI_HANDLE FsHandle
+ );
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
new file mode 100644
index 0000000000..4731e77865
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
@@ -0,0 +1,53 @@
+## @file
+# NvVarsFileLib
+#
+# This library saves and restores non-volatile variables in a
+# file within a file system.
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NvVarsFileLib
+ FILE_GUID = 8ECD4CC0-1772-4583-8A74-83633A15FAA0
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NvVarsFileLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ FsAccess.c
+ NvVarsFileLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ShellPkg/ShellPkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ MemoryAllocationLib
+ SerializeVariablesLib
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiFileInfoGuid
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
new file mode 100644
index 0000000000..0c75430260
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridge.h
@@ -0,0 +1,68 @@
+/** @file
+ Header file of OVMF instance of PciHostBridgeLib.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+PCI_ROOT_BRIDGE *
+ScanForRootBridges (
+ UINTN *NumberOfRootBridges
+);
+
+/**
+ Initialize a PCI_ROOT_BRIDGE structure.
+
+ @param[in] Supports Supported attributes.
+
+ @param[in] Attributes Initial attributes.
+
+ @param[in] AllocAttributes Allocation attributes.
+
+ @param[in] RootBusNumber The bus number to store in RootBus.
+
+ @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
+ assigned to any subordinate bus found behind any
+ PCI bridge hanging off this root bus.
+
+ The caller is repsonsible for ensuring that
+ RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then the
+ root bus has no room for subordinate buses.
+
+ @param[in] Io IO aperture.
+
+ @param[in] Mem MMIO aperture.
+
+ @param[in] MemAbove4G MMIO aperture above 4G.
+
+ @param[in] PMem Prefetchable MMIO aperture.
+
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
+
+ @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the
+ caller) that should be filled in by this
+ function.
+
+ @retval EFI_SUCCESS Initialization successful. A device path
+ consisting of an ACPI device path node, with
+ UID = RootBusNumber, has been allocated and
+ linked into RootBus.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+**/
+EFI_STATUS
+InitRootBridge (
+ IN UINT64 Supports,
+ IN UINT64 Attributes,
+ IN UINT64 AllocAttributes,
+ IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
+ IN PCI_ROOT_BRIDGE_APERTURE *Io,
+ IN PCI_ROOT_BRIDGE_APERTURE *Mem,
+ IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMem,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
+ OUT PCI_ROOT_BRIDGE *RootBus
+ );
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 0000000000..e1920bd2ff
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Simics's instance of the PCI Host Bridge Library.
+#
+# Copyright (C) 2016, Red Hat, Inc.
+# Copyright (c) 2016 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciHostBridgeLib
+ FILE_GUID = 2F04EC41-C3A0-43EB-AC6A-409F973F4439
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciHostBridgeLib
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ PciHostBridgeLib.c
+ PciHostBridge.h
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ PciLib
+
+[Pcd]
+ gBoardModuleTokenSpaceGuid.PcdPciIoBase
+ gBoardModuleTokenSpaceGuid.PcdPciIoSize
+ gBoardModuleTokenSpaceGuid.PcdPciMmio32Base
+ gBoardModuleTokenSpaceGuid.PcdPciMmio32Size
+ gBoardModuleTokenSpaceGuid.PcdPciMmio64Base
+ gBoardModuleTokenSpaceGuid.PcdPciMmio64Size
+ gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
new file mode 100644
index 0000000000..bc85420f97
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PeiReportFvLib/PeiReportFvLib.inf
@@ -0,0 +1,56 @@
+### @file
+# Component information file for the Report Firmware Volume (FV) library.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiReportFvLib
+ FILE_GUID = 44328FA5-E4DD-4A15-ABDF-C6584AC363D9
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ LIBRARY_CLASS = ReportFvLib
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ PeiServicesLib
+ PcdLib
+ IoLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ SimicsX58SktPkg/SktPkg.dec
+ SimicsIch10Pkg/Ich10Pkg.dec
+
+[Sources]
+ PeiReportFvLib.c
+ Fv.c
+
+[Pcd]
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPostMemoryBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPostMemorySize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvUefiBootBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvUefiBootSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvOsBootBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvOsBootSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvSecurityBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvSecuritySize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvAdvancedBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvAdvancedSize ## CONSUMES
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
+ gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000000..01ba20d2da
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,172 @@
+/** @file
+ Platform BDS customizations include file.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/PeImage.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/NvVarsFileLib.h>
+
+#include <Protocol/Decompress.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/S3SaveState.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Guid/Acpi.h>
+#include <Guid/SmBios.h>
+#include <Guid/Mps.h>
+#include <Guid/HobList.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+
+#include <SimicsPlatforms.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH gUartDeviceNode;
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+ { \
+ { \
+ HARDWARE_DEVICE_PATH, \
+ HW_PCI_DP, \
+ { \
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ (Func), \
+ (Dev) \
+ }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+ { \
+ { \
+ ACPI_DEVICE_PATH, \
+ ACPI_DP, \
+ { \
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+ }, \
+ }, \
+ EISA_PNP_ID((PnpId)), \
+ 0 \
+ }
+
+#define gPciIsaBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+ PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+ PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_UART_DP, \
+ { \
+ (UINT8) (sizeof (UART_DEVICE_PATH)), \
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ 0, \
+ 115200, \
+ 8, \
+ 1, \
+ 1 \
+ }
+
+#define gPcAnsiTerminal \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_VENDOR_DP, \
+ { \
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ DEVICE_PATH_MESSAGING_PC_ANSI \
+ }
+
+#define PCI_CLASS_SCC 0x07
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_16550 0x02
+#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN BIT1
+#define STD_ERROR BIT2
+extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformInitializeConsole (
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ );
+
+/**
+ Use SystemTable ConOut to stop video based Simple Text Out consoles from going
+ to the video device. Put up LogoFile on every video device that is a console.
+
+ @param[in] LogoFile The file name of logo to display on the center of the screen.
+
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
+ @retval EFI_UNSUPPORTED Logo not found.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableBootLogo(
+ IN EFI_GUID *LogoFile
+);
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100644
index 0000000000..cdb6e242e8
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,72 @@
+## @file
+# Platform BDS customizations library.
+#
+# Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformBootManagerLib
+ FILE_GUID = 8AE4756F-0C71-4C06-84D4-4C71F204D514
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ OvmfPkg/OvmfPkg.dec
+ SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ UefiBootManagerLib
+ BootLogoLib
+ DevicePathLib
+ PciLib
+ NvVarsFileLib
+ DxeLoadLinuxLib
+ UefiLib
+ LogoLib
+
+[Pcd]
+ gBoardModuleTokenSpaceGuid.PcdEmuVariableEvent
+ gBoardModuleTokenSpaceGuid.PcdOvmfFlashVariablesEnable
+ gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+ gBoardModuleTokenSpaceGuid.PcdShellFile
+ gBoardModuleTokenSpaceGuid.PcdLogoFile
+
+[Pcd.IA32, Pcd.X64]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock
+
+[Protocols]
+ gEfiDecompressProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
new file mode 100644
index 0000000000..9b4c2a629a
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
@@ -0,0 +1,33 @@
+/** @file
+ Serialize Variables Library implementation
+
+ Copyright (c) 2009 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __SERIALIZE_VARIABLES_LIB_INSTANCE__
+#define __SERIALIZE_VARIABLES_LIB_INSTANCE__
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SerializeVariablesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#define SV_FROM_HANDLE(a) CR (a, SV_INSTANCE, Signature, SV_SIGNATURE)
+#define SV_SIGNATURE SIGNATURE_32 ('S', 'V', 'A', 'R')
+
+typedef struct {
+ UINT32 Signature;
+ VOID *BufferPtr;
+ UINTN BufferSize;
+ UINTN DataSize;
+} SV_INSTANCE;
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
new file mode 100644
index 0000000000..08c561f586
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Serialize Variables Library implementation
+#
+# This library serializes and deserializes UEFI variables
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeSerializeVariablesLib
+ FILE_GUID = 266A1434-6B22-441F-A8D2-D54AA8FDF95C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerializeVariablesLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER
+
+[Sources]
+ SerializeVariablesLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ShellPkg/ShellPkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
new file mode 100644
index 0000000000..6be3b301ad
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyInitLib/SiliconPolicyInitLib.inf
@@ -0,0 +1,38 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SiliconPolicyInitLib
+ FILE_GUID = B494DF39-A5F8-48A1-B2D0-EF523AD91C55
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SiliconPolicyInitLib
+
+[Sources]
+ SiliconPolicyInitLib.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ DebugPrintErrorLevelLib
+ HobLib
+ IoLib
+ MemoryAllocationLib
+ PeiServicesLib
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
new file mode 100644
index 0000000000..4fde3c75a6
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/Policy/Library/SiliconPolicyUpdateLib/SiliconPolicyUpdateLib.inf
@@ -0,0 +1,35 @@
+## @file
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SiliconPolicyUpdateLib
+ FILE_GUID = 6EA9585C-3C15-47da-9FFC-25E9E4EA4D0C
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SiliconPolicyUpdateLib
+
+[Sources]
+ SiliconPolicyUpdateLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ HobLib
+ IoLib
+ PcdLib
+
+[Pcd]
+
+[FixedPcd]
+
+[Ppis]
+
+[Guids]
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm b/Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
new file mode 100644
index 0000000000..adb87de943
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/Ia32/SecEntry.nasm
@@ -0,0 +1,45 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+#include <Base.h>
+
+ SECTION .text
+
+extern ASM_PFX(SecCoreStartupWithStack)
+
+;
+; SecCore Entry Point
+;
+; Processor is in flat protected mode
+;
+; @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test)
+; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor
+; @param[in] EBP Pointer to the start of the Boot Firmware Volume
+;
+; @return None This routine does not return
+;
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+ ;
+ ; Load temporary RAM stack based on PCDs
+ ;
+ %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdSimicsSecPeiTempRamBase) + \
+ FixedPcdGet32 (PcdSimicsSecPeiTempRamSize))
+ mov eax, SEC_TOP_OF_STACK
+ mov esp, eax
+ nop
+
+ ;
+ ; Setup parameters and call SecCoreStartupWithStack
+ ; [esp] return address for call
+ ; [esp+4] BootFirmwareVolumePtr
+ ; [esp+8] TopOfCurrentStack
+ ;
+ push eax
+ push ebp
+ call ASM_PFX(SecCoreStartupWithStack)
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
new file mode 100644
index 0000000000..b1d319c5ea
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/SecMain.inf
@@ -0,0 +1,73 @@
+## @file
+# SEC Driver
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecMain
+ FILE_GUID = e67f156f-54c5-47f3-a35d-07c045881e14
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SecMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ SecMain.c
+
+[Sources.IA32]
+ Ia32/SecEntry.nasm
+
+[Sources.X64]
+ X64/SecEntry.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ SimicsX58SktPkg/SktPkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ PeiServicesLib
+ PcdLib
+ UefiCpuLib
+ DebugAgentLib
+ IoLib
+ PeCoffLib
+ PeCoffGetEntryPointLib
+ PeCoffExtraActionLib
+ ExtractGuidedSectionLib
+ LocalApicLib
+ PciCf8Lib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+
+[Pcd]
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize
+ gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
+ gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
+
+[FeaturePcd]
+ gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm b/Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
new file mode 100644
index 0000000000..2e6d8f618c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SecCore/X64/SecEntry.nasm
@@ -0,0 +1,45 @@
+; @file
+; Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+#include <Base.h>
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(SecCoreStartupWithStack)
+
+;
+; SecCore Entry Point
+;
+; Processor is in flat protected mode
+;
+; @param[in] RAX Initial value of the EAX register (BIST: Built-in Self Test)
+; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor
+; @param[in] RBP Pointer to the start of the Boot Firmware Volume
+;
+; @return None This routine does not return
+;
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+ ;
+ ; Load temporary RAM stack based on PCDs
+ ;
+ %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdSimicsSecPeiTempRamBase) + \
+ FixedPcdGet32 (PcdSimicsSecPeiTempRamSize))
+ mov rsp, SEC_TOP_OF_STACK
+ nop
+
+ ;
+ ; Setup parameters and call SecCoreStartupWithStack
+ ; rcx: BootFirmwareVolumePtr
+ ; rdx: TopOfCurrentStack
+ ;
+ mov rcx, rbp
+ mov rdx, rsp
+ sub rsp, 0x20
+ call ASM_PFX(SecCoreStartupWithStack)
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
new file mode 100644
index 0000000000..623d8ad2a9
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.h
@@ -0,0 +1,38 @@
+/** @file
+ This driver effectuates QSP platform configuration settings and exposes
+ them via HII.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_H_
+#define _PLATFORM_H_
+
+//
+// Macro and type definitions that connect the form with the HII driver code.
+//
+#define FORMSTATEID_MAIN_FORM 1
+#define FORMID_MAIN_FORM 1
+
+#define QUESTION_RES_CUR 1
+#define MAXSIZE_RES_CUR 16
+
+#define LABEL_RES_NEXT 1
+#define QUESTION_RES_NEXT 2
+
+#define QUESTION_SAVE_EXIT 3
+#define QUESTION_DISCARD_EXIT 4
+
+//
+// This structure describes the form state. Its fields relate strictly to the
+// visual widgets on the form.
+//
+typedef struct {
+ UINT16 CurrentPreferredResolution[MAXSIZE_RES_CUR];
+ UINT32 NextPreferredResolution;
+} MAIN_FORM_STATE;
+
+#endif // _PLATFORM_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
new file mode 100644
index 0000000000..3d9af148ec
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/Platform.uni
@@ -0,0 +1,31 @@
+// *++
+//
+// Copyright (C) 2014, Red Hat, Inc.
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+// Platform.uni
+//
+// Abstract:
+//
+// String definitions for PlatformForms.vfr
+//
+// --*/
+
+/=#
+
+#langdef en-US "English"
+
+#string STR_FORMSET_TITLE #language en-US "QSP Platform Configuration"
+#string STR_FORMSET_HELP #language en-US "Change various QSP platform settings."
+#string STR_MAIN_FORM_TITLE #language en-US "QSP Settings"
+#string STR_RES_CUR #language en-US "Preferred Resolution at Next Boot"
+#string STR_RES_CUR_HELP #language en-US "The preferred resolution of the Graphics Console at next boot. It might be unset, or even invalid (hence ignored) wrt. the video RAM size."
+#string STR_RES_NEXT #language en-US "Change Preferred Resolution for Next Boot"
+#string STR_RES_NEXT_HELP #language en-US "You can specify a new preference for the Graphics Console here. The list is filtered against the video RAM size."
+#string STR_SAVE_EXIT #language en-US "Commit Changes and Exit"
+#string STR_DISCARD_EXIT #language en-US "Discard Changes and Exit"
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
new file mode 100644
index 0000000000..c2063c427b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformConfig.h
@@ -0,0 +1,52 @@
+/** @file
+ Utility functions for serializing (persistently storing) and deserializing
+ Simics's platform configuration.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_CONFIG_H_
+#define _PLATFORM_CONFIG_H_
+
+#include <Base.h>
+
+//
+// This structure participates in driver configuration. It does not
+// (necessarily) reflect the wire format in the persistent store.
+//
+#pragma pack(1)
+typedef struct {
+ //
+ // preferred graphics console resolution when booting
+ //
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+} PLATFORM_CONFIG;
+#pragma pack()
+
+//
+// Please see the API documentation near the function definitions.
+//
+EFI_STATUS
+EFIAPI
+PlatformConfigSave (
+ IN PLATFORM_CONFIG *PlatformConfig
+ );
+
+EFI_STATUS
+EFIAPI
+PlatformConfigLoad (
+ OUT PLATFORM_CONFIG *PlatformConfig,
+ OUT UINT64 *OptionalElements
+ );
+
+//
+// Feature flags for OptionalElements.
+//
+#define PLATFORM_CONFIG_F_GRAPHICS_RESOLUTION BIT0
+#define PLATFORM_CONFIG_F_DOWNGRADE BIT63
+
+#endif // _PLATFORM_CONFIG_H_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
new file mode 100644
index 0000000000..a38521e8d3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/PlatformForms.vfr
@@ -0,0 +1,67 @@
+// *++
+//
+// Copyright (C) 2014, Red Hat, Inc.
+// Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+// PlatformForms.vfr
+//
+// Abstract:
+//
+// Form definitions for exposing some of OVMF's platform knobs via HII.
+//
+// --*/
+
+#include <Guid/SimicsBoardConfig.h>
+#include "Platform.h"
+
+formset
+ guid = SIMICS_BOARD_CONFIG_GUID,
+ title = STRING_TOKEN(STR_FORMSET_TITLE),
+ help = STRING_TOKEN(STR_FORMSET_HELP),
+
+ varstore MAIN_FORM_STATE,
+ varid = FORMSTATEID_MAIN_FORM,
+ name = MainFormState,
+ guid = SIMICS_BOARD_CONFIG_GUID;
+
+ form
+ formid = FORMID_MAIN_FORM,
+ title = STRING_TOKEN(STR_MAIN_FORM_TITLE);
+
+ //
+ // Display the current preference in a read-only string field.
+ //
+ string
+ varid = MainFormState.CurrentPreferredResolution,
+ questionid = QUESTION_RES_CUR,
+ prompt = STRING_TOKEN(STR_RES_CUR),
+ help = STRING_TOKEN(STR_RES_CUR_HELP),
+ flags = READ_ONLY,
+ minsize = 0,
+ maxsize = MAXSIZE_RES_CUR,
+ endstring;
+
+ //
+ // We'll dynamically generate a one-of-many selection at this label.
+ //
+ label LABEL_RES_NEXT;
+
+ text
+ help = STRING_TOKEN(STR_SAVE_EXIT),
+ text = STRING_TOKEN(STR_SAVE_EXIT),
+ flags = INTERACTIVE,
+ key = QUESTION_SAVE_EXIT;
+
+ text
+ help = STRING_TOKEN(STR_DISCARD_EXIT),
+ text = STRING_TOKEN(STR_DISCARD_EXIT),
+ flags = INTERACTIVE,
+ key = QUESTION_DISCARD_EXIT;
+
+ endform;
+
+endformset;
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
new file mode 100644
index 0000000000..eef187d2a7
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsDxe/SimicsDxe.inf
@@ -0,0 +1,65 @@
+## @file
+# This driver effectuates Simics X58 platform configuration settings and exposes
+# them via HII.
+#
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SimicsDxe
+ FILE_GUID = 74B64DC1-B0B6-4853-A6BD-C6426059AB1E
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformInit
+ UNLOAD_IMAGE = PlatformUnload
+
+[Sources]
+ Platform.c
+ Platform.uni
+ PlatformConfig.c
+ PlatformForms.vfr
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ HiiLib
+ MemoryAllocationLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiHiiServicesLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiDriverEntryPoint
+ DxeServicesTableLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## PRODUCES
+ gEfiGraphicsOutputProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+
+[Guids]
+ gEfiIfrTianoGuid
+ gSimicsBoardConfigGuid
+
+[Depex]
+ gEfiHiiConfigRoutingProtocolGuid AND
+ gEfiHiiDatabaseProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
new file mode 100644
index 0000000000..07fa2e2d11
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Cmos.h
@@ -0,0 +1,50 @@
+/** @file
+ PC/AT CMOS access routines
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __CMOS_H__
+#define __CMOS_H__
+
+/**
+ Reads 8-bits of CMOS data.
+
+ Reads the 8-bits of CMOS data at the location specified by Index.
+ The 8-bit read value is returned.
+
+ @param Index The CMOS location to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+ IN UINTN Index
+ );
+
+/**
+ Writes 8-bits of CMOS data.
+
+ Writes 8-bits of CMOS data to the location specified by Index
+ with the value specified by Value and returns Value.
+
+ @param Index The CMOS location to write.
+ @param Value The value to write to CMOS.
+
+ @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+ IN UINTN Index,
+ IN UINT8 Value
+ );
+
+
+#endif
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
new file mode 100644
index 0000000000..102d21cd64
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/Platform.h
@@ -0,0 +1,88 @@
+/** @file
+ Platform PEI module include file.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PLATFORM_PEI_H_INCLUDED_
+#define _PLATFORM_PEI_H_INCLUDED_
+
+VOID
+AddIoMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddIoMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddUntestedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize,
+ BOOLEAN Cacheable
+ );
+
+VOID
+AddressWidthInitialization (
+ VOID
+ );
+
+VOID
+X58TsegMbytesInitialization (
+ VOID
+ );
+
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ );
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+ VOID
+ );
+
+VOID
+InitializeRamRegions (
+ VOID
+ );
+
+VOID
+InstallFeatureControlCallback (
+ VOID
+ );
+
+extern EFI_BOOT_MODE mBootMode;
+
+extern BOOLEAN mS3Supported;
+
+extern UINT8 mPhysMemAddressWidth;
+
+extern UINT32 mMaxCpuCount;
+
+extern UINT16 mHostBridgeDevId;
+#endif // _PLATFORM_PEI_H_INCLUDED_
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
new file mode 100644
index 0000000000..ccc7037d75
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsPei/SimicsPei.inf
@@ -0,0 +1,104 @@
+## @file
+# Platform PEI driver
+#
+# This module provides platform specific function to detect boot mode.
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SimicsPei
+ FILE_GUID = 05116218-f9f1-41f8-8d17-c2207006ffff
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializePlatform
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ Cmos.c
+ FeatureControl.c
+ MemDetect.c
+ Platform.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ SimicsX58SktPkg/SktPkg.dec
+ SimicsIch10Pkg/Ich10Pkg.dec
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+ gEfiSmmPeiSmramMemoryReserveGuid ## CONSUMES
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ HobLib
+ IoLib
+ PciLib
+ PeiResourcePublicationLib
+ PeiServicesLib
+ PeiServicesTablePointerLib
+ PeimEntryPoint
+ MtrrLib
+ PcdLib
+
+[Pcd]
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize
+ gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
+ gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+ gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd
+ gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+ gBoardModuleTokenSpaceGuid.PcdPciIoBase
+ gBoardModuleTokenSpaceGuid.PcdPciIoSize
+ gBoardModuleTokenSpaceGuid.PcdPciMmio32Base
+ gBoardModuleTokenSpaceGuid.PcdPciMmio32Size
+ gBoardModuleTokenSpaceGuid.PcdPciMmio64Base
+ gBoardModuleTokenSpaceGuid.PcdPciMmio64Size
+ gSimicsX58PkgTokenSpaceGuid.PcdX58TsegMbytes
+ gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdIoApicId
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid
+ gEfiPeiMpServicesPpiGuid
+
+[Depex]
+ TRUE
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
new file mode 100644
index 0000000000..f9c641845c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
@@ -0,0 +1,38 @@
+/** @file
+ This driver installs SMBIOS information for QSP
+
+ Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SMBIOS_PLATFORM_DXE_H_
+#define _SMBIOS_PLATFORM_DXE_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+
+/**
+ Validates the SMBIOS entry point structure
+
+ @param EntryPointStructure SMBIOS entry point structure
+
+ @retval TRUE The entry point structure is valid
+ @retval FALSE The entry point structure is not valid
+
+**/
+BOOLEAN
+IsEntryPointStructureValid (
+ IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure
+ );
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
new file mode 100644
index 0000000000..1420a315cf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
@@ -0,0 +1,51 @@
+## @file
+# This driver installs SMBIOS information for QSP
+#
+# Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+# Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmbiosPlatformDxe
+ FILE_GUID = 4b18323d-2d42-4afa-b9e5-91516a6fe505
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SmbiosTablePublishEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64
+#
+
+[Sources]
+ SmbiosPlatformDxe.h
+ SmbiosPlatformDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ AdvancedFeaturePkg/AdvancedFeaturePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+ HobLib
+ MemoryAllocationLib
+ IoLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [edk2-platforms PATCH v5 5/7] SimicsOpenBoardPkg: Add modules and dec file under SimicsOpenBoardPkg
2019-09-05 21:38 [edk2-platforms PATCH v5 0/7] Add Initial QSP MinPlatform Pkg for SIMICS David Wei
` (3 preceding siblings ...)
2019-09-05 21:38 ` [edk2-platforms PATCH v5 4/7] SimicsOpenBoardPkg: Add DXE driver for Legacy Sio David Wei
@ 2019-09-05 21:38 ` David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 6/7] SimicsOpenBoardPkg/BoardX58Ich10: Add board modules for QSP Build tip David Wei
2019-09-05 21:38 ` [edk2-platforms PATCH v5 7/7] Platform/Intel: Add build option for SIMICS QSP Platform David Wei
6 siblings, 0 replies; 9+ messages in thread
From: David Wei @ 2019-09-05 21:38 UTC (permalink / raw)
To: devel
Cc: Hao Wu, Liming Gao, Ankit Sinha, Agyeman Prince,
Kubacki Michael A, Nate DeSimone, Michael D Kinney
Add AcpiTable, Logo image, dec file and GOP driver
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Agyeman Prince <prince.agyeman@intel.com>
Cc: Kubacki Michael A <michael.a.kubacki@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: David Wei <david.y.wei@intel.com>
---
.../MinPlatformAcpiTables/AcpiPlatform.c | 1579 ++++++++++++++++++++
.../AcpiTables/MinPlatformAcpiTables/Facs/Facs.c | 84 ++
.../AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c | 359 +++++
.../AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c | 78 +
.../AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c | 46 +
.../SimicsVideoDxe/ComponentName.c | 205 +++
.../SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c | 1011 +++++++++++++
.../SimicsVideoDxe/DriverSupportedEfiVersion.c | 15 +
.../Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c | 416 ++++++
.../SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c | 341 +++++
.../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c | 302 ++++
.../SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf | 31 +
.../Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl | 821 ++++++++++
.../MinPlatformAcpiTables/AcpiPlatform.h | 45 +
.../MinPlatformAcpiTables/AcpiPlatform.inf | 105 ++
.../Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h | 75 +
Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp | Bin 0 -> 141078 bytes
Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec | 152 ++
.../SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h | 507 +++++++
.../SimicsVideoDxe/SimicsVideoDxe.inf | 74 +
.../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm | 279 ++++
.../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h | 701 +++++++++
.../SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh | 79 +
23 files changed, 7305 insertions(+)
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
create mode 100644 Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
new file mode 100644
index 0000000000..1edac89240
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.c
@@ -0,0 +1,1579 @@
+/** @file
+ ACPI Platform Driver
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiPlatform.h"
+
+#define MAX_CPU_NUM (FixedPcdGet32(PcdMaxCpuThreadCount) * FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuSocketCount))
+
+#pragma pack(1)
+
+typedef struct {
+ UINT32 AcpiProcessorId;
+ UINT32 ApicId;
+ UINT32 Flags;
+ UINT32 SwProcApicId;
+ UINT32 SocketNum;
+} EFI_CPU_ID_ORDER_MAP;
+
+//
+// Private Driver Data
+//
+//
+// Define Union of IO APIC & Local APIC structure;
+//
+typedef union {
+ EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
+ EFI_ACPI_4_0_IO_APIC_STRUCTURE AcpiIoApic;
+ EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE AcpiLocalx2Apic;
+ struct {
+ UINT8 Type;
+ UINT8 Length;
+ } AcpiApicCommon;
+} ACPI_APIC_STRUCTURE_PTR;
+
+#pragma pack()
+
+extern EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs;
+extern EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt;
+extern EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet;
+extern EFI_ACPI_WSMT_TABLE Wsmt;
+
+VOID *mLocalTable[] = {
+ &Facs,
+ &Fadt,
+ &Hpet,
+ &Wsmt,
+};
+
+EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+
+UINT32 mNumOfBitShift = 6;
+BOOLEAN mForceX2ApicId;
+BOOLEAN mX2ApicEnabled;
+
+EFI_MP_SERVICES_PROTOCOL *mMpService;
+BOOLEAN mCpuOrderSorted;
+EFI_CPU_ID_ORDER_MAP mCpuApicIdOrderTable[MAX_CPU_NUM];
+UINTN mNumberOfCPUs = 0;
+UINTN mNumberOfEnabledCPUs = 0;
+//
+// following are possible APICID Map for SKX
+//
+static const UINT32 ApicIdMapA[] = { //for SKUs have number of core > 16
+ //it is 14 + 14 + 14 + 14 format
+ 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+ 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x00000010, 0x00000011,
+ 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018, 0x00000019,
+ 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x00000020, 0x00000021, 0x00000022, 0x00000023,
+ 0x00000024, 0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002A, 0x0000002B,
+ 0x0000002C, 0x0000002D, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035,
+ 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000003A, 0x0000003B, 0x0000003C, 0x0000003D
+};
+
+static const UINT32 ApicIdMapB[] = { //for SKUs have number of cores <= 16 use 32 ID space
+ //
+ //it is 16+16 format
+ //
+ 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+ 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
+ 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017,
+ 0x00000018, 0x00000019, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+
+static const UINT32 ApicIdMapC[] = { //for SKUs have number of cores <= 16 use 64 ID space
+ //
+ //it is 16+0+16+0 format
+ //
+ 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+ 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
+ 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027,
+ 0x00000028, 0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static const UINT32 ApicIdMapD[] = { //for SKUs have number of cores <= 8 use 16 ID space
+ //
+ //it is 16 format
+ //
+ 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
+ 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+const UINT32 *mApicIdMap = NULL;
+
+/**
+ This function detect the APICID map and update ApicID Map pointer
+
+ @param None
+
+ @retval VOID
+
+**/
+VOID DetectApicIdMap(VOID)
+{
+ UINTN CoreCount;
+
+ CoreCount = 0;
+
+ if(mApicIdMap != NULL) {
+ return; //aleady initialized
+ }
+
+ mApicIdMap = ApicIdMapA; // default to > 16C SKUs
+
+ CoreCount = mNumberOfEnabledCPUs / 2;
+ DEBUG ((DEBUG_INFO, "CoreCount - %d\n", CoreCount));
+
+ if(CoreCount <= 16) {
+
+ if(mNumOfBitShift == 4) {
+ mApicIdMap = ApicIdMapD;
+ }
+
+ if(mNumOfBitShift == 5) {
+ mApicIdMap = ApicIdMapB;
+ }
+
+ if(mNumOfBitShift == 6) {
+ mApicIdMap = ApicIdMapC;
+ }
+
+ }
+
+ return;
+}
+
+/**
+ This function return the CoreThreadId of ApicId from ACPI ApicId Map array
+
+ @param ApicId
+
+ @retval Index of ACPI ApicId Map array
+
+**/
+UINT32
+GetIndexFromApicId (
+ UINT32 ApicId
+ )
+{
+ UINT32 CoreThreadId;
+ UINT32 i;
+
+ ASSERT (mApicIdMap != NULL);
+
+ CoreThreadId = ApicId & ((1 << mNumOfBitShift) - 1);
+
+ for(i = 0; i < (FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuThreadCount)); i++) {
+ if(mApicIdMap[i] == CoreThreadId) {
+ break;
+ }
+ }
+
+ ASSERT (i <= (FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuThreadCount)));
+
+ return i;
+}
+
+UINT32
+ApicId2SwProcApicId (
+ UINT32 ApicId
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+ if ((mCpuApicIdOrderTable[Index].Flags == 1) && (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
+ return Index;
+ }
+ }
+
+ return (UINT32) -1;
+
+}
+
+VOID
+DebugDisplayReOrderTable(
+ VOID
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((EFI_D_ERROR, "Index AcpiProcId ApicId Flags SwApicId Skt\n"));
+ for (Index=0; Index<MAX_CPU_NUM; Index++) {
+ DEBUG ((EFI_D_ERROR, " %02d 0x%02X 0x%02X %d 0x%02X %d\n",
+ Index, mCpuApicIdOrderTable[Index].AcpiProcessorId,
+ mCpuApicIdOrderTable[Index].ApicId,
+ mCpuApicIdOrderTable[Index].Flags,
+ mCpuApicIdOrderTable[Index].SwProcApicId,
+ mCpuApicIdOrderTable[Index].SocketNum));
+ }
+}
+
+EFI_STATUS
+AppendCpuMapTableEntry (
+ IN VOID *ApicPtr,
+ IN UINT32 LocalApicCounter
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApicPtr;
+ EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *LocalX2ApicPtr;
+ UINT8 Type;
+
+ Status = EFI_SUCCESS;
+ Type = ((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiApicCommon.Type;
+ LocalApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalApic);
+ LocalX2ApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalx2Apic);
+
+ if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC) {
+ if(!mX2ApicEnabled) {
+ LocalApicPtr->Flags = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
+ LocalApicPtr->ApicId = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].ApicId;
+ LocalApicPtr->AcpiProcessorId = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
+ } else {
+ LocalApicPtr->Flags = 0;
+ LocalApicPtr->ApicId = 0xFF;
+ LocalApicPtr->AcpiProcessorId = (UINT8)0xFF;
+ Status = EFI_UNSUPPORTED;
+ }
+ } else if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC) {
+ if(mX2ApicEnabled) {
+ LocalX2ApicPtr->Flags = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
+ LocalX2ApicPtr->X2ApicId = mCpuApicIdOrderTable[LocalApicCounter].ApicId;
+ LocalX2ApicPtr->AcpiProcessorUid = mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
+ } else {
+ LocalX2ApicPtr->Flags = 0;
+ LocalX2ApicPtr->X2ApicId = (UINT32)-1;
+ LocalX2ApicPtr->AcpiProcessorUid = (UINT32)-1;
+ Status = EFI_UNSUPPORTED;
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ return Status;
+
+}
+
+EFI_STATUS
+SortCpuLocalApicInTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ UINT32 Index;
+ UINT32 CurrProcessor;
+ UINT32 BspApicId;
+ UINT32 TempVal = 0;
+ EFI_CPU_ID_ORDER_MAP *CpuIdMapPtr;
+ UINT32 CoreThreadMask;
+
+ Index = 0;
+ Status = EFI_SUCCESS;
+
+ CoreThreadMask = (UINT32) ((1 << mNumOfBitShift) - 1);
+
+ if(!mCpuOrderSorted) {
+
+ Index = 0;
+
+ for (CurrProcessor = 0; CurrProcessor < mNumberOfCPUs; CurrProcessor++) {
+ Status = mMpService->GetProcessorInfo (
+ mMpService,
+ CurrProcessor,
+ &ProcessorInfoBuffer
+ );
+
+ if ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0) {
+ if(ProcessorInfoBuffer.ProcessorId & 1) { //is 2nd thread
+ CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[(Index - 1) + MAX_CPU_NUM / 2];
+ } else { //is primary thread
+ CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[Index];
+ Index++;
+ }
+ CpuIdMapPtr->ApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
+ CpuIdMapPtr->Flags = ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0);
+ CpuIdMapPtr->SocketNum = (UINT32)ProcessorInfoBuffer.Location.Package;
+ CpuIdMapPtr->AcpiProcessorId = (CpuIdMapPtr->SocketNum * FixedPcdGet32(PcdMaxCpuCoreCount) * FixedPcdGet32(PcdMaxCpuThreadCount)) + GetIndexFromApicId(CpuIdMapPtr->ApicId); //CpuIdMapPtr->ApicId;
+ CpuIdMapPtr->SwProcApicId = ((UINT32)(ProcessorInfoBuffer.Location.Package << mNumOfBitShift) + (((UINT32)ProcessorInfoBuffer.ProcessorId) & CoreThreadMask));
+ if(mX2ApicEnabled) { //if X2Apic, re-order the socket # so it starts from base 0 and contiguous
+ //may not necessory!!!!!
+ }
+
+ //update processorbitMask
+ if (CpuIdMapPtr->Flags == 1) {
+
+ if(mForceX2ApicId) {
+ CpuIdMapPtr->SocketNum &= 0x7;
+ CpuIdMapPtr->AcpiProcessorId &= 0xFF; //keep lower 8bit due to use Proc obj in dsdt
+ CpuIdMapPtr->SwProcApicId &= 0xFF;
+ }
+ }
+ } else { //not enabled
+ CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[Index];
+ CpuIdMapPtr->ApicId = (UINT32)-1;
+ CpuIdMapPtr->Flags = 0;
+ CpuIdMapPtr->AcpiProcessorId = (UINT32)-1;
+ CpuIdMapPtr->SwProcApicId = (UINT32)-1;
+ CpuIdMapPtr->SocketNum = (UINT32)-1;
+ } //end if PROC ENABLE
+ } //end for CurrentProcessor
+ //
+ //keep for debug purpose
+ //
+ DEBUG(( EFI_D_ERROR, "::ACPI:: APIC ID Order Table Init. CoreThreadMask = %x, mNumOfBitShift = %x\n", CoreThreadMask, mNumOfBitShift));
+ DebugDisplayReOrderTable();
+ //
+ //make sure 1st entry is BSP
+ //
+ if(mX2ApicEnabled) {
+ BspApicId = (UINT32)AsmReadMsr64(0x802);
+ } else {
+ BspApicId = (*(volatile UINT32 *)(UINTN)0xFEE00020) >> 24;
+ }
+ DEBUG ((EFI_D_INFO, "BspApicId - 0x%x\n", BspApicId));
+
+ if(mCpuApicIdOrderTable[0].ApicId != BspApicId) {
+ //
+ //check to see if 1st entry is BSP, if not swap it
+ //
+ Index = ApicId2SwProcApicId(BspApicId);
+
+ if(MAX_CPU_NUM <= Index) {
+ DEBUG ((EFI_D_ERROR, "Asserting the SortCpuLocalApicInTable Index Bufferflow\n"));
+ ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
+ }
+
+ TempVal = mCpuApicIdOrderTable[Index].ApicId;
+ mCpuApicIdOrderTable[Index].ApicId = mCpuApicIdOrderTable[0].ApicId;
+ mCpuApicIdOrderTable[0].ApicId = TempVal;
+ mCpuApicIdOrderTable[Index].Flags = mCpuApicIdOrderTable[0].Flags;
+ mCpuApicIdOrderTable[0].Flags = 1;
+ TempVal = mCpuApicIdOrderTable[Index].SwProcApicId;
+ mCpuApicIdOrderTable[Index].SwProcApicId = mCpuApicIdOrderTable[0].SwProcApicId;
+ mCpuApicIdOrderTable[0].SwProcApicId = TempVal;
+ //
+ //swap AcpiProcId
+ //
+ TempVal = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+ mCpuApicIdOrderTable[Index].AcpiProcessorId = mCpuApicIdOrderTable[0].AcpiProcessorId;
+ mCpuApicIdOrderTable[0].AcpiProcessorId = TempVal;
+
+ }
+ //
+ //Make sure no holes between enabled threads
+ //
+ for(CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
+
+ if(mCpuApicIdOrderTable[CurrProcessor].Flags == 0) {
+ //
+ //make sure disabled entry has ProcId set to FFs
+ //
+ mCpuApicIdOrderTable[CurrProcessor].ApicId = (UINT32)-1;
+ mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = (UINT32)-1;
+ mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = (UINT32)-1;
+
+ for(Index = CurrProcessor+1; Index < MAX_CPU_NUM; Index++) {
+ if(mCpuApicIdOrderTable[Index].Flags == 1) {
+ //
+ //move enabled entry up
+ //
+ mCpuApicIdOrderTable[CurrProcessor].Flags = 1;
+ mCpuApicIdOrderTable[CurrProcessor].ApicId = mCpuApicIdOrderTable[Index].ApicId;
+ mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+ mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = mCpuApicIdOrderTable[Index].SwProcApicId;
+ mCpuApicIdOrderTable[CurrProcessor].SocketNum = mCpuApicIdOrderTable[Index].SocketNum;
+ //
+ //disable moved entry
+ //
+ mCpuApicIdOrderTable[Index].Flags = 0;
+ mCpuApicIdOrderTable[Index].ApicId = (UINT32)-1;
+ mCpuApicIdOrderTable[Index].AcpiProcessorId = (UINT32)-1;
+ mCpuApicIdOrderTable[Index].SwProcApicId = (UINT32)-1;
+ break;
+ }
+ }
+ }
+ }
+ //
+ //keep for debug purpose
+ //
+ DEBUG ((EFI_D_ERROR, "APIC ID Order Table ReOrdered\n"));
+ DebugDisplayReOrderTable();
+
+ mCpuOrderSorted = TRUE;
+ }
+
+ return Status;
+}
+
+
+/** Structure of a sub-structure of the ACPI header.
+
+ This structure contains the type and length fields, which are common to every
+ sub-structure of the ACPI tables. A pointer to any structure can be cast as this.
+**/
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+} STRUCTURE_HEADER;
+
+STRUCTURE_HEADER mMadtStructureTable[] = {
+ {EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC, sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE)},
+ {EFI_ACPI_4_0_IO_APIC, sizeof (EFI_ACPI_4_0_IO_APIC_STRUCTURE)},
+ {EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE, sizeof (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE)},
+ {EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE, sizeof (EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE)},
+ {EFI_ACPI_4_0_LOCAL_APIC_NMI, sizeof (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE)},
+ {EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE, sizeof (EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE)},
+ {EFI_ACPI_4_0_IO_SAPIC, sizeof (EFI_ACPI_4_0_IO_SAPIC_STRUCTURE)},
+ {EFI_ACPI_4_0_LOCAL_SAPIC, sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE)},
+ {EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES, sizeof (EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE)},
+ {EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC, sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE)},
+ {EFI_ACPI_4_0_LOCAL_X2APIC_NMI, sizeof (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE)}
+};
+
+/**
+ Get the size of the ACPI table.
+
+ This function calculates the size needed for the ACPI Table based on the number and
+ size of the sub-structures that will compose it.
+
+ @param[in] TableSpecificHdrLength Size of the table specific header, not the ACPI standard header size.
+ @param[in] Structures Pointer to an array of sub-structure pointers.
+ @param[in] StructureCount Number of structure pointers in the array.
+
+ @return Total size needed for the ACPI table.
+**/
+UINT32
+GetTableSize (
+ IN UINTN TableSpecificHdrLength,
+ IN STRUCTURE_HEADER **Structures,
+ IN UINTN StructureCount
+ )
+{
+ UINT32 TableLength;
+ UINT32 Index;
+
+ //
+ // Compute size of the ACPI table; header plus all structures needed.
+ //
+ TableLength = (UINT32) TableSpecificHdrLength;
+
+ for (Index = 0; Index < StructureCount; Index++) {
+ ASSERT (Structures[Index] != NULL);
+ if (Structures[Index] == NULL) {
+ return 0;
+ }
+
+ TableLength += Structures[Index]->Length;
+ }
+
+ return TableLength;
+}
+
+/**
+ Allocate the ACPI Table.
+
+ This function allocates space for the ACPI table based on the number and size of
+ the sub-structures that will compose it.
+
+ @param[in] TableSpecificHdrLength Size of the table specific header, not the ACPI standard header size.
+ @param[in] Structures Pointer to an array of sub-structure pointers.
+ @param[in] StructureCount Number of structure pointers in the array.
+ @param[out] Table Newly allocated ACPI Table pointer.
+
+ @retval EFI_SUCCESS Successfully allocated the Table.
+ @retval EFI_OUT_OF_RESOURCES Space for the Table could not be allocated.
+**/
+EFI_STATUS
+AllocateTable (
+ IN UINTN TableSpecificHdrLength,
+ IN STRUCTURE_HEADER **Structures,
+ IN UINTN StructureCount,
+ OUT EFI_ACPI_DESCRIPTION_HEADER **Table
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Size;
+ EFI_ACPI_DESCRIPTION_HEADER *InternalTable;
+
+ //
+ // Get the size of the ACPI table and allocate memory.
+ //
+ Size = GetTableSize (TableSpecificHdrLength, Structures, StructureCount);
+ InternalTable = (EFI_ACPI_DESCRIPTION_HEADER *) AllocatePool (Size);
+
+ if (InternalTable == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "Failed to allocate %d bytes for ACPI Table\n",
+ Size
+ ));
+ } else {
+ Status = EFI_SUCCESS;
+ DEBUG ((
+ DEBUG_INFO,
+ "Successfully allocated %d bytes for ACPI Table at 0x%p\n",
+ Size,
+ InternalTable
+ ));
+ *Table = InternalTable;
+ }
+
+ return Status;
+}
+
+/**
+ Initialize the header.
+
+ This function fills in the standard table header with correct values,
+ except for the length and checksum fields, which are filled in later.
+
+ @param[in,out] Header Pointer to the header structure.
+
+ @retval EFI_SUCCESS Successfully initialized the header.
+ @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+**/
+EFI_STATUS
+InitializeHeader (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *Header,
+ IN UINT32 Signature,
+ IN UINT8 Revision,
+ IN UINT32 OemRevision
+ )
+{
+ UINT64 AcpiTableOemId;
+
+ if (Header == NULL) {
+ DEBUG ((DEBUG_ERROR, "Header pointer is NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Header->Signature = Signature;
+ Header->Length = 0; // filled in by Build function
+ Header->Revision = Revision;
+ Header->Checksum = 0; // filled in by InstallAcpiTable
+
+ CopyMem (
+ (VOID *) &Header->OemId,
+ PcdGetPtr (PcdAcpiDefaultOemId),
+ sizeof (Header->OemId)
+ );
+
+ AcpiTableOemId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ CopyMem (
+ (VOID *) &Header->OemTableId,
+ (VOID *) &AcpiTableOemId,
+ sizeof (Header->OemTableId)
+ );
+
+ Header->OemRevision = OemRevision;
+ Header->CreatorId = 0;
+ Header->CreatorRevision = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the MADT header.
+
+ This function fills in the MADT's standard table header with correct values,
+ except for the length and checksum fields, which are filled in later.
+
+ @param[in,out] MadtHeader Pointer to the MADT header structure.
+
+ @retval EFI_SUCCESS Successfully initialized the MADT header.
+ @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+**/
+EFI_STATUS
+InitializeMadtHeader (
+ IN OUT EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader
+ )
+{
+ EFI_STATUS Status;
+
+ if (MadtHeader == NULL) {
+ DEBUG ((DEBUG_ERROR, "MADT header pointer is NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = InitializeHeader (
+ &MadtHeader->Header,
+ EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MadtHeader->LocalApicAddress = PcdGet32(PcdLocalApicAddress);
+ MadtHeader->Flags = EFI_ACPI_4_0_PCAT_COMPAT;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Copy an ACPI sub-structure; MADT and SRAT supported
+
+ This function validates the structure type and size of a sub-structure
+ and returns a newly allocated copy of it.
+
+ @param[in] Header Pointer to the header of the table.
+ @param[in] Structure Pointer to the structure to copy.
+ @param[in] NewStructure Newly allocated copy of the structure.
+
+ @retval EFI_SUCCESS Successfully copied the structure.
+ @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+ @retval EFI_INVALID_PARAMETER Structure type was unknown.
+ @retval EFI_INVALID_PARAMETER Structure length was wrong for its type.
+ @retval EFI_UNSUPPORTED Header passed in is not supported.
+**/
+EFI_STATUS
+CopyStructure (
+ IN EFI_ACPI_DESCRIPTION_HEADER *Header,
+ IN STRUCTURE_HEADER *Structure,
+ OUT STRUCTURE_HEADER **NewStructure
+ )
+{
+ STRUCTURE_HEADER *NewStructureInternal;
+ STRUCTURE_HEADER *StructureTable;
+ UINTN TableNumEntries;
+ BOOLEAN EntryFound;
+ UINT8 Index;
+
+ //
+ // Initialize the number of table entries and the table based on the table header passed in.
+ //
+ if (Header->Signature == EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
+ TableNumEntries = sizeof (mMadtStructureTable) / sizeof (STRUCTURE_HEADER);
+ StructureTable = mMadtStructureTable;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check the incoming structure against the table of supported structures.
+ //
+ EntryFound = FALSE;
+ for (Index = 0; Index < TableNumEntries; Index++) {
+ if (Structure->Type == StructureTable[Index].Type) {
+ if (Structure->Length == StructureTable[Index].Length) {
+ EntryFound = TRUE;
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Invalid length for structure type %d: expected %d, actually %d\n",
+ Structure->Type,
+ StructureTable[Index].Length,
+ Structure->Length
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ //
+ // If no entry in the table matches the structure type and length passed in
+ // then return invalid parameter.
+ //
+ if (!EntryFound) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Unknown structure type: %d\n",
+ Structure->Type
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NewStructureInternal = (STRUCTURE_HEADER *) AllocatePool (Structure->Length);
+ if (NewStructureInternal == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Failed to allocate %d bytes for type %d structure\n",
+ Structure->Length,
+ Structure->Type
+ ));
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "Successfully allocated %d bytes for type %d structure at 0x%p\n",
+ Structure->Length,
+ Structure->Type,
+ NewStructureInternal
+ ));
+ }
+
+ CopyMem (
+ (VOID *) NewStructureInternal,
+ (VOID *) Structure,
+ Structure->Length
+ );
+
+ *NewStructure = NewStructureInternal;
+ return EFI_SUCCESS;
+}
+
+/**
+ Build ACPI Table. MADT tables supported.
+
+ This function builds the ACPI table from the header plus the list of sub-structures
+ passed in. The table returned by this function is ready to be installed using
+ the ACPI table protocol's InstallAcpiTable function, which copies it into
+ ACPI memory. After that, the caller should free the memory returned by this
+ function.
+
+ @param[in] AcpiHeader Pointer to the header structure.
+ @param[in] TableSpecificHdrLength Size of the table specific header, not the ACPI standard header size.
+ @param[in] Structures Pointer to an array of sub-structure pointers.
+ @param[in] StructureCount Number of structure pointers in the array.
+ @param[out] NewTable Newly allocated and initialized pointer to the ACPI Table.
+
+ @retval EFI_SUCCESS Successfully built the ACPI table.
+ @retval EFI_INVALID_PARAMETER Pointer parameter was null.
+ @retval EFI_INVALID_PARAMETER Header parameter had the wrong signature.
+ @retval EFI_OUT_OF_RESOURCES Space for the ACPI Table could not be allocated.
+**/
+EFI_STATUS
+BuildAcpiTable (
+ IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader,
+ IN UINTN TableSpecificHdrLength,
+ IN STRUCTURE_HEADER **Structures,
+ IN UINTN StructureCount,
+ OUT UINT8 **NewTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *InternalTable;
+ UINTN Index;
+ UINT8 *CurrPtr;
+ UINT8 *EndOfTablePtr;
+
+ if (AcpiHeader == NULL) {
+ DEBUG ((DEBUG_ERROR, "AcpiHeader pointer is NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (AcpiHeader->Signature != EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "MADT header signature is expected, actually 0x%08x\n",
+ AcpiHeader->Signature
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Structures == NULL) {
+ DEBUG ((DEBUG_ERROR, "Structure array pointer is NULL\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < StructureCount; Index++) {
+ if (Structures[Index] == NULL) {
+ DEBUG ((DEBUG_ERROR, "Structure pointer %d is NULL\n", Index));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Allocate the memory needed for the table.
+ //
+ Status = AllocateTable (
+ TableSpecificHdrLength,
+ Structures,
+ StructureCount,
+ &InternalTable
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Copy Header and patch in structure length, checksum is programmed later
+ // after all structures are populated.
+ //
+ CopyMem (
+ (VOID *) InternalTable,
+ (VOID *) AcpiHeader,
+ TableSpecificHdrLength
+ );
+
+ InternalTable->Length = GetTableSize (TableSpecificHdrLength, Structures, StructureCount);
+
+ //
+ // Copy all the sub structures to the table.
+ //
+ CurrPtr = ((UINT8 *) InternalTable) + TableSpecificHdrLength;
+ EndOfTablePtr = ((UINT8 *) InternalTable) + InternalTable->Length;
+
+ for (Index = 0; Index < StructureCount; Index++) {
+ ASSERT (Structures[Index] != NULL);
+ if (Structures[Index] == NULL) {
+ break;
+ }
+
+ CopyMem (
+ (VOID *) CurrPtr,
+ (VOID *) Structures[Index],
+ Structures[Index]->Length
+ );
+
+ CurrPtr += Structures[Index]->Length;
+ ASSERT (CurrPtr <= EndOfTablePtr);
+ if (CurrPtr > EndOfTablePtr) {
+ break;
+ }
+ }
+
+ //
+ // Update the return pointer.
+ //
+ *NewTable = (UINT8 *) InternalTable;
+ return EFI_SUCCESS;
+}
+
+/**
+ Build from scratch and install the MADT.
+
+ @retval EFI_SUCCESS The MADT was installed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate required structures.
+**/
+EFI_STATUS
+InstallMadtFromScratch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *NewMadtTable;
+ UINTN TableHandle;
+ EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MadtTableHeader;
+ EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE ProcLocalApicStruct;
+ EFI_ACPI_4_0_IO_APIC_STRUCTURE IoApicStruct;
+ EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE IntSrcOverrideStruct;
+ EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE LocalApciNmiStruct;
+ EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE ProcLocalX2ApicStruct;
+ EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE LocalX2ApicNmiStruct;
+ STRUCTURE_HEADER **MadtStructs;
+ UINTN MaxMadtStructCount;
+ UINTN MadtStructsIndex;
+ UINT32 CurrentIoApicAddress = (UINT32)(PcdGet32(PcdPcIoApicAddressBase));
+ UINT32 PcIoApicEnable;
+ UINT32 PcIoApicMask;
+ UINTN PcIoApicIndex;
+
+ DetectApicIdMap();
+
+ // Call for Local APIC ID Reorder
+ SortCpuLocalApicInTable ();
+
+ NewMadtTable = NULL;
+
+ MaxMadtStructCount = (UINT32) (
+ MAX_CPU_NUM + // processor local APIC structures
+ MAX_CPU_NUM + // processor local x2APIC structures
+ 1 + PcdGet8(PcdPcIoApicCount) + // I/O APIC structures
+ 2 + // interrupt source override structures
+ 1 + // local APIC NMI structures
+ 1 // local x2APIC NMI structures
+ ); // other structures are not used
+
+ MadtStructs = (STRUCTURE_HEADER **) AllocateZeroPool (MaxMadtStructCount * sizeof (STRUCTURE_HEADER *));
+ if (MadtStructs == NULL) {
+ DEBUG ((DEBUG_ERROR, "Could not allocate MADT structure pointer array\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the next index into the structure pointer array. It is
+ // incremented every time a structure of any type is copied to the array.
+ //
+ MadtStructsIndex = 0;
+
+ //
+ // Initialize MADT Header Structure
+ //
+ Status = InitializeMadtHeader (&MadtTableHeader);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "InitializeMadtHeader failed: %r\n", Status));
+ goto Done;
+ }
+
+ DEBUG ((EFI_D_INFO, "Number of CPUs detected = %d \n", mNumberOfCPUs));
+
+ //
+ // Build Processor Local APIC Structures and Processor Local X2APIC Structures
+ //
+ ProcLocalApicStruct.Type = EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC;
+ ProcLocalApicStruct.Length = sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE);
+
+ ProcLocalX2ApicStruct.Type = EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC;
+ ProcLocalX2ApicStruct.Length = sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE);
+ ProcLocalX2ApicStruct.Reserved[0] = 0;
+ ProcLocalX2ApicStruct.Reserved[1] = 0;
+
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+ //
+ // If x2APIC mode is not enabled, and if it is possible to express the
+ // APIC ID as a UINT8, use a processor local APIC structure. Otherwise,
+ // use a processor local x2APIC structure.
+ //
+ if (!mX2ApicEnabled && mCpuApicIdOrderTable[Index].ApicId < MAX_UINT8) {
+ ProcLocalApicStruct.Flags = (UINT8) mCpuApicIdOrderTable[Index].Flags;
+ ProcLocalApicStruct.ApicId = (UINT8) mCpuApicIdOrderTable[Index].ApicId;
+ ProcLocalApicStruct.AcpiProcessorId = (UINT8) mCpuApicIdOrderTable[Index].AcpiProcessorId;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &ProcLocalApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ } else if (mCpuApicIdOrderTable[Index].ApicId != 0xFFFFFFFF) {
+ ProcLocalX2ApicStruct.Flags = (UINT8) mCpuApicIdOrderTable[Index].Flags;
+ ProcLocalX2ApicStruct.X2ApicId = mCpuApicIdOrderTable[Index].ApicId;
+ ProcLocalX2ApicStruct.AcpiProcessorUid = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &ProcLocalX2ApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (local APIC/x2APIC) failed: %r\n", Status));
+ goto Done;
+ }
+ }
+
+ //
+ // Build I/O APIC Structures
+ //
+ IoApicStruct.Type = EFI_ACPI_4_0_IO_APIC;
+ IoApicStruct.Length = sizeof (EFI_ACPI_4_0_IO_APIC_STRUCTURE);
+ IoApicStruct.Reserved = 0;
+
+ PcIoApicEnable = PcdGet32(PcdPcIoApicEnable);
+
+ if (FixedPcdGet32(PcdMaxCpuSocketCount) <= 4) {
+ IoApicStruct.IoApicId = PcdGet8(PcdIoApicId);
+ IoApicStruct.IoApicAddress = PcdGet32(PcdIoApicAddress);
+ IoApicStruct.GlobalSystemInterruptBase = 0;
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IoApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (I/O APIC) failed: %r\n", Status));
+ goto Done;
+ }
+ }
+
+ for (PcIoApicIndex = 0; PcIoApicIndex < PcdGet8(PcdPcIoApicCount); PcIoApicIndex++) {
+ PcIoApicMask = (1 << PcIoApicIndex);
+ if ((PcIoApicEnable & PcIoApicMask) == 0) {
+ continue;
+ }
+
+ IoApicStruct.IoApicId = (UINT8)(PcdGet8(PcdPcIoApicIdBase) + PcIoApicIndex);
+ IoApicStruct.IoApicAddress = CurrentIoApicAddress;
+ CurrentIoApicAddress = (CurrentIoApicAddress & 0xFFFF8000) + 0x8000;
+ IoApicStruct.GlobalSystemInterruptBase = (UINT32)(24 + (PcIoApicIndex * 8));
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IoApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (I/O APIC) failed: %r\n", Status));
+ goto Done;
+ }
+ }
+
+ //
+ // Build Interrupt Source Override Structures
+ //
+ IntSrcOverrideStruct.Type = EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE;
+ IntSrcOverrideStruct.Length = sizeof (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+
+ //
+ // IRQ0=>IRQ2 Interrupt Source Override Structure
+ //
+ IntSrcOverrideStruct.Bus = 0x0; // Bus - ISA
+ IntSrcOverrideStruct.Source = 0x0; // Source - IRQ0
+ IntSrcOverrideStruct.GlobalSystemInterrupt = 0x2; // Global System Interrupt - IRQ2
+ IntSrcOverrideStruct.Flags = 0x0; // Flags - Conforms to specifications of the bus
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (IRQ2 source override) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // IRQ9 (SCI Active High) Interrupt Source Override Structure
+ //
+ IntSrcOverrideStruct.Bus = 0x0; // Bus - ISA
+ IntSrcOverrideStruct.Source = 0x9; // Source - IRQ9
+ IntSrcOverrideStruct.GlobalSystemInterrupt = 0x9; // Global System Interrupt - IRQ9
+ IntSrcOverrideStruct.Flags = 0xD; // Flags - Level-tiggered, Active High
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (IRQ9 source override) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Build Local APIC NMI Structures
+ //
+ LocalApciNmiStruct.Type = EFI_ACPI_4_0_LOCAL_APIC_NMI;
+ LocalApciNmiStruct.Length = sizeof (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE);
+ LocalApciNmiStruct.AcpiProcessorId = 0xFF; // Applies to all processors
+ LocalApciNmiStruct.Flags = 0x000D; // Flags - Level-tiggered, Active High
+ LocalApciNmiStruct.LocalApicLint = 0x1;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &LocalApciNmiStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (APIC NMI) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Build Local x2APIC NMI Structure
+ //
+ LocalX2ApicNmiStruct.Type = EFI_ACPI_4_0_LOCAL_X2APIC_NMI;
+ LocalX2ApicNmiStruct.Length = sizeof (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE);
+ LocalX2ApicNmiStruct.Flags = 0x000D; // Flags - Level-tiggered, Active High
+ LocalX2ApicNmiStruct.AcpiProcessorUid = 0xFFFFFFFF; // Applies to all processors
+ LocalX2ApicNmiStruct.LocalX2ApicLint = 0x01;
+ LocalX2ApicNmiStruct.Reserved[0] = 0x00;
+ LocalX2ApicNmiStruct.Reserved[1] = 0x00;
+ LocalX2ApicNmiStruct.Reserved[2] = 0x00;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &LocalX2ApicNmiStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CopyMadtStructure (x2APIC NMI) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Build Madt Structure from the Madt Header and collection of pointers in MadtStructs[]
+ //
+ Status = BuildAcpiTable (
+ (EFI_ACPI_DESCRIPTION_HEADER *) &MadtTableHeader,
+ sizeof (EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER),
+ MadtStructs,
+ MadtStructsIndex,
+ (UINT8 **)&NewMadtTable
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "BuildAcpiTable failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Publish Madt Structure to ACPI
+ //
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ NewMadtTable,
+ NewMadtTable->Header.Length,
+ &TableHandle
+ );
+
+Done:
+ //
+ // Free memory
+ //
+ for (MadtStructsIndex = 0; MadtStructsIndex < MaxMadtStructCount; MadtStructsIndex++) {
+ if (MadtStructs[MadtStructsIndex] != NULL) {
+ FreePool (MadtStructs[MadtStructsIndex]);
+ }
+ }
+
+ FreePool (MadtStructs);
+
+ if (NewMadtTable != NULL) {
+ FreePool (NewMadtTable);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+InstallMcfgFromScratch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *McfgTable;
+ EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *Segment;
+ UINTN Index;
+ UINTN SegmentCount;
+ PCI_SEGMENT_INFO *PciSegmentInfo;
+ UINTN TableHandle;
+
+ PciSegmentInfo = GetPciSegmentInfo (&SegmentCount);
+
+ McfgTable = AllocateZeroPool (
+ sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER) +
+ sizeof(EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE) * SegmentCount
+ );
+ if (McfgTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "Could not allocate MCFG structure\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = InitializeHeader (
+ &McfgTable->Header,
+ EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Set MCFG table "Length" field based on the number of PCIe segments enumerated so far
+ //
+ McfgTable->Header.Length = (UINT32)(sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER) +
+ sizeof (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE) * SegmentCount);
+
+ Segment = (VOID *)(McfgTable + 1);
+
+ for (Index = 0; Index < SegmentCount; Index++) {
+ Segment[Index].PciSegmentGroupNumber = PciSegmentInfo[Index].SegmentNumber;
+ Segment[Index].BaseAddress = PciSegmentInfo[Index].BaseAddress;
+ Segment[Index].StartBusNumber = PciSegmentInfo[Index].StartBusNumber;
+ Segment[Index].EndBusNumber = PciSegmentInfo[Index].EndBusNumber;
+ }
+
+ //
+ // Publish Madt Structure to ACPI
+ //
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ McfgTable,
+ McfgTable->Header.Length,
+ &TableHandle
+ );
+
+ return Status;
+}
+
+/**
+ This function will update any runtime platform specific information.
+ This currently includes:
+ Setting OEM table values, ID, table ID, creator ID and creator revision.
+ Enabling the proper processor entries in the APIC tables
+ It also indicates with which ACPI table version the table belongs.
+
+ @param[in] Table The table to update
+ @param[in] Version Where to install this table
+
+ @retval EFI_SUCCESS Updated tables commplete.
+**/
+EFI_STATUS
+PlatformUpdateTables (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ UINT8 *TempOemId;
+ UINT64 TempOemTableId;
+ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader;
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTable;
+ UINT32 HpetBaseAddress;
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID HpetBlockId;
+ UINT32 HpetCapabilitiesData;
+ HPET_GENERAL_CAPABILITIES_ID_REGISTER HpetCapabilities;
+
+ TableHeader = NULL;
+
+ //
+ // By default, a table belongs in all ACPI table versions published.
+ // Some tables will override this because they have different versions of the table.
+ //
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+
+ //
+ // Update the OEM and creator information for every table except FACS.
+ //
+ if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
+ TempOemId = (UINT8 *)PcdGetPtr(PcdAcpiDefaultOemId);
+ CopyMem (&TableHeader->OemId, TempOemId, 6);
+
+ //
+ // Skip OEM table ID and creator information for DSDT, SSDT and PSDT tables, since these are
+ // created by an ASL compiler and the creator information is useful.
+ //
+ if (Table->Signature != EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
+ Table->Signature != EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
+ Table->Signature != EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
+ ) {
+ TempOemTableId = PcdGet64(PcdAcpiDefaultOemTableId);
+ CopyMem (&TableHeader->OemTableId, &TempOemTableId, 8);
+
+ //
+ // Update the creator ID
+ //
+ TableHeader->CreatorId = PcdGet32(PcdAcpiDefaultCreatorId);
+
+ //
+ // Update the creator revision
+ //
+ TableHeader->CreatorRevision = PcdGet32(PcdAcpiDefaultCreatorRevision);
+ }
+ }
+
+
+ //
+ // By default, a table belongs in all ACPI table versions published.
+ // Some tables will override this because they have different versions of the table.
+ //
+ *Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+ //
+ // Update the various table types with the necessary updates
+ //
+ switch (Table->Signature) {
+
+ case EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+ ASSERT(FALSE);
+ break;
+
+ case EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ FadtHeader = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
+
+ FadtHeader->PreferredPmProfile = PcdGet8 (PcdFadtPreferredPmProfile);
+ FadtHeader->IaPcBootArch = PcdGet16 (PcdFadtIaPcBootArch);
+ FadtHeader->Flags = PcdGet32 (PcdFadtFlags);
+
+ FadtHeader->AcpiEnable = PcdGet8 (PcdAcpiEnableSwSmi);
+ FadtHeader->AcpiDisable = PcdGet8 (PcdAcpiDisableSwSmi);
+
+ FadtHeader->Pm1aEvtBlk = PcdGet16 (PcdAcpiPm1AEventBlockAddress);
+ FadtHeader->Pm1bEvtBlk = PcdGet16 (PcdAcpiPm1BEventBlockAddress);
+ FadtHeader->Pm1aCntBlk = PcdGet16 (PcdAcpiPm1AControlBlockAddress);
+ FadtHeader->Pm1bCntBlk = PcdGet16 (PcdAcpiPm1BControlBlockAddress);
+ FadtHeader->Pm2CntBlk = PcdGet16 (PcdAcpiPm2ControlBlockAddress);
+ FadtHeader->PmTmrBlk = PcdGet16 (PcdAcpiPmTimerBlockAddress);
+ FadtHeader->Gpe0Blk = PcdGet16 (PcdAcpiGpe0BlockAddress);
+ FadtHeader->Gpe1Blk = PcdGet16 (PcdAcpiGpe1BlockAddress);
+
+ FadtHeader->XPm1aEvtBlk.Address = PcdGet16 (PcdAcpiPm1AEventBlockAddress);
+ FadtHeader->XPm1bEvtBlk.Address = PcdGet16 (PcdAcpiPm1BEventBlockAddress);
+ if (FadtHeader->XPm1bEvtBlk.Address == 0) {
+ FadtHeader->XPm1bEvtBlk.AccessSize = 0;
+ }
+ FadtHeader->XPm1aCntBlk.Address = PcdGet16 (PcdAcpiPm1AControlBlockAddress);
+ FadtHeader->XPm1bCntBlk.Address = PcdGet16 (PcdAcpiPm1BControlBlockAddress);
+ if (FadtHeader->XPm1bCntBlk.Address == 0) {
+ FadtHeader->XPm1bCntBlk.AccessSize = 0;
+ }
+ FadtHeader->XPm2CntBlk.Address = PcdGet16 (PcdAcpiPm2ControlBlockAddress);
+ //if (FadtHeader->XPm2CntBlk.Address == 0) {
+ FadtHeader->XPm2CntBlk.AccessSize = 0;
+ //}
+ FadtHeader->XPmTmrBlk.Address = PcdGet16 (PcdAcpiPmTimerBlockAddress);
+ FadtHeader->XGpe0Blk.Address = PcdGet16 (PcdAcpiGpe0BlockAddress);
+ FadtHeader->XGpe1Blk.Address = PcdGet16 (PcdAcpiGpe1BlockAddress);
+ if (FadtHeader->XGpe1Blk.Address == 0) {
+ FadtHeader->XGpe1Blk.AccessSize = 0;
+ }
+
+ DEBUG(( EFI_D_ERROR, "ACPI FADT table @ address 0x%x\n", Table ));
+ DEBUG(( EFI_D_ERROR, " IaPcBootArch 0x%x\n", FadtHeader->IaPcBootArch ));
+ DEBUG(( EFI_D_ERROR, " Flags 0x%x\n", FadtHeader->Flags ));
+ break;
+
+ case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
+ HpetTable = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *)Table;
+ HpetBaseAddress = PcdGet32 (PcdHpetBaseAddress);
+ HpetTable->BaseAddressLower32Bit.Address = HpetBaseAddress;
+ HpetTable->BaseAddressLower32Bit.RegisterBitWidth = 0;
+ HpetCapabilitiesData = MmioRead32 (HpetBaseAddress + HPET_GENERAL_CAPABILITIES_ID_OFFSET);
+ HpetCapabilities.Uint64 = HpetCapabilitiesData;
+ HpetCapabilitiesData = MmioRead32 (HpetBaseAddress + HPET_GENERAL_CAPABILITIES_ID_OFFSET + 4);
+ HpetCapabilities.Uint64 |= LShiftU64 (HpetCapabilitiesData, 32);
+ HpetBlockId.Bits.Revision = HpetCapabilities.Bits.Revision;
+ HpetBlockId.Bits.NumberOfTimers = HpetCapabilities.Bits.NumberOfTimers;
+ HpetBlockId.Bits.CounterSize = HpetCapabilities.Bits.CounterSize;
+ HpetBlockId.Bits.Reserved = 0;
+ HpetBlockId.Bits.LegacyRoute = HpetCapabilities.Bits.LegacyRoute;
+ HpetBlockId.Bits.VendorId = HpetCapabilities.Bits.VendorId;
+ HpetTable->EventTimerBlockId = HpetBlockId.Uint32;
+ HpetTable->MainCounterMinimumClockTickInPeriodicMode = (UINT16)HpetCapabilities.Bits.CounterClockPeriod;
+ DEBUG(( EFI_D_ERROR, "ACPI HPET table @ address 0x%x\n", Table ));
+ DEBUG(( EFI_D_ERROR, " HPET base 0x%x\n", PcdGet32 (PcdHpetBaseAddress) ));
+ break;
+
+ case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
+ ASSERT(FALSE);
+ break;
+
+ default:
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function calculates RCR based on PCI Device ID and Vendor ID from the devices
+ available on the platform.
+ It also includes other instances of BIOS change to calculate CRC and provides as
+ HWSignature filed in FADT table.
+**/
+VOID
+IsHardwareChange (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 CRC;
+ UINT32 *HWChange;
+ UINTN HWChangeSize;
+ UINT32 PciId;
+ UINTN Handle;
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsPtr;
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *pFADT;
+
+ HandleCount = 0;
+ HandleBuffer = NULL;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return; // PciIO protocol not installed yet!
+ }
+
+ //
+ // Allocate memory for HWChange and add additional entrie for
+ // pFADT->XDsdt
+ //
+ HWChangeSize = HandleCount + 1;
+ HWChange = AllocateZeroPool( sizeof(UINT32) * HWChangeSize );
+ ASSERT( HWChange != NULL );
+
+ if (HWChange == NULL) return;
+
+ //
+ // add HWChange inputs: PCI devices
+ //
+ for (Index = 0; HandleCount > 0; HandleCount--) {
+ PciId = 0;
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
+ if (!EFI_ERROR (Status)) {
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &PciId);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ HWChange[Index++] = PciId;
+ }
+ }
+
+ //
+ // Locate FACP Table
+ //
+ Handle = 0;
+ Status = LocateAcpiTableBySignature (
+ EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ (EFI_ACPI_DESCRIPTION_HEADER **) &pFADT,
+ &Handle
+ );
+ if (EFI_ERROR (Status) || (pFADT == NULL)) {
+ return; //Table not found or out of memory resource for pFADT table
+ }
+
+ //
+ // add HWChange inputs: others
+ //
+ HWChange[Index++] = (UINT32)pFADT->XDsdt;
+
+ //
+ // Calculate CRC value with HWChange data.
+ //
+ Status = gBS->CalculateCrc32(HWChange, HWChangeSize, &CRC);
+ DEBUG((DEBUG_INFO, "CRC = %x and Status = %r\n", CRC, Status));
+
+ //
+ // Set HardwareSignature value based on CRC value.
+ //
+ FacsPtr = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)pFADT->FirmwareCtrl;
+ FacsPtr->HardwareSignature = CRC;
+ FreePool( HWChange );
+}
+
+VOID
+UpdateLocalTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINTN TableHandle;
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof(mLocalTable)/sizeof(mLocalTable[0]); Index++) {
+ CurrentTable = mLocalTable[Index];
+
+ PlatformUpdateTables (CurrentTable, &Version);
+
+ TableHandle = 0;
+
+ if (Version != EFI_ACPI_TABLE_VERSION_NONE) {
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+}
+
+
+VOID
+EFIAPI
+AcpiEndOfDxeEvent (
+ EFI_EVENT Event,
+ VOID *ParentImageHandle
+ )
+{
+
+ if (Event != NULL) {
+ gBS->CloseEvent(Event);
+ }
+
+
+ //
+ // Calculate Hardware Signature value based on current platform configurations
+ //
+ IsHardwareChange();
+}
+
+/**
+ ACPI Platform driver installation function.
+
+ @param[in] ImageHandle Handle for this drivers loaded image protocol.
+ @param[in] SystemTable EFI system table.
+
+ @retval EFI_SUCCESS The driver installed without error.
+ @retval EFI_ABORTED The driver encountered an error and could not complete installation of
+ the ACPI tables.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallAcpiPlatform (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+
+
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&mAcpiTable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create an End of DXE event.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ AcpiEndOfDxeEvent,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Determine the number of processors
+ //
+ mMpService->GetNumberOfProcessors (
+ mMpService,
+ &mNumberOfCPUs,
+ &mNumberOfEnabledCPUs
+ );
+ ASSERT (mNumberOfCPUs <= MAX_CPU_NUM && mNumberOfEnabledCPUs >= 1);
+ DEBUG ((DEBUG_INFO, "mNumberOfCPUs - %d\n", mNumberOfCPUs));
+ DEBUG ((DEBUG_INFO, "mNumberOfEnabledCPUs - %d\n", mNumberOfEnabledCPUs));
+
+ DEBUG ((DEBUG_INFO, "mX2ApicEnabled - 0x%x\n", mX2ApicEnabled));
+ DEBUG ((DEBUG_INFO, "mForceX2ApicId - 0x%x\n", mForceX2ApicId));
+
+ // support up to 64 threads/socket
+ AsmCpuidEx(CPUID_EXTENDED_TOPOLOGY, 1, &mNumOfBitShift, NULL, NULL, NULL);
+ mNumOfBitShift &= 0x1F;
+ DEBUG ((DEBUG_INFO, "mNumOfBitShift - 0x%x\n", mNumOfBitShift));
+
+ UpdateLocalTable ();
+
+ InstallMadtFromScratch ();
+ InstallMcfgFromScratch ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
new file mode 100644
index 0000000000..e649b5b89c
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Facs/Facs.c
@@ -0,0 +1,84 @@
+/** @file
+ This file contains a structure definition for the ACPI 5.0 Firmware ACPI
+ Control Structure (FACS). The contents of this file should only be modified
+ for bug fixes, no porting is required.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+
+//
+// FACS Definitions
+//
+#define EFI_ACPI_FIRMWARE_WAKING_VECTOR 0x00000000
+#define EFI_ACPI_GLOBAL_LOCK 0x00000000
+
+//
+// Firmware Control Structure Feature Flags are defined in AcpiX.0.h
+//
+#define EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS 0x00000000
+
+#define EFI_ACPI_X_FIRMWARE_WAKING_VECTOR 0x0000000000000000
+
+#define EFI_ACPI_OSPM_FLAGS 0x00000000
+
+
+//
+// Firmware ACPI Control Structure
+// Please modify all values in Facs.h only.
+//
+
+EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs = {
+ EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+ sizeof (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+
+ //
+ // Hardware Signature will be updated at runtime
+ //
+ 0x00000000,
+
+ EFI_ACPI_FIRMWARE_WAKING_VECTOR,
+ EFI_ACPI_GLOBAL_LOCK,
+ EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS,
+ EFI_ACPI_X_FIRMWARE_WAKING_VECTOR,
+ EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+ {
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE
+ },
+ EFI_ACPI_OSPM_FLAGS,
+ {
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE
+ }
+};
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
new file mode 100644
index 0000000000..d1fe98e24b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Fadt/Fadt.c
@@ -0,0 +1,359 @@
+/** @file
+ This file contains a structure definition for the ACPI 5.0 Fixed ACPI
+ Description Table (FADT). The contents of this file should only be modified
+ for bug fixes, no porting is required.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include <IndustryStandard/Acpi.h>
+
+//
+// FADT Definitions
+//
+#define EFI_ACPI_OEM_FADT_REVISION 0x00000000
+
+#define EFI_ACPI_PREFERRED_PM_PROFILE 0x00 // To be fixed
+
+#define EFI_ACPI_SCI_INT 0x0009
+#define EFI_ACPI_SMI_CMD 0x000000B2
+
+#define EFI_ACPI_ACPI_ENABLE 0 // To be fixed
+#define EFI_ACPI_ACPI_DISABLE 0 // To be fixed
+#define EFI_ACPI_S4_BIOS_REQ 0x00
+#define EFI_ACPI_CST_CNT 0x00
+
+#define EFI_ACPI_PSTATE_CNT 0x00
+#define EFI_ACPI_GPE1_BASE (EFI_ACPI_GPE1_BLK_BIT_WIDTH / 2)
+#define EFI_ACPI_P_LVL2_LAT 0x0065 // 101
+#define EFI_ACPI_P_LVL3_LAT 0x03E9 // 1001
+#define EFI_ACPI_FLUSH_SIZE 0x0000
+#define EFI_ACPI_FLUSH_STRIDE 0x0000
+#define EFI_ACPI_DUTY_OFFSET 0x01
+#define EFI_ACPI_DUTY_WIDTH 0x00
+
+#define EFI_ACPI_DAY_ALRM 0x0D
+#define EFI_ACPI_MON_ALRM 0x00
+#define EFI_ACPI_CENTURY 0x32
+
+//
+// IA-PC Boot Architecture Flags
+//
+
+#define EFI_ACPI_IAPC_BOOT_ARCH 0 // To be fixed
+
+//
+// Fixed Feature Flags
+//
+#define EFI_ACPI_FIXED_FEATURE_FLAGS 0 // To be fixed
+
+//
+// PM1A Event Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH 0x20
+#define EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS 0 // To be fixed
+
+//
+// PM1B Event Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH 0x00
+#define EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS 0 // To be fixed
+
+//
+// PM1A Control Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH 0x10
+#define EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS 0 // To be fixed
+
+//
+// PM1B Control Register Block Generic Address Information
+//
+#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH 0x00
+#define EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS 0 // To be fixed
+
+//
+// PM2 Control Register Block Generic Address Information
+//
+#define EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH 0x08
+#define EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_PM2_CNT_BLK_ADDRESS 0 // To be fixed
+
+//
+// Power Management Timer Control Register Block Generic Address
+// Information
+//
+#define EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM_TMR_BLK_BIT_WIDTH 0x20
+#define EFI_ACPI_PM_TMR_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_PM_TMR_BLK_ADDRESS 0 // To be fixed
+
+//
+// General Purpose Event 0 Register Block Generic Address
+// Information
+//
+#define EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_GPE0_BLK_BIT_WIDTH 0 // size of R_PCH_ACPI_GPE0_STS_127_96 + R_PCH_ACPI_GPE0_EN_127_96
+#define EFI_ACPI_GPE0_BLK_BIT_OFFSET 0x00
+#define EFI_ACPI_GPE0_BLK_ADDRESS 0 // To be fixed
+
+//
+// General Purpose Event 1 Register Block Generic Address
+// Information
+//
+#define EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_GPE1_BLK_BIT_WIDTH 0x0
+#define EFI_ACPI_GPE1_BLK_BIT_OFFSET 0x0
+#define EFI_ACPI_GPE1_BLK_ADDRESS 0 // To be fixed
+//
+// Reset Register Generic Address Information
+//
+#define EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_RESET_REG_BIT_WIDTH 0x08
+#define EFI_ACPI_RESET_REG_BIT_OFFSET 0x00
+#define EFI_ACPI_RESET_REG_ADDRESS 0x00000CF9
+#define EFI_ACPI_RESET_VALUE 0x06
+
+//
+// Number of bytes decoded by PM1 event blocks (a and b)
+//
+#define EFI_ACPI_PM1_EVT_LEN ((EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH + EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH) / 8)
+
+//
+// Number of bytes decoded by PM1 control blocks (a and b)
+//
+#define EFI_ACPI_PM1_CNT_LEN ((EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH + EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH) / 8)
+
+//
+// Number of bytes decoded by PM2 control block
+//
+#define EFI_ACPI_PM2_CNT_LEN (EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH / 8)
+
+//
+// Number of bytes decoded by PM timer block
+//
+#define EFI_ACPI_PM_TMR_LEN (EFI_ACPI_PM_TMR_BLK_BIT_WIDTH / 8)
+
+//
+// Number of bytes decoded by GPE0 block
+//
+#define EFI_ACPI_GPE0_BLK_LEN (EFI_ACPI_GPE0_BLK_BIT_WIDTH / 8)
+
+//
+// Number of bytes decoded by GPE1 block
+//
+#define EFI_ACPI_GPE1_BLK_LEN (EFI_ACPI_GPE1_BLK_BIT_WIDTH / 8)
+
+//
+// Fixed ACPI Description Table
+// Please modify all values in Fadt.h only.
+//
+
+EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt = {
+ {
+ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE),
+ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+
+ //
+ // It is expected that these values will be updated at runtime
+ //
+ { ' ', ' ', ' ', ' ', ' ', ' ' },
+
+ 0,
+ EFI_ACPI_OEM_FADT_REVISION,
+ 0,
+ 0
+ },
+
+ //
+ // These addresses will be updated at runtime
+ //
+ 0x00000000,
+ 0x00000000,
+
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_PREFERRED_PM_PROFILE,
+ EFI_ACPI_SCI_INT,
+ EFI_ACPI_SMI_CMD,
+ EFI_ACPI_ACPI_ENABLE,
+ EFI_ACPI_ACPI_DISABLE,
+ EFI_ACPI_S4_BIOS_REQ,
+ EFI_ACPI_PSTATE_CNT,
+
+ EFI_ACPI_PM1A_EVT_BLK_ADDRESS,
+ EFI_ACPI_PM1B_EVT_BLK_ADDRESS,
+ EFI_ACPI_PM1A_CNT_BLK_ADDRESS,
+ EFI_ACPI_PM1B_CNT_BLK_ADDRESS,
+ EFI_ACPI_PM2_CNT_BLK_ADDRESS,
+ EFI_ACPI_PM_TMR_BLK_ADDRESS,
+ EFI_ACPI_GPE0_BLK_ADDRESS,
+ EFI_ACPI_GPE1_BLK_ADDRESS,
+ EFI_ACPI_PM1_EVT_LEN,
+ EFI_ACPI_PM1_CNT_LEN,
+ EFI_ACPI_PM2_CNT_LEN,
+ EFI_ACPI_PM_TMR_LEN,
+ EFI_ACPI_GPE0_BLK_LEN,
+ EFI_ACPI_GPE1_BLK_LEN,
+ EFI_ACPI_GPE1_BASE,
+
+ //
+ // Latest OS have C-State capability and CST_CNT SMI doesn't need to be defined.
+ // CST_CNT SMI is not handled in BIOS and it can be removed safely.
+ //
+ EFI_ACPI_CST_CNT,
+ EFI_ACPI_P_LVL2_LAT,
+ EFI_ACPI_P_LVL3_LAT,
+ EFI_ACPI_FLUSH_SIZE,
+ EFI_ACPI_FLUSH_STRIDE,
+ EFI_ACPI_DUTY_OFFSET,
+ EFI_ACPI_DUTY_WIDTH,
+ EFI_ACPI_DAY_ALRM,
+ EFI_ACPI_MON_ALRM,
+ EFI_ACPI_CENTURY,
+ EFI_ACPI_IAPC_BOOT_ARCH,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_FIXED_FEATURE_FLAGS,
+
+ //
+ // Reset Register Block
+ //
+ {
+ EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID,
+ EFI_ACPI_RESET_REG_BIT_WIDTH,
+ EFI_ACPI_RESET_REG_BIT_OFFSET,
+ EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_RESET_REG_ADDRESS
+ },
+ EFI_ACPI_RESET_VALUE,
+ {
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE
+ },
+
+ //
+ // These addresses will be updated at runtime
+ //
+ 0x0000000000000000, // X_FIRMWARE_CTRL
+ 0x0000000000000000, // X_DSDT
+
+ {
+ //
+ // X_PM1a Event Register Block
+ //
+ EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH,
+ EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_WORD,
+ EFI_ACPI_PM1A_EVT_BLK_ADDRESS
+ },
+ {
+ //
+ // X_PM1b Event Register Block
+ //
+ EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH,
+ EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_WORD,
+ EFI_ACPI_PM1B_EVT_BLK_ADDRESS
+ },
+ {
+ //
+ // X_PM1a Control Register Block
+ //
+ EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH,
+ EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_WORD,
+ EFI_ACPI_PM1A_CNT_BLK_ADDRESS
+ },
+ {
+ //
+ // X_PM1b Control Register Block
+ //
+ EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH,
+ EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_WORD,
+ EFI_ACPI_PM1B_CNT_BLK_ADDRESS
+ },
+ {
+ //
+ // X_PM2 Control Register Block
+ //
+ EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH,
+ EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_PM2_CNT_BLK_ADDRESS
+ },
+ {
+ //
+ // X_PM Timer Control Register Block
+ //
+ EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_PM_TMR_BLK_BIT_WIDTH,
+ EFI_ACPI_PM_TMR_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_DWORD,
+ EFI_ACPI_PM_TMR_BLK_ADDRESS
+ },
+ {
+ //
+ // X_General Purpose Event 0 Register Block
+ //
+ EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_GPE0_BLK_BIT_WIDTH,
+ EFI_ACPI_GPE0_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_GPE0_BLK_ADDRESS
+ },
+ {
+ //
+ // X_General Purpose Event 1 Register Block
+ //
+ EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID,
+ EFI_ACPI_GPE1_BLK_BIT_WIDTH,
+ EFI_ACPI_GPE1_BLK_BIT_OFFSET,
+ EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_GPE1_BLK_ADDRESS
+ },
+ {
+ //
+ // Sleep Control Reg - update in DXE driver
+ //
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ //
+ // Sleep Status Reg - update in DXE driver
+ //
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ }
+};
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
new file mode 100644
index 0000000000..e9528b0ec3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Hpet/Hpet.c
@@ -0,0 +1,78 @@
+/** @file
+ This file contains a structure definition for the ACPI 1.0 High Precision Event Timer
+ Description Table (HPET). The contents of this file should only be modified
+ for bug fixes, no porting is required.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+
+//
+// HPET Definitions
+//
+#define EFI_ACPI_OEM_HPET_REVISION 0x00000001
+
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ID 0x0 // To be filled
+
+//
+// Event Timer Block Base Address Information
+//
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID EFI_ACPI_3_0_SYSTEM_MEMORY
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH 0x40
+#define EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET 0x00
+#define EFI_ACPI_EVENT_TIMER_ACCESS_SIZE 0x00
+#define EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS 0x0 // To be filled
+
+#define EFI_ACPI_HPET_NUMBER 0x00
+
+#define EFI_ACPI_MIN_CLOCK_TICK 0x0080
+
+#define EFI_ACPI_HPET_ATTRIBUTES 0x00
+
+//
+// High Precision Event Timer Table
+// Please modify all values in Hpet.h only.
+//
+
+EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet = {
+ {
+ EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER),
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,
+
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+
+ //
+ // It is expected that these values will be updated at runtime
+ //
+ { ' ', ' ', ' ', ' ', ' ', ' ' },
+
+ 0,
+ EFI_ACPI_OEM_HPET_REVISION,
+ 0,
+ 0
+ },
+
+ EFI_ACPI_EVENT_TIMER_BLOCK_ID,
+ {
+ EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS_SPACE_ID,
+ EFI_ACPI_EVENT_TIMER_BLOCK_BIT_WIDTH,
+ EFI_ACPI_EVENT_TIMER_BLOCK_BIT_OFFSET,
+ EFI_ACPI_EVENT_TIMER_ACCESS_SIZE,
+ EFI_ACPI_EVENT_TIMER_BLOCK_ADDRESS
+ },
+ EFI_ACPI_HPET_NUMBER,
+ EFI_ACPI_MIN_CLOCK_TICK,
+ EFI_ACPI_HPET_ATTRIBUTES
+};
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
new file mode 100644
index 0000000000..625b7560bb
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/Wsmt/Wsmt.c
@@ -0,0 +1,46 @@
+/** @file
+ ACPI WSMT table
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
+#include <Library/PcdLib.h>
+
+//
+// WSMT Definitions
+//
+
+#define EFI_ACPI_OEM_WSMT_REVISION 0x00000001
+
+EFI_ACPI_WSMT_TABLE Wsmt = {
+ {
+ EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_WSMT_TABLE),
+ EFI_WSMT_TABLE_REVISION,
+
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+
+ //
+ // It is expected that these values will be updated at runtime
+ //
+ { ' ', ' ', ' ', ' ', ' ', ' ' },
+
+ 0,
+ EFI_ACPI_OEM_WSMT_REVISION,
+ 0,
+ 0
+ },
+
+ FixedPcdGet32(PcdWsmtProtectionFlags)
+};
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
new file mode 100644
index 0000000000..b1286b0b64
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/ComponentName.c
@@ -0,0 +1,205 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gQemuVideoComponentName = {
+ QemuVideoComponentNameGetDriverName,
+ QemuVideoComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gQemuVideoComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) QemuVideoComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) QemuVideoComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mQemuVideoDriverNameTable[] = {
+ { "eng;en", L"QEMU Video Driver" },
+ { NULL , NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mQemuVideoControllerNameTable[] = {
+ { "eng;en", L"QEMU Video PCI Adapter" },
+ { NULL , NULL }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mQemuVideoDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gQemuVideoComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gQemuVideoDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the QEMU Video's Device structure
+ //
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mQemuVideoControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gQemuVideoComponentName)
+ );
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
new file mode 100644
index 0000000000..15f03812bf
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Driver.c
@@ -0,0 +1,1011 @@
+/** @file
+ This driver is a sample implementation of the Graphics Output Protocol for
+ the QEMU (Cirrus Logic 5446) video controller.
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+#include <IndustryStandard/Acpi.h>
+
+EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {
+ QemuVideoControllerDriverSupported,
+ QemuVideoControllerDriverStart,
+ QemuVideoControllerDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+QEMU_VIDEO_CARD gQemuVideoCardList[] = {
+ {
+ PCI_CLASS_DISPLAY_VGA,
+ CIRRUS_LOGIC_VENDOR_ID,
+ CIRRUS_LOGIC_5430_DEVICE_ID,
+ QEMU_VIDEO_CIRRUS_5430,
+ L"Cirrus 5430"
+ },{
+ PCI_CLASS_DISPLAY_VGA,
+ CIRRUS_LOGIC_VENDOR_ID,
+ CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,
+ QEMU_VIDEO_CIRRUS_5430,
+ L"Cirrus 5430"
+ },{
+ PCI_CLASS_DISPLAY_VGA,
+ CIRRUS_LOGIC_VENDOR_ID,
+ CIRRUS_LOGIC_5446_DEVICE_ID,
+ QEMU_VIDEO_CIRRUS_5446,
+ L"Cirrus 5446"
+ },{
+ PCI_CLASS_DISPLAY_VGA,
+ 0x4321,
+ 0x1111,
+ QEMU_VIDEO_BOCHS_MMIO,
+ L"QEMU Standard VGA"
+ },{
+ PCI_CLASS_DISPLAY_OTHER,
+ 0x1234,
+ 0x1111,
+ QEMU_VIDEO_BOCHS_MMIO,
+ L"QEMU Standard VGA (secondary)"
+ },{
+ PCI_CLASS_DISPLAY_VGA,
+ 0x1b36,
+ 0x0100,
+ QEMU_VIDEO_BOCHS,
+ L"QEMU QXL VGA"
+ },{
+ PCI_CLASS_DISPLAY_VGA,
+ 0x1af4,
+ 0x1050,
+ QEMU_VIDEO_BOCHS_MMIO,
+ L"QEMU VirtIO VGA"
+ },{
+ 0 /* end of list */
+ }
+};
+
+static QEMU_VIDEO_CARD*
+QemuVideoDetect(
+ IN UINT8 SubClass,
+ IN UINT16 VendorId,
+ IN UINT16 DeviceId
+ )
+{
+ UINTN Index = 0;
+
+ while (gQemuVideoCardList[Index].VendorId != 0) {
+ if (gQemuVideoCardList[Index].SubClass == SubClass &&
+ gQemuVideoCardList[Index].VendorId == VendorId &&
+ gQemuVideoCardList[Index].DeviceId == DeviceId) {
+ return gQemuVideoCardList + Index;
+ }
+ Index++;
+ }
+ return NULL;
+}
+
+/**
+ Check if this device is supported.
+
+ @param This The driver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The bus supports this controller.
+ @retval EFI_UNSUPPORTED This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ QEMU_VIDEO_CARD *Card;
+
+ //
+ // Open the PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Read the PCI Configuration Header from the PCI Device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (!IS_PCI_DISPLAY (&Pci)) {
+ goto Done;
+ }
+ Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);
+ if (Card != NULL) {
+ DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ //
+ // Close the PCI I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+/**
+ Start to process the controller.
+
+ @param This The USB bus driver binding instance.
+ @param Controller The controller to check.
+ @param RemainingDevicePath The remaining device patch.
+
+ @retval EFI_SUCCESS The controller is controlled by the usb bus.
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
+ bus.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ QEMU_VIDEO_PRIVATE_DATA *Private;
+ BOOLEAN IsQxl;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
+ PCI_TYPE00 Pci;
+ QEMU_VIDEO_CARD *Card;
+ EFI_PCI_IO_PROTOCOL *ChildPciIo;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ //
+ // Allocate Private context data for GOP inteface.
+ //
+ Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));
+ if (Private == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto RestoreTpl;
+ }
+
+ //
+ // Set up context record
+ //
+ Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;
+
+ //
+ // Open PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &Private->PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreePrivate;
+ }
+
+ //
+ // Read the PCI Configuration Header from the PCI Device
+ //
+ Status = Private->PciIo->Pci.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ goto ClosePciIo;
+ }
+
+ //
+ // Determine card variant.
+ //
+ Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);
+ if (Card == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto ClosePciIo;
+ }
+ Private->Variant = Card->Variant;
+
+ //
+ // IsQxl is based on the detected Card->Variant, which at a later point might
+ // not match Private->Variant.
+ //
+ IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);
+
+ //
+ // Save original PCI attributes
+ //
+ Status = Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &Private->OriginalPciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ClosePciIo;
+ }
+
+ //
+ // Set new PCI attributes
+ //
+ Status = Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ClosePciIo;
+ }
+
+ //
+ // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).
+ //
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;
+
+ Status = Private->PciIo->GetBarAttributes (
+ Private->PciIo,
+ PCI_BAR_IDX2,
+ NULL,
+ (VOID**) &MmioDesc
+ );
+ if (EFI_ERROR (Status) ||
+ MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((EFI_D_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));
+ Private->Variant = QEMU_VIDEO_BOCHS;
+ } else {
+ DEBUG ((EFI_D_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n",
+ MmioDesc->AddrRangeMin));
+ }
+
+ if (!EFI_ERROR (Status)) {
+ FreePool (MmioDesc);
+ }
+ }
+
+ //
+ // Check if accessing the bochs interface works.
+ //
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
+ Private->Variant == QEMU_VIDEO_BOCHS) {
+ UINT16 BochsId;
+ BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);
+ if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {
+ DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));
+ Status = EFI_DEVICE_ERROR;
+ goto RestoreAttributes;
+ }
+ }
+
+ //
+ // Get ParentDevicePath
+ //
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ goto RestoreAttributes;
+ }
+
+ //
+ // Set Gop Device Path
+ //
+ ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+
+ Private->GopDevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
+ );
+ if (Private->GopDevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto RestoreAttributes;
+ }
+
+ //
+ // Create new child handle and install the device path protocol on it.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiDevicePathProtocolGuid,
+ Private->GopDevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeGopDevicePath;
+ }
+
+ //
+ // Construct video mode buffer
+ //
+ switch (Private->Variant) {
+ case QEMU_VIDEO_CIRRUS_5430:
+ case QEMU_VIDEO_CIRRUS_5446:
+ Status = QemuVideoCirrusModeSetup (Private);
+ break;
+ case QEMU_VIDEO_BOCHS_MMIO:
+ case QEMU_VIDEO_BOCHS:
+ Status = QemuVideoBochsModeSetup (Private, IsQxl);
+ break;
+ default:
+ ASSERT (FALSE);
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ if (EFI_ERROR (Status)) {
+ goto UninstallGopDevicePath;
+ }
+
+ //
+ // Start the GOP software stack.
+ //
+ Status = QemuVideoGraphicsOutputConstructor (Private);
+ if (EFI_ERROR (Status)) {
+ goto FreeModeData;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Private->GraphicsOutput,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto DestructQemuVideoGraphics;
+ }
+
+ //
+ // Reference parent handle from child handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &ChildPciIo,
+ This->DriverBindingHandle,
+ Private->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto UninstallGop;
+ }
+
+#if defined MDE_CPU_IA32 || defined MDE_CPU_X64
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
+ Private->Variant == QEMU_VIDEO_BOCHS) {
+ InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+ }
+#endif
+
+ gBS->RestoreTPL (OldTpl);
+ return EFI_SUCCESS;
+
+UninstallGop:
+ gBS->UninstallProtocolInterface (Private->Handle,
+ &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);
+
+DestructQemuVideoGraphics:
+ QemuVideoGraphicsOutputDestructor (Private);
+
+FreeModeData:
+ FreePool (Private->ModeData);
+
+UninstallGopDevicePath:
+ gBS->UninstallProtocolInterface (Private->Handle,
+ &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
+
+FreeGopDevicePath:
+ FreePool (Private->GopDevicePath);
+
+RestoreAttributes:
+ Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,
+ Private->OriginalPciAttributes, NULL);
+
+ClosePciIo:
+ gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle, Controller);
+
+FreePrivate:
+ FreePool (Private);
+
+RestoreTpl:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Stop this device
+
+ @param This The USB bus driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of children of this device that
+ opened the controller BY_CHILD.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The controller or children are stopped.
+ @retval EFI_DEVICE_ERROR Failed to stop the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ EFI_STATUS Status;
+ QEMU_VIDEO_PRIVATE_DATA *Private;
+
+ if (NumberOfChildren == 0) {
+ //
+ // Close the PCI I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+ }
+
+ //
+ // free all resources for whose access we need the child handle, because the
+ // child handle is going away
+ //
+ ASSERT (NumberOfChildren == 1);
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[0],
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get our private context information
+ //
+ Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
+ ASSERT (Private->Handle == ChildHandleBuffer[0]);
+
+ QemuVideoGraphicsOutputDestructor (Private);
+ //
+ // Remove the GOP protocol interface from the system
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Private->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Private->GraphicsOutput,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Restore original PCI attributes
+ //
+ Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Private->OriginalPciAttributes,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Private->Handle
+ );
+
+ FreePool (Private->ModeData);
+ gBS->UninstallProtocolInterface (Private->Handle,
+ &gEfiDevicePathProtocolGuid, Private->GopDevicePath);
+ FreePool (Private->GopDevicePath);
+
+ //
+ // Free our instance data
+ //
+ gBS->FreePool (Private);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Address TODO: add argument description
+ @param Data TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+outb (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT8 Data
+ )
+{
+ EFI_STATUS Status;
+ VOID *Interface;
+ Private->PciIo->Io.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+ Status = gBS->LocateProtocol(&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
+ if (!EFI_ERROR(Status)) {
+ return;
+ }
+
+ Status = S3BootScriptSaveIoWrite(
+ S3BootScriptWidthUint8,
+ Address,
+ (UINTN)1,
+ &Data
+ );
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Address TODO: add argument description
+ @param Data TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+outw (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT16 Data
+ )
+{
+ EFI_STATUS Status;
+ VOID *Interface;
+
+ Private->PciIo->Io.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+
+ Status = gBS->LocateProtocol(&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
+ if (!EFI_ERROR(Status)) {
+ return;
+ }
+ Status = S3BootScriptSaveIoWrite(
+ S3BootScriptWidthUint16,
+ Address,
+ 1,
+ &Data
+ );
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Address TODO: add argument description
+
+ TODO: add return values
+
+**/
+UINT8
+inb (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address
+ )
+{
+ UINT8 Data;
+
+ Private->PciIo->Io.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Address TODO: add argument description
+
+ TODO: add return values
+
+**/
+UINT16
+inw (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address
+ )
+{
+ UINT16 Data;
+
+ Private->PciIo->Io.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param Index TODO: add argument description
+ @param Red TODO: add argument description
+ @param Green TODO: add argument description
+ @param Blue TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+SetPaletteColor (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Index,
+ UINT8 Red,
+ UINT8 Green,
+ UINT8 Blue
+ )
+{
+ VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
+ VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
+ VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
+ VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+SetDefaultPalette (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ )
+{
+ UINTN Index;
+ UINTN RedIndex;
+ UINTN GreenIndex;
+ UINTN BlueIndex;
+
+ Index = 0;
+ for (RedIndex = 0; RedIndex < 8; RedIndex++) {
+ for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
+ for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
+ SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
+ Index++;
+ }
+ }
+ }
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+ClearScreen (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ )
+{
+ UINT32 Color;
+
+ Color = 0;
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthFillUint32,
+ 0,
+ 0,
+ 0x400000 >> 2,
+ &Color
+ );
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+DrawLogo (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN ScreenWidth,
+ UINTN ScreenHeight
+ )
+{
+}
+
+/**
+ TODO: Add function description
+
+ @param Private TODO: add argument description
+ @param ModeData TODO: add argument description
+
+ TODO: add return values
+
+**/
+VOID
+InitializeCirrusGraphicsMode (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ QEMU_VIDEO_CIRRUS_MODES *ModeData
+ )
+{
+ UINT8 Byte;
+ UINTN Index;
+
+ outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
+ outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
+
+ for (Index = 0; Index < 15; Index++) {
+ outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
+ }
+
+ if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {
+ outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
+ Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
+ outb (Private, SEQ_DATA_REGISTER, Byte);
+ }
+
+ outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
+ outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
+ outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
+
+ for (Index = 0; Index < 28; Index++) {
+ outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
+ }
+
+ for (Index = 0; Index < 9; Index++) {
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
+ }
+
+ inb (Private, INPUT_STATUS_1_REGISTER);
+
+ for (Index = 0; Index < 21; Index++) {
+ outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
+ outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
+ }
+
+ outb (Private, ATT_ADDRESS_REGISTER, 0x20);
+
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
+ outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
+
+ SetDefaultPalette (Private);
+ ClearScreen (Private);
+}
+
+VOID
+BochsWrite (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 Reg,
+ UINT16 Data
+ )
+{
+ EFI_STATUS Status;
+
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+ Status = Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ PCI_BAR_IDX2,
+ 0x500 + (Reg << 1),
+ 1,
+ &Data
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
+ outw (Private, VBE_DISPI_IOPORT_DATA, Data);
+ }
+}
+
+UINT16
+BochsRead (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 Reg
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Data;
+
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+ Status = Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ PCI_BAR_IDX2,
+ 0x500 + (Reg << 1),
+ 1,
+ &Data
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);
+ Data = inw (Private, VBE_DISPI_IOPORT_DATA);
+ }
+ return Data;
+}
+
+VOID
+VgaOutb (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Reg,
+ UINT8 Data
+ )
+{
+ EFI_STATUS Status;
+
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {
+ Status = Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ PCI_BAR_IDX2,
+ 0x400 - 0x3c0 + Reg,
+ 1,
+ &Data
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ outb (Private, Reg, Data);
+ }
+}
+
+VOID
+InitializeBochsGraphicsMode (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ QEMU_VIDEO_BOCHS_MODES *ModeData
+ )
+{
+ DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",
+ ModeData->Width, ModeData->Height, ModeData->ColorDepth));
+
+ /* unblank */
+ VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);
+
+ BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);
+ BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);
+ BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);
+ BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);
+
+ BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);
+ BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);
+ BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);
+ BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);
+ BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);
+
+ BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,
+ VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+
+ SetDefaultPalette (Private);
+ ClearScreen (Private);
+}
+
+EFI_STATUS
+EFIAPI
+InitializeQemuVideo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gQemuVideoDriverBinding,
+ ImageHandle,
+ &gQemuVideoComponentName,
+ &gQemuVideoComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install EFI Driver Supported EFI Version Protocol required for
+ // EFI drivers that are on PCI and other plug in cards.
+ //
+ gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiDriverSupportedEfiVersionProtocolGuid,
+ &gQemuVideoDriverSupportedEfiVersion,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
new file mode 100644
index 0000000000..a743056382
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/DriverSupportedEfiVersion.c
@@ -0,0 +1,15 @@
+/** @file
+ Driver supported version protocol for the QEMU video driver.
+
+ Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gQemuVideoDriverSupportedEfiVersion = {
+ sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of Protocol structure.
+ 0 // Version number to be filled at start up.
+};
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
new file mode 100644
index 0000000000..bbb82fe867
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Gop.c
@@ -0,0 +1,416 @@
+/** @file
+ Graphics Output Protocol functions for the QEMU video controller.
+
+ Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+STATIC
+VOID
+QemuVideoCompleteModeInfo (
+ IN QEMU_VIDEO_MODE_DATA *ModeData,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
+ )
+{
+ Info->Version = 0;
+ if (ModeData->ColorDepth == 8) {
+ Info->PixelFormat = PixelBitMask;
+ Info->PixelInformation.RedMask = PIXEL_RED_MASK;
+ Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
+ Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
+ Info->PixelInformation.ReservedMask = 0;
+ } else if (ModeData->ColorDepth == 24) {
+ Info->PixelFormat = PixelBitMask;
+ Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
+ Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
+ Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
+ Info->PixelInformation.ReservedMask = 0;
+ } else if (ModeData->ColorDepth == 32) {
+ DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
+ Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+ }
+ Info->PixelsPerScanLine = Info->HorizontalResolution;
+}
+
+
+STATIC
+EFI_STATUS
+QemuVideoCompleteModeData (
+ IN QEMU_VIDEO_PRIVATE_DATA *Private,
+ OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
+ )
+{
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+
+ ModeData = &Private->ModeData[Mode->Mode];
+ Info = Mode->Info;
+ QemuVideoCompleteModeInfo (ModeData, Info);
+
+ Private->PciIo->GetBarAttributes (
+ Private->PciIo,
+ 0,
+ NULL,
+ (VOID**) &FrameBufDesc
+ );
+
+ Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
+ Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
+ Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
+ Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (
+ EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)
+ );
+ DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
+ Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));
+
+ FreePool (FrameBufDesc);
+ return EFI_SUCCESS;
+}
+
+//
+// Graphics Output Protocol Member Functions
+//
+EFI_STATUS
+EFIAPI
+QemuVideoGraphicsOutputQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol interface to query video mode
+
+ Arguments:
+ This - Protocol instance pointer.
+ ModeNumber - The mode number to return information on.
+ Info - Caller allocated buffer that returns information about ModeNumber.
+ SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
+
+ Returns:
+ EFI_SUCCESS - Mode information returned.
+ EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
+ EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
+ EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
+ EFI_INVALID_PARAMETER - One of the input args was NULL.
+
+--*/
+{
+ QEMU_VIDEO_PRIVATE_DATA *Private;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+
+ Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+ if (*Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ ModeData = &Private->ModeData[ModeNumber];
+ (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
+ (*Info)->VerticalResolution = ModeData->VerticalResolution;
+ QemuVideoCompleteModeInfo (ModeData, *Info);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+QemuVideoGraphicsOutputSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol interface to set video mode
+
+ Arguments:
+ This - Protocol instance pointer.
+ ModeNumber - The mode number to be set.
+
+ Returns:
+ EFI_SUCCESS - Graphics mode was changed.
+ EFI_DEVICE_ERROR - The device had an error and could not complete the request.
+ EFI_UNSUPPORTED - ModeNumber is not supported by this device.
+
+--*/
+{
+ QEMU_VIDEO_PRIVATE_DATA *Private;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+ RETURN_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
+
+ Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
+
+ if (ModeNumber >= This->Mode->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ModeData = &Private->ModeData[ModeNumber];
+
+ switch (Private->Variant) {
+ case QEMU_VIDEO_CIRRUS_5430:
+ case QEMU_VIDEO_CIRRUS_5446:
+ InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
+ break;
+ case QEMU_VIDEO_BOCHS_MMIO:
+ case QEMU_VIDEO_BOCHS:
+ InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
+ break;
+ default:
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+
+ This->Mode->Mode = ModeNumber;
+ This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+ This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+ This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ QemuVideoCompleteModeData (Private, This->Mode);
+
+ //
+ // Re-initialize the frame buffer configure when mode changes.
+ //
+ Status = FrameBufferBltConfigure (
+ (VOID*) (UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info,
+ Private->FrameBufferBltConfigure,
+ &Private->FrameBufferBltConfigureSize
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ //
+ // Frame buffer configure may be larger in new mode.
+ //
+ if (Private->FrameBufferBltConfigure != NULL) {
+ FreePool (Private->FrameBufferBltConfigure);
+ }
+ Private->FrameBufferBltConfigure =
+ AllocatePool (Private->FrameBufferBltConfigureSize);
+ ASSERT (Private->FrameBufferBltConfigure != NULL);
+
+ //
+ // Create the configuration for FrameBufferBltLib
+ //
+ Status = FrameBufferBltConfigure (
+ (VOID*) (UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info,
+ Private->FrameBufferBltConfigure,
+ &Private->FrameBufferBltConfigureSize
+ );
+ }
+ ASSERT (Status == RETURN_SUCCESS);
+
+ //
+ // Per UEFI Spec, need to clear the visible portions of the output display to black.
+ //
+ ZeroMem (&Black, sizeof (Black));
+ Status = FrameBufferBlt (
+ Private->FrameBufferBltConfigure,
+ &Black,
+ EfiBltVideoFill,
+ 0, 0,
+ 0, 0,
+ This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution,
+ 0
+ );
+ ASSERT_RETURN_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+QemuVideoGraphicsOutputBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+/*++
+
+Routine Description:
+
+ Graphics Output protocol instance to block transfer for CirrusLogic device
+
+Arguments:
+
+ This - Pointer to Graphics Output protocol instance
+ BltBuffer - The data to transfer to screen
+ BltOperation - The operation to perform
+ SourceX - The X coordinate of the source for BltOperation
+ SourceY - The Y coordinate of the source for BltOperation
+ DestinationX - The X coordinate of the destination for BltOperation
+ DestinationY - The Y coordinate of the destination for BltOperation
+ Width - The width of a rectangle in the blt rectangle in pixels
+ Height - The height of a rectangle in the blt rectangle in pixels
+ Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
+ If a Delta of 0 is used, the entire BltBuffer will be operated on.
+ If a subrectangle of the BltBuffer is used, then Delta represents
+ the number of bytes in a row of the BltBuffer.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter passed in
+ EFI_SUCCESS - Blt operation success
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_TPL OriginalTPL;
+ QEMU_VIDEO_PRIVATE_DATA *Private;
+
+ Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+ case EfiBltBufferToVideo:
+ case EfiBltVideoFill:
+ case EfiBltVideoToVideo:
+ Status = FrameBufferBlt (
+ Private->FrameBufferBltConfigure,
+ BltBuffer,
+ BltOperation,
+ SourceX,
+ SourceY,
+ DestinationX,
+ DestinationY,
+ Width,
+ Height,
+ Delta
+ );
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return Status;
+}
+
+EFI_STATUS
+QemuVideoGraphicsOutputConstructor (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+
+ GraphicsOutput = &Private->GraphicsOutput;
+ GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
+ GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
+ GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
+
+ //
+ // Initialize the private data
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
+ (VOID **) &Private->GraphicsOutput.Mode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **) &Private->GraphicsOutput.Mode->Info
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeMode;
+ }
+ Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
+ Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
+ Private->FrameBufferBltConfigure = NULL;
+ Private->FrameBufferBltConfigureSize = 0;
+
+ //
+ // Initialize the hardware
+ //
+ Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
+ if (EFI_ERROR (Status)) {
+ goto FreeInfo;
+ }
+
+ DrawLogo (
+ Private,
+ Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
+ Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
+ );
+
+ return EFI_SUCCESS;
+
+FreeInfo:
+ FreePool (Private->GraphicsOutput.Mode->Info);
+
+FreeMode:
+ FreePool (Private->GraphicsOutput.Mode);
+ Private->GraphicsOutput.Mode = NULL;
+
+ return Status;
+}
+
+EFI_STATUS
+QemuVideoGraphicsOutputDestructor (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ if (Private->FrameBufferBltConfigure != NULL) {
+ FreePool (Private->FrameBufferBltConfigure);
+ }
+
+ if (Private->GraphicsOutput.Mode != NULL) {
+ if (Private->GraphicsOutput.Mode->Info != NULL) {
+ gBS->FreePool (Private->GraphicsOutput.Mode->Info);
+ }
+ gBS->FreePool (Private->GraphicsOutput.Mode);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
new file mode 100644
index 0000000000..c8a76636af
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Initialize.c
@@ -0,0 +1,341 @@
+/** @file
+ Graphics Output Protocol functions for the QEMU video controller.
+
+ Copyright (c) 2007 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Simics.h"
+
+
+///
+/// Generic Attribute Controller Register Settings
+///
+UINT8 AttributeController[21] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00
+};
+
+///
+/// Generic Graphics Controller Register Settings
+///
+UINT8 GraphicsController[9] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
+};
+
+//
+// 640 x 480 x 256 color @ 60 Hertz
+//
+UINT8 Crtc_640_480_256_60[28] = {
+ 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22
+};
+
+UINT8 Crtc_640_480_32bpp_60[28] = {
+ 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x32
+};
+
+UINT16 Seq_640_480_256_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
+};
+
+UINT16 Seq_640_480_32bpp_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
+};
+
+//
+// 800 x 600 x 256 color @ 60 Hertz
+//
+UINT8 Crtc_800_600_256_60[28] = {
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22
+};
+
+UINT8 Crtc_800_600_32bpp_60[28] = {
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x32
+};
+
+UINT16 Seq_800_600_256_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
+};
+
+UINT16 Seq_800_600_32bpp_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
+};
+
+UINT8 Crtc_960_720_32bpp_60[28] = {
+ 0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x32
+};
+
+UINT16 Seq_960_720_32bpp_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+//
+// 1024 x 768 x 256 color @ 60 Hertz
+//
+UINT8 Crtc_1024_768_256_60[28] = {
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22
+};
+
+UINT16 Seq_1024_768_256_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+//
+// 1024 x 768 x 24-bit color @ 60 Hertz
+//
+UINT8 Crtc_1024_768_24bpp_60[28] = {
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x32
+};
+
+UINT16 Seq_1024_768_24bpp_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+UINT8 Crtc_1024_768_32bpp_60[28] = {
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x32
+};
+
+UINT16 Seq_1024_768_32bpp_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+///
+/// Table of supported video modes
+///
+QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[] = {
+// { 640, 480, 8, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 },
+// { 800, 600, 8, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef },
+ { 640, 480, 32, Crtc_640_480_32bpp_60, Seq_640_480_32bpp_60, 0xef },
+ { 800, 600, 32, Crtc_800_600_32bpp_60, Seq_800_600_32bpp_60, 0xef },
+// { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }
+ { 1024, 768, 24, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60, 0xef }
+// { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
+// { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
+};
+
+#define QEMU_VIDEO_CIRRUS_MODE_COUNT \
+ (ARRAY_SIZE (QemuVideoCirrusModes))
+
+/**
+ Construct the valid video modes for QemuVideo.
+
+**/
+EFI_STATUS
+QemuVideoCirrusModeSetup (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ )
+{
+ UINT32 Index;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+ QEMU_VIDEO_CIRRUS_MODES *VideoMode;
+
+ //
+ // Setup Video Modes
+ //
+ Private->ModeData = AllocatePool (
+ sizeof (Private->ModeData[0]) * QEMU_VIDEO_CIRRUS_MODE_COUNT
+ );
+ if (Private->ModeData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ModeData = Private->ModeData;
+ VideoMode = &QemuVideoCirrusModes[0];
+ for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) {
+ ModeData->InternalModeIndex = Index;
+ ModeData->HorizontalResolution = VideoMode->Width;
+ ModeData->VerticalResolution = VideoMode->Height;
+ ModeData->ColorDepth = VideoMode->ColorDepth;
+ DEBUG ((EFI_D_INFO,
+ "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",
+ (INT32) (ModeData - Private->ModeData),
+ ModeData->InternalModeIndex,
+ ModeData->HorizontalResolution,
+ ModeData->VerticalResolution,
+ ModeData->ColorDepth
+ ));
+
+ ModeData ++ ;
+ VideoMode ++;
+ }
+ Private->MaxMode = ModeData - Private->ModeData;
+
+ return EFI_SUCCESS;
+}
+
+///
+/// Table of supported video modes
+///
+QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[] = {
+ { 640, 480, 32 },
+ { 800, 480, 32 },
+ { 800, 600, 32 },
+ { 832, 624, 32 },
+ { 960, 640, 32 },
+ { 1024, 600, 32 },
+ { 1024, 768, 32 },
+ { 1152, 864, 32 },
+ { 1152, 870, 32 },
+ { 1280, 720, 32 },
+ { 1280, 760, 32 },
+ { 1280, 768, 32 },
+ { 1280, 800, 32 },
+ { 1280, 960, 32 },
+ { 1280, 1024, 32 },
+ { 1360, 768, 32 },
+ { 1366, 768, 32 },
+ { 1400, 1050, 32 },
+ { 1440, 900, 32 },
+ { 1600, 900, 32 },
+ { 1600, 1200, 32 },
+ { 1680, 1050, 32 },
+ { 1920, 1080, 32 },
+ { 1920, 1200, 32 },
+ { 1920, 1440, 32 },
+ { 2000, 2000, 32 },
+ { 2048, 1536, 32 },
+ { 2048, 2048, 32 },
+ { 2560, 1440, 32 },
+ { 2560, 1600, 32 },
+ { 2560, 2048, 32 },
+ { 2800, 2100, 32 },
+ { 3200, 2400, 32 },
+ { 3840, 2160, 32 },
+ { 4096, 2160, 32 },
+ { 7680, 4320, 32 },
+ { 8192, 4320, 32 }
+};
+
+#define QEMU_VIDEO_BOCHS_MODE_COUNT \
+ (ARRAY_SIZE (QemuVideoBochsModes))
+
+EFI_STATUS
+QemuVideoBochsModeSetup (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ BOOLEAN IsQxl
+ )
+{
+ UINT32 AvailableFbSize;
+ UINT32 Index;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+ QEMU_VIDEO_BOCHS_MODES *VideoMode;
+
+ //
+ // Fetch the available framebuffer size.
+ //
+ // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the
+ // drawable framebuffer. Up to and including qemu-2.1 however it used to
+ // return the size of PCI BAR 0 (ie. the full video RAM size).
+ //
+ // On stdvga the two concepts coincide with each other; the full memory size
+ // is usable for drawing.
+ //
+ // On QXL however, only a leading segment, "surface 0", can be used for
+ // drawing; the rest of the video memory is used for the QXL guest-host
+ // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of
+ // "surface 0", but since it doesn't (up to and including qemu-2.1), we
+ // retrieve the size of the drawable portion from a field in the QXL ROM BAR,
+ // where it is also available.
+ //
+ if (IsQxl) {
+ UINT32 Signature;
+ UINT32 DrawStart;
+
+ Signature = 0;
+ DrawStart = 0xFFFFFFFF;
+ AvailableFbSize = 0;
+ if (EFI_ERROR (
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+ PCI_BAR_IDX2, 0, 1, &Signature)) ||
+ Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||
+ EFI_ERROR (
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+ PCI_BAR_IDX2, 36, 1, &DrawStart)) ||
+ DrawStart != 0 ||
+ EFI_ERROR (
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,
+ PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {
+ DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "
+ "ROM\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
+ AvailableFbSize *= SIZE_64KB;
+ }
+ DEBUG ((EFI_D_INFO, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,
+ AvailableFbSize));
+
+ //
+ // Setup Video Modes
+ //
+ Private->ModeData = AllocatePool (
+ sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT
+ );
+ if (Private->ModeData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ModeData = Private->ModeData;
+ VideoMode = &QemuVideoBochsModes[0];
+ for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {
+ UINTN RequiredFbSize;
+
+ ASSERT (VideoMode->ColorDepth % 8 == 0);
+ RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *
+ (VideoMode->ColorDepth / 8);
+ if (RequiredFbSize <= AvailableFbSize) {
+ ModeData->InternalModeIndex = Index;
+ ModeData->HorizontalResolution = VideoMode->Width;
+ ModeData->VerticalResolution = VideoMode->Height;
+ ModeData->ColorDepth = VideoMode->ColorDepth;
+ DEBUG ((EFI_D_INFO,
+ "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit\n",
+ (INT32) (ModeData - Private->ModeData),
+ ModeData->InternalModeIndex,
+ ModeData->HorizontalResolution,
+ ModeData->VerticalResolution,
+ ModeData->ColorDepth
+ ));
+
+ ModeData ++ ;
+ }
+ VideoMode ++;
+ }
+ Private->MaxMode = ModeData - Private->ModeData;
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
new file mode 100644
index 0000000000..ba13e3d8e5
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.c
@@ -0,0 +1,302 @@
+/** @file
+ Install a fake VGABIOS service handler (real mode Int10h) for the buggy
+ Windows 2008 R2 SP1 UEFI guest.
+
+ The handler is never meant to be directly executed by a VCPU; it's there for
+ the internal real mode emulator of Windows 2008 R2 SP1.
+
+ The code is based on Ralf Brown's Interrupt List:
+ <http://www.cs.cmu.edu/~ralf/files.html>
+ <http://www.ctyme.com/rbrown.htm>
+
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <IndustryStandard/LegacyVgaBios.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PrintLib.h>
+#include <SimicsPlatforms.h>
+
+#include "Simics.h"
+#include "VbeShim.h"
+
+#pragma pack (1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} IVT_ENTRY;
+#pragma pack ()
+
+//
+// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
+// Advanced Settings dialog. It should be short.
+//
+STATIC CONST CHAR8 mProductRevision[] = "OVMF Int10h (fake)";
+
+/**
+ Install the VBE Info and VBE Mode Info structures, and the VBE service
+ handler routine in the C segment. Point the real-mode Int10h interrupt vector
+ to the handler. The only advertised mode is 1024x768x32.
+
+ @param[in] CardName Name of the video card to be exposed in the
+ Product Name field of the VBE Info structure. The
+ parameter must originate from a
+ QEMU_VIDEO_CARD.Name field.
+ @param[in] FrameBufferBase Guest-physical base address of the video card's
+ frame buffer.
+**/
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
+ UINTN Segment0Pages;
+ IVT_ENTRY *Int0x10;
+ EFI_STATUS Segment0AllocationStatus;
+ UINT16 HostBridgeDevId;
+ UINTN SegmentCPages;
+ VBE_INFO *VbeInfoFull;
+ VBE_INFO_BASE *VbeInfo;
+ UINT8 *Ptr;
+ UINTN Printed;
+ VBE_MODE_INFO *VbeModeInfo;
+
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: page 0 protected, not installing VBE shim\n",
+ __FUNCTION__
+ ));
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: page 0 protection prevents Windows 7 from booting anyway\n",
+ __FUNCTION__
+ ));
+ return;
+ }
+
+ Segment0 = 0x00000;
+ SegmentC = 0xC0000;
+ SegmentF = 0xF0000;
+
+ //
+ // Attempt to cover the real mode IVT with an allocation. This is a UEFI
+ // driver, hence the arch protocols have been installed previously. Among
+ // those, the CPU arch protocol has configured the IDT, so we can overwrite
+ // the IVT used in real mode.
+ //
+ // The allocation request may fail, eg. if LegacyBiosDxe has already run.
+ //
+ Segment0Pages = 1;
+ Int0x10 = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
+ Segment0AllocationStatus = gBS->AllocatePages (
+ AllocateAddress,
+ EfiBootServicesCode,
+ Segment0Pages,
+ &Segment0
+ );
+
+ if (EFI_ERROR (Segment0AllocationStatus)) {
+ EFI_PHYSICAL_ADDRESS Handler;
+
+ //
+ // Check if a video BIOS handler has been installed previously -- we
+ // shouldn't override a real video BIOS with our shim, nor our own shim if
+ // it's already present.
+ //
+ Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
+ if (Handler >= SegmentC && Handler < SegmentF) {
+ DEBUG ((EFI_D_INFO, "%a: Video BIOS handler found at %04x:%04x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+ return;
+ }
+
+ //
+ // Otherwise we'll overwrite the Int10h vector, even though we may not own
+ // the page at zero.
+ //
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: failed to allocate page at zero: %r\n",
+ __FUNCTION__,
+ Segment0AllocationStatus
+ ));
+ } else {
+ //
+ // We managed to allocate the page at zero. SVN r14218 guarantees that it
+ // is NUL-filled.
+ //
+ ASSERT (Int0x10->Segment == 0x0000);
+ ASSERT (Int0x10->Offset == 0x0000);
+ }
+
+ HostBridgeDevId = PcdGet16(PcdSimicsX58HostBridgePciDevId);
+ switch (HostBridgeDevId) {
+ case INTEL_ICH10_DEVICE_ID:
+ break;
+ default:
+ DEBUG((
+ DEBUG_ERROR,
+ "%a: unknown host bridge device ID: 0x%04x\n",
+ __FUNCTION__,
+ HostBridgeDevId
+ ));
+ ASSERT (FALSE);
+
+ if (!EFI_ERROR(Segment0AllocationStatus)) {
+ gBS->FreePages(Segment0, Segment0Pages);
+ }
+ return;
+ }
+ //
+ // low nibble covers 0xC0000 to 0xC3FFF
+ // high nibble covers 0xC4000 to 0xC7FFF
+ // bit1 in each nibble is Write Enable
+ // bit0 in each nibble is Read Enable
+ //
+
+ //
+ // We never added memory space during PEI or DXE for the C segment, so we
+ // don't need to (and can't) allocate from there. Also, guest operating
+ // systems will see a hole in the UEFI memory map there.
+ //
+ SegmentCPages = 4;
+
+ ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
+ CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim);
+
+ //
+ // Fill in the VBE INFO structure.
+ //
+ VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
+ VbeInfo = &VbeInfoFull->Base;
+ Ptr = VbeInfoFull->Buffer;
+
+ CopyMem (VbeInfo->Signature, "VESA", 4);
+ VbeInfo->VesaVersion = 0x0300;
+
+ VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+ CopyMem (Ptr, "QEMU", 5);
+ Ptr += 5;
+
+ VbeInfo->Capabilities = BIT0; // DAC can be switched into 8-bit mode
+
+ VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+ *(UINT16*)Ptr = 0x00f1; // mode number
+ Ptr += 2;
+ *(UINT16*)Ptr = 0xFFFF; // mode list terminator
+ Ptr += 2;
+
+ VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
+ VbeInfo->OemSoftwareVersion = 0x0000;
+
+ VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+ CopyMem (Ptr, "OVMF", 5);
+ Ptr += 5;
+
+ VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+ Printed = AsciiSPrint ((CHAR8 *)Ptr,
+ sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
+ CardName);
+ Ptr += Printed + 1;
+
+ VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
+ CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
+ Ptr += sizeof mProductRevision;
+
+ ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
+ ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
+
+ //
+ // Fil in the VBE MODE INFO structure.
+ //
+ VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
+
+ //
+ // bit0: mode supported by present hardware configuration
+ // bit1: optional information available (must be =1 for VBE v1.2+)
+ // bit3: set if color, clear if monochrome
+ // bit4: set if graphics mode, clear if text mode
+ // bit5: mode is not VGA-compatible
+ // bit7: linear framebuffer mode supported
+ //
+ VbeModeInfo->ModeAttr = BIT7 | BIT5 | BIT4 | BIT3 | BIT1 | BIT0;
+
+ //
+ // bit0: exists
+ // bit1: bit1: readable
+ // bit2: writeable
+ //
+ VbeModeInfo->WindowAAttr = BIT2 | BIT1 | BIT0;
+
+ VbeModeInfo->WindowBAttr = 0x00;
+ VbeModeInfo->WindowGranularityKB = 0x0040;
+ VbeModeInfo->WindowSizeKB = 0x0040;
+ VbeModeInfo->WindowAStartSegment = 0xA000;
+ VbeModeInfo->WindowBStartSegment = 0x0000;
+ VbeModeInfo->WindowPositioningAddress = 0x0000;
+ VbeModeInfo->BytesPerScanLine = 1024 * 4;
+
+ VbeModeInfo->Width = 1024;
+ VbeModeInfo->Height = 768;
+ VbeModeInfo->CharCellWidth = 8;
+ VbeModeInfo->CharCellHeight = 16;
+ VbeModeInfo->NumPlanes = 1;
+ VbeModeInfo->BitsPerPixel = 32;
+ VbeModeInfo->NumBanks = 1;
+ VbeModeInfo->MemoryModel = 6; // direct color
+ VbeModeInfo->BankSizeKB = 0;
+ VbeModeInfo->NumImagePagesLessOne = 0;
+ VbeModeInfo->Vbe3 = 0x01;
+
+ VbeModeInfo->RedMaskSize = 8;
+ VbeModeInfo->RedMaskPos = 16;
+ VbeModeInfo->GreenMaskSize = 8;
+ VbeModeInfo->GreenMaskPos = 8;
+ VbeModeInfo->BlueMaskSize = 8;
+ VbeModeInfo->BlueMaskPos = 0;
+ VbeModeInfo->ReservedMaskSize = 8;
+ VbeModeInfo->ReservedMaskPos = 24;
+
+ //
+ // bit1: Bytes in reserved field may be used by application
+ //
+ VbeModeInfo->DirectColorModeInfo = BIT1;
+
+ VbeModeInfo->LfbAddress = (UINT32)FrameBufferBase;
+ VbeModeInfo->OffScreenAddress = 0;
+ VbeModeInfo->OffScreenSizeKB = 0;
+
+ VbeModeInfo->BytesPerScanLineLinear = 1024 * 4;
+ VbeModeInfo->NumImagesLessOneBanked = 0;
+ VbeModeInfo->NumImagesLessOneLinear = 0;
+ VbeModeInfo->RedMaskSizeLinear = 8;
+ VbeModeInfo->RedMaskPosLinear = 16;
+ VbeModeInfo->GreenMaskSizeLinear = 8;
+ VbeModeInfo->GreenMaskPosLinear = 8;
+ VbeModeInfo->BlueMaskSizeLinear = 8;
+ VbeModeInfo->BlueMaskPosLinear = 0;
+ VbeModeInfo->ReservedMaskSizeLinear = 8;
+ VbeModeInfo->ReservedMaskPosLinear = 24;
+ VbeModeInfo->MaxPixelClockHz = 0;
+
+ ZeroMem (VbeModeInfo->Reserved, sizeof VbeModeInfo->Reserved);
+
+ //
+ // Clear Write Enable (bit1), keep Read Enable (bit0) set
+ //
+
+ //
+ // Second, point the Int10h vector at the shim.
+ //
+ Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
+ Int0x10->Offset = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+
+ DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__));
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
new file mode 100644
index 0000000000..b8d326cdb6
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/AcpiTables.inf
@@ -0,0 +1,31 @@
+## @file
+# Component description file for PlatformAcpiTables module.
+#
+# ACPI table data and ASL sources required to boot the platform.
+#
+# Copyright (c) 2008 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformAcpiTables
+ FILE_GUID = 7E374E25-8E01-4FEE-87F2-390C23C606CD
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ Platform.h
+ Dsdt.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
new file mode 100644
index 0000000000..8a6c3792ba
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Dsdt.asl
@@ -0,0 +1,821 @@
+/** @file
+ Contains root level name space objects for the platform
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+DefinitionBlock ("Dsdt.aml", "DSDT", 1, "INTEL ", "SIMICS ", 4) {
+ //
+ // System Sleep States
+ //
+ Name (\_S3, Package () {5, 5, 0, 0})
+ Name (\_S4, Package () {6, 6, 0, 0})
+ Name (\_S5, Package () {7, 7, 0, 0})
+
+ Name (GPIC, Zero)
+ Method (_PIC, 1, NotSerialized) // _PIC: Interrupt Model
+ {
+ GPIC = Arg0
+ }
+ //
+ // System Bus
+ //
+ Scope (\_SB) {
+ //
+ // PCI Root Bridge
+ //
+ Device (PCI0) {
+ Name (_HID, EISAID ("PNP0A03"))
+ Name (_ADR, 0x00000000)
+ Name (_BBN, 0x00)
+ Name (_UID, 0x00)
+
+
+ // Current resource settings
+ Name (_CRS, ResourceTemplate () {
+ WORDBusNumber ( // Bus number resource (0); the bridge produces bus numbers for its subsequent buses
+ ResourceProducer, // bit 0 of general flags is 1
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ PosDecode, // PosDecode
+ 0x0000, // Granularity
+ 0x0000, // Min
+ 0x00FF, // Max
+ 0x0000, // Translation
+ 0x0100 // Range Length = Max-Min+1
+ )
+
+ IO (Decode16, 0xCF8, 0xCF8, 0x01, 0x08) //Consumed resource (0xCF8-0xCFF)
+
+ WORDIO ( // Consumed-and-produced resource (all I/O below CF8)
+ ResourceProducer, // bit 0 of general flags is 0
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ PosDecode,
+ EntireRange,
+ 0x0000, // Granularity
+ 0x0000, // Min
+ 0x0CF7, // Max
+ 0x0000, // Translation
+ 0x0CF8 // Range Length
+ )
+
+ WORDIO ( // Consumed-and-produced resource (all I/O above CFF)
+ ResourceProducer, // bit 0 of general flags is 0
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is fixed
+ PosDecode,
+ EntireRange,
+ 0x0000, // Granularity
+ 0x0D00, // Min
+ 0xFFFF, // Max
+ 0x0000, // Translation
+ 0xF300 // Range Length
+ )
+
+ DWORDMEMORY ( // Descriptor for legacy VGA video RAM
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode,
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is Fixed
+ Cacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0x000A0000, // Min
+ 0x000BFFFF, // Max
+ 0x00000000, // Translation
+ 0x00020000 // Range Length
+ )
+
+ DWORDMEMORY ( // Descriptor for 32-bit MMIO
+ ResourceProducer, // bit 0 of general flags is 0
+ PosDecode,
+ MinFixed, // Range is fixed
+ MaxFixed, // Range is Fixed
+ NonCacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0xF0000000, // Min
+ 0xFBFFFFFF, // Max
+ 0x00000000, // Translation
+ 0x0C000000, // Range Length
+ , // ResourceSourceIndex
+ , // ResourceSource
+ PW32 // DescriptorName
+ )
+ })
+
+ //
+ // PCI Interrupt Routing Table - PIC Mode Only
+ //
+ // If you change the IRQ mapping here you also need
+ // to change the mapping in the south bridge
+ // (pci-conf.py) and in the BIOS.
+ // INTA -> 0xa (10)
+ // INTB -> 0xb (11)
+ // INTC -> 0xa (10)
+ // INTD -> 0xb (11)
+
+ Method (_PRT, 0, NotSerialized) {
+ If (GPIC) {
+ Return (AR00) // APIC Mode
+ }
+ Return (PR00) // PIC Mode
+ }
+
+ Name (PR00, Package(){
+ Package () {0x000FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ //
+ // Bus 0, Device 1
+ //
+ Package () {0x0001FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0002FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0002FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0002FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0002FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+ //
+ // Bus 0, Device 3
+ //
+ Package () {0x0003FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0003FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0003FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0003FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0004FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0004FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0004FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0004FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0005FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0005FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0005FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0005FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0006FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0006FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0006FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0006FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0007FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0007FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0007FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0007FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0008FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0008FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0008FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0008FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0009FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0009FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0009FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0009FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x000AFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000AFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000AFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000AFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x000BFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000BFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000BFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000BFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x000CFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000CFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000CFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000CFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x000DFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000DFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000DFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000DFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x000EFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000EFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000EFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000EFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x000FFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x000FFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x000FFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x000FFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00010FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00010FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00010FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00010FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00011FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00011FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00011FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00011FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00012FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00012FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00012FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00012FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00013FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00013FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00013FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00013FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00014FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00014FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00014FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00014FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00015FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00015FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00015FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00015FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00016FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00016FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00016FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00016FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00017FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00017FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00017FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00017FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00018FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00018FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00018FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00018FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0001EFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001EFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001EFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001EFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x00019FFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x00019FFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x00019FFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x00019FFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0001AFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001AFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001AFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001AFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0001BFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001BFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001BFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001BFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0001CFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001CFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001CFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001CFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0001DFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001DFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001DFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001DFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+
+ Package () {0x0001FFFFF, 0x00, \_SB.PCI0.LPC.LNKA, 0x00},
+ Package () {0x0001FFFFF, 0x01, \_SB.PCI0.LPC.LNKB, 0x00},
+ Package () {0x0001FFFFF, 0x02, \_SB.PCI0.LPC.LNKC, 0x00},
+ Package () {0x0001FFFFF, 0x03, \_SB.PCI0.LPC.LNKD, 0x00},
+ }
+ )
+
+ Name(AR00, Package(){
+
+ Package () {0x000FFFF, 0x00, 0, 16},
+ Package () {0x000FFFF, 0x01, 0, 17},
+ Package () {0x000FFFF, 0x02, 0, 18},
+ Package () {0x000FFFF, 0x03, 0, 19},
+
+ //
+ // Bus 0, Device 1
+ //
+ Package () {0x0001FFFF, 0x00, 0, 16},
+ Package () {0x0001FFFF, 0x01, 0, 17},
+ Package () {0x0001FFFF, 0x02, 0, 18},
+ Package () {0x0001FFFF, 0x03, 0, 19},
+
+ Package () {0x0002FFFF, 0x00, 0, 16},
+ Package () {0x0002FFFF, 0x01, 0, 17},
+ Package () {0x0002FFFF, 0x02, 0, 18},
+ Package () {0x0002FFFF, 0x03, 0, 19},
+ //
+ // Bus 0, Device 3
+ //
+ Package () {0x0003FFFF, 0x00, 0, 16},
+ Package () {0x0003FFFF, 0x01, 0, 17},
+ Package () {0x0003FFFF, 0x02, 0, 18},
+ Package () {0x0003FFFF, 0x03, 0, 19},
+
+ Package () {0x0004FFFF, 0x00, 0, 16},
+ Package () {0x0004FFFF, 0x01, 0, 17},
+ Package () {0x0004FFFF, 0x02, 0, 18},
+ Package () {0x0004FFFF, 0x03, 0, 19},
+
+ Package () {0x0005FFFF, 0x00, 0, 16},
+ Package () {0x0005FFFF, 0x01, 0, 17},
+ Package () {0x0005FFFF, 0x02, 0, 18},
+ Package () {0x0005FFFF, 0x03, 0, 19},
+
+ Package () {0x0006FFFF, 0x00, 0, 16},
+ Package () {0x0006FFFF, 0x01, 0, 17},
+ Package () {0x0006FFFF, 0x02, 0, 18},
+ Package () {0x0006FFFF, 0x03, 0, 19},
+
+ Package () {0x0007FFFF, 0x00, 0, 16},
+ Package () {0x0007FFFF, 0x01, 0, 17},
+ Package () {0x0007FFFF, 0x02, 0, 18},
+ Package () {0x0007FFFF, 0x03, 0, 19},
+
+ Package () {0x0008FFFF, 0x00, 0, 16},
+ Package () {0x0008FFFF, 0x01, 0, 17},
+ Package () {0x0008FFFF, 0x02, 0, 18},
+ Package () {0x0008FFFF, 0x03, 0, 19},
+
+ Package () {0x0009FFFF, 0x00, 0, 16},
+ Package () {0x0009FFFF, 0x01, 0, 17},
+ Package () {0x0009FFFF, 0x02, 0, 18},
+ Package () {0x0009FFFF, 0x03, 0, 19},
+
+ Package () {0x000AFFFF, 0x00, 0, 16},
+ Package () {0x000AFFFF, 0x01, 0, 17},
+ Package () {0x000AFFFF, 0x02, 0, 18},
+ Package () {0x000AFFFF, 0x03, 0, 19},
+
+ Package () {0x000BFFFF, 0x00, 0, 16},
+ Package () {0x000BFFFF, 0x01, 0, 17},
+ Package () {0x000BFFFF, 0x02, 0, 18},
+ Package () {0x000BFFFF, 0x03, 0, 19},
+
+ Package () {0x000CFFFF, 0x00, 0, 16},
+ Package () {0x000CFFFF, 0x01, 0, 17},
+ Package () {0x000CFFFF, 0x02, 0, 18},
+ Package () {0x000CFFFF, 0x03, 0, 19},
+
+ Package () {0x000DFFFF, 0x00, 0, 16},
+ Package () {0x000DFFFF, 0x01, 0, 17},
+ Package () {0x000DFFFF, 0x02, 0, 18},
+ Package () {0x000DFFFF, 0x03, 0, 19},
+
+ Package () {0x000EFFFF, 0x00, 0, 16},
+ Package () {0x000EFFFF, 0x01, 0, 17},
+ Package () {0x000EFFFF, 0x02, 0C, 18},
+ Package () {0x000EFFFF, 0x03, 0, 19},
+
+ Package () {0x000FFFFF, 0x00, 0, 16},
+ Package () {0x000FFFFF, 0x01, 0, 17},
+ Package () {0x000FFFFF, 0x02, 0, 18},
+ Package () {0x000FFFFF, 0x03, 0, 19},
+
+ Package () {0x00010FFFF, 0x00, 0, 16},
+ Package () {0x00010FFFF, 0x01, 0, 17},
+ Package () {0x00010FFFF, 0x02, 0, 18},
+ Package () {0x00010FFFF, 0x03, 0, 19},
+
+ Package () {0x00011FFFF, 0x00, 0, 16},
+ Package () {0x00011FFFF, 0x01, 0, 17},
+ Package () {0x00011FFFF, 0x02, 0, 18},
+ Package () {0x00011FFFF, 0x03, 0, 19},
+
+ Package () {0x00012FFFF, 0x00, 0, 16},
+ Package () {0x00012FFFF, 0x01, 0, 17},
+ Package () {0x00012FFFF, 0x02, 0, 18},
+ Package () {0x00012FFFF, 0x03, 0, 19},
+
+ Package () {0x00013FFFF, 0x00, 0, 16},
+ Package () {0x00013FFFF, 0x01, 0, 17},
+ Package () {0x00013FFFF, 0x02, 0, 18},
+ Package () {0x00013FFFF, 0x03, 0, 19},
+
+ Package () {0x00014FFFF, 0x00, 0, 16},
+ Package () {0x00014FFFF, 0x01, 0, 17},
+ Package () {0x00014FFFF, 0x02, 0, 18},
+ Package () {0x00014FFFF, 0x03, 0, 19},
+
+ Package () {0x00015FFFF, 0x00, 0, 16},
+ Package () {0x00015FFFF, 0x01, 0, 17},
+ Package () {0x00015FFFF, 0x02, 0, 18},
+ Package () {0x00015FFFF, 0x03, 0, 19},
+
+ Package () {0x00016FFFF, 0x00, 0, 16},
+ Package () {0x00016FFFF, 0x01, 0, 17},
+ Package () {0x00016FFFF, 0x02, 0, 18},
+ Package () {0x00016FFFF, 0x03, 0, 19},
+
+ Package () {0x00017FFFF, 0x00, 0, 16},
+ Package () {0x00017FFFF, 0x01, 0, 17},
+ Package () {0x00017FFFF, 0x02, 0, 18},
+ Package () {0x00017FFFF, 0x03, 0, 19},
+
+ Package () {0x00018FFFF, 0x00, 0, 16},
+ Package () {0x00018FFFF, 0x01, 0, 17},
+ Package () {0x00018FFFF, 0x02, 0, 18},
+ Package () {0x00018FFFF, 0x03, 0, 19},
+
+ Package () {0x0001EFFFF, 0x00, 0, 16},
+ Package () {0x0001EFFFF, 0x01, 0, 17},
+ Package () {0x0001EFFFF, 0x02, 0, 18},
+ Package () {0x0001EFFFF, 0x03, 0, 19},
+
+ Package () {0x00019FFFF, 0x00, 0, 16},
+ Package () {0x00019FFFF, 0x01, 0, 17},
+ Package () {0x00019FFFF, 0x02, 0, 18},
+ Package () {0x00019FFFF, 0x03, 0, 19},
+
+ Package () {0x0001AFFFF, 0x00, 0, 16},
+ Package () {0x0001AFFFF, 0x01, 0, 17},
+ Package () {0x0001AFFFF, 0x02, 0, 18},
+ Package () {0x0001AFFFF, 0x03, 0, 19},
+
+ Package () {0x0001BFFFF, 0x00, 0, 16},
+ Package () {0x0001BFFFF, 0x01, 0, 17},
+ Package () {0x0001BFFFF, 0x02, 0, 18},
+ Package () {0x0001BFFFF, 0x03, 0, 19},
+
+ Package () {0x0001CFFFF, 0x00, 0, 16},
+ Package () {0x0001CFFFF, 0x01, 0, 17},
+ Package () {0x0001CFFFF, 0x02, 0, 18},
+ Package () {0x0001CFFFF, 0x03, 0, 19},
+
+ Package () {0x0001DFFFF, 0x00, 0, 16},
+ Package () {0x0001DFFFF, 0x01, 0, 17},
+ Package () {0x0001DFFFF, 0x02, 0, 18},
+ Package () {0x0001DFFFF, 0x03, 0, 19},
+
+ Package () {0x0001FFFFF, 0x00, 0, 16},
+ Package () {0x0001FFFFF, 0x01, 0, 17},
+ Package () {0x0001FFFFF, 0x02, 0, 18},
+ Package () {0x0001FFFFF, 0x03, 0, 19},
+ }
+ )
+
+ //
+ // PCI to ISA Bridge (Bus 0, Device 7, Function 0)
+ //
+ Device (LPC) {
+ Name (_ADR, 0x001F0000)
+
+ //
+ // PCI Interrupt Routing Configuration Registers
+ //
+ OperationRegion (PRR0, PCI_Config, 0x60, 0x0C)
+ Field (PRR0, ANYACC, NOLOCK, PRESERVE) {
+ PIRA, 8,
+ PIRB, 8,
+ PIRC, 8,
+ PIRD, 8,
+ Offset (0x04),
+ PIRE, 8,
+ PIRF, 8,
+ PIRG, 8,
+ PIRH, 8
+ }
+
+ //
+ // _STA method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+ //
+ Method (PSTA, 1, NotSerialized) {
+ If (And (Arg0, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ }
+ }
+
+ //
+ // _DIS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+ //
+ Method (PDIS, 1, NotSerialized) {
+ Or (Arg0, 0x80, Arg0)
+ }
+
+ //
+ // _CRS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+ //
+ Method (PCRS, 1, NotSerialized) {
+ Name (BUF0, ResourceTemplate () {IRQ (Level, ActiveLow, Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (Arg0, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One, Local0)
+ }
+ //
+ // Shift 1 by value in register 70
+ //
+ ShiftLeft (Local0, And (Arg0, 0x0F), IRQW) // Save in buffer
+ Return (BUF0) // Return Buf0
+ }
+
+ //
+ // _PRS resource for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+ //
+ Name (PPRS, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {3, 4, 5, 7, 9, 10, 11, 12, 14, 15}
+ })
+
+ //
+ // _SRS method for LNKA, LNKB, LNKC, LNKD, LNKE, LNKF, LNKG, LNKH
+ //
+ Method (PSRS, 2, NotSerialized) {
+ CreateWordField (Arg1, 0x01, IRQW) // IRQ low
+ FindSetRightBit (IRQW, Local0) // Set IRQ
+ If (LNotEqual (IRQW, Zero)) {
+ And (Local0, 0x7F, Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80, Local0)
+ }
+ Store (Local0, Arg0)
+ }
+
+ //
+ // PCI IRQ Link A
+ //
+ Device (LNKA) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 1)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRA)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRA) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRA)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRA, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link B
+ //
+ Device (LNKB) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 2)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRB)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRB) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRB)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRB, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link C
+ //
+ Device (LNKC) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 3)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRC)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRC) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRC)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRC, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link D
+ //
+ Device (LNKD) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 4)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRD)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRD) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRD)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRD, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link E
+ //
+ Device (LNKE) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 5)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRE)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRE) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRE)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRE, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link F
+ //
+ Device (LNKF) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 6)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRF)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRF) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRF)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRF, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link G
+ //
+ Device (LNKG) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 7)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRG)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRG) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRG)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRG, Arg0) }
+ }
+
+ //
+ // PCI IRQ Link H
+ //
+ Device (LNKH) {
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 8)
+
+ Method (_STA, 0, NotSerialized) { Return (PSTA (PIRH)) }
+ Method (_DIS, 0, NotSerialized) { PDIS (PIRH) }
+ Method (_CRS, 0, NotSerialized) { Return (PCRS (PIRH)) }
+ Method (_PRS, 0, NotSerialized) { Return (PPRS) }
+ Method (_SRS, 1, NotSerialized) { PSRS (PIRH, Arg0) }
+ }
+
+ //
+ // Programmable Interrupt Controller (PIC)
+ //
+ Device(PIC) {
+ Name (_HID, EISAID ("PNP0000"))
+ Name (_CRS, ResourceTemplate () {
+ IO (Decode16, 0x020, 0x020, 0x00, 0x02)
+ IO (Decode16, 0x0A0, 0x0A0, 0x00, 0x02)
+ IO (Decode16, 0x4D0, 0x4D0, 0x00, 0x02)
+ IRQNoFlags () {2}
+ })
+ }
+
+ //
+ // ISA DMA
+ //
+ Device (DMAC) {
+ Name (_HID, EISAID ("PNP0200"))
+ Name (_CRS, ResourceTemplate () {
+ IO (Decode16, 0x00, 0x00, 0, 0x10)
+ IO (Decode16, 0x81, 0x81, 0, 0x03)
+ IO (Decode16, 0x87, 0x87, 0, 0x01)
+ IO (Decode16, 0x89, 0x89, 0, 0x03)
+ IO (Decode16, 0x8f, 0x8f, 0, 0x01)
+ IO (Decode16, 0xc0, 0xc0, 0, 0x20)
+ DMA (Compatibility, NotBusMaster, Transfer8) {4}
+ })
+ }
+
+ //
+ // 8254 Timer
+ //
+ Device(TMR) {
+ Name(_HID,EISAID("PNP0100"))
+ Name(_CRS, ResourceTemplate () {
+ IO (Decode16, 0x40, 0x40, 0x00, 0x04)
+ IRQNoFlags () {0}
+ })
+ }
+
+ //
+ // Real Time Clock
+ //
+ Device (RTC) {
+ Name (_HID, EISAID ("PNP0B00"))
+ Name (_CRS, ResourceTemplate () {
+ IO (Decode16, 0x70, 0x70, 0x00, 0x02)
+ IRQNoFlags () {8}
+ })
+ }
+
+ //
+ // PCAT Speaker
+ //
+ Device(SPKR) {
+ Name (_HID, EISAID("PNP0800"))
+ Name (_CRS, ResourceTemplate () {
+ IO (Decode16, 0x61, 0x61, 0x01, 0x01)
+ })
+ }
+
+ //
+ // Floating Point Coprocessor
+ //
+ Device(FPU) {
+ Name (_HID, EISAID("PNP0C04"))
+ Name (_CRS, ResourceTemplate () {
+ IO (Decode16, 0xF0, 0xF0, 0x00, 0x10)
+ IRQNoFlags () {13}
+ })
+ }
+
+ //
+ // Generic motherboard devices and pieces that don't fit anywhere else
+ //
+ Device(XTRA) {
+ Name (_HID, EISAID ("PNP0C02"))
+ Name (_UID, 0x01)
+ Name (_CRS, ResourceTemplate () {
+ IO (Decode16, 0x010, 0x010, 0x00, 0x10)
+ IO (Decode16, 0x022, 0x022, 0x00, 0x1E)
+ IO (Decode16, 0x044, 0x044, 0x00, 0x1C)
+ IO (Decode16, 0x062, 0x062, 0x00, 0x02)
+ IO (Decode16, 0x065, 0x065, 0x00, 0x0B)
+ IO (Decode16, 0x072, 0x072, 0x00, 0x0E)
+ IO (Decode16, 0x080, 0x080, 0x00, 0x01)
+ IO (Decode16, 0x084, 0x084, 0x00, 0x03)
+ IO (Decode16, 0x088, 0x088, 0x00, 0x01)
+ IO (Decode16, 0x08c, 0x08c, 0x00, 0x03)
+ IO (Decode16, 0x090, 0x090, 0x00, 0x10)
+ IO (Decode16, 0x0A2, 0x0A2, 0x00, 0x1E)
+ IO (Decode16, 0x0E0, 0x0E0, 0x00, 0x10)
+ IO (Decode16, 0x1E0, 0x1E0, 0x00, 0x10)
+ IO (Decode16, 0x160, 0x160, 0x00, 0x10)
+ IO (Decode16, 0x278, 0x278, 0x00, 0x08)
+ IO (Decode16, 0x370, 0x370, 0x00, 0x02)
+ IO (Decode16, 0x378, 0x378, 0x00, 0x08)
+ IO (Decode16, 0x400, 0x400, 0x00, 0x40) // PMBLK1
+ IO (Decode16, 0x440, 0x440, 0x00, 0x10)
+ IO (Decode16, 0x678, 0x678, 0x00, 0x08)
+ IO (Decode16, 0x778, 0x778, 0x00, 0x08)
+ Memory32Fixed (ReadOnly, 0xFEC00000, 0x1000) // IO APIC
+ Memory32Fixed (ReadOnly, 0xFEE00000, 0x100000) // LAPIC
+ })
+ }
+
+ //
+ // PS/2 Keyboard and PC/AT Enhanced Keyboard 101/102
+ //
+ Device (PS2K) {
+ Name (_HID, EISAID ("PNP0303"))
+ Name (_CID, EISAID ("PNP030B"))
+ Name(_CRS,ResourceTemplate() {
+ IO (Decode16, 0x60, 0x60, 0x00, 0x01)
+ IO (Decode16, 0x64, 0x64, 0x00, 0x01)
+ IRQNoFlags () {1}
+ })
+ }
+
+ //
+ // PS/2 Mouse and Microsoft Mouse
+ //
+ Device (PS2M) { // PS/2 stype mouse port
+ Name (_HID, EISAID ("PNP0F03"))
+ Name (_CID, EISAID ("PNP0F13"))
+ Name (_CRS, ResourceTemplate() {
+ IRQNoFlags () {12}
+ })
+ }
+
+ //
+ // UART Serial Port - COM1
+ //
+ Device (UAR1) {
+ Name (_HID, EISAID ("PNP0501"))
+ Name (_DDN, "COM1")
+ Name (_UID, 0x01)
+ Name(_CRS,ResourceTemplate() {
+ IO (Decode16, 0x3F8, 0x3F8, 0x00, 0x08)
+ IRQ (Edge, ActiveHigh, Exclusive, ) {4}
+ })
+ }
+
+ //
+ // UART Serial Port - COM2
+ //
+ Device (UAR2) {
+ Name (_HID, EISAID ("PNP0501"))
+ Name (_DDN, "COM2")
+ Name (_UID, 0x02)
+ Name(_CRS,ResourceTemplate() {
+ IO (Decode16, 0x2F8, 0x2F8, 0x00, 0x08)
+ IRQ (Edge, ActiveHigh, Exclusive, ) {3}
+ })
+ }
+ }
+ }
+ }
+}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
new file mode 100644
index 0000000000..e98aac4676
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.h
@@ -0,0 +1,45 @@
+/** @file
+ This is an implementation of the ACPI platform driver.
+
+ Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+//
+// Statements that include other header files
+//
+
+#include <Base.h>
+#include <Uefi.h>
+#include <IndustryStandard/Pci30.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+#include <IndustryStandard/WindowsSmmSecurityMitigationTable.h>
+#include <Register/Hpet.h>
+#include <Guid/EventGroup.h>
+#include <Guid/GlobalVariable.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BoardAcpiTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/AslUpdateLib.h>
+#include <Library/PciSegmentInfoLib.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/MpService.h>
+#include <Protocol/PciIo.h>
+
+#include <Register/Cpuid.h>
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
new file mode 100644
index 0000000000..7dfd0832a3
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/MinPlatformAcpiTables/AcpiPlatform.inf
@@ -0,0 +1,105 @@
+## @file
+# Component information file for AcpiPlatform module
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = FC90EB7A-3E0A-483C-A26C-484D36593FF4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InstallAcpiPlatform
+
+[Sources.common]
+ AcpiPlatform.h
+ AcpiPlatform.c
+ Fadt/Fadt.c
+ Facs/Facs.c
+ Hpet/Hpet.c
+ Wsmt/Wsmt.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ BaseLib
+ DebugLib
+ IoLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ HobLib
+ PciSegmentInfoLib
+ AslUpdateLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+ gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicEnable
+ gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicCount
+ gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicIdBase
+ gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicAddressBase
+ gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicInterruptBase
+ gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuThreadCount
+ gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+ gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+
+ gMinPlatformPkgTokenSpaceGuid.PcdFadtPreferredPmProfile
+ gMinPlatformPkgTokenSpaceGuid.PcdFadtIaPcBootArch
+ gMinPlatformPkgTokenSpaceGuid.PcdFadtFlags
+
+ gPcAtChipsetPkgTokenSpaceGuid.PcdHpetBaseAddress
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdPciExpressRegionLength
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiEnableSwSmi
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiDisableSwSmi
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AEventBlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BEventBlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1AControlBlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm1BControlBlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiPm2ControlBlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiPmTimerBlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe0BlockAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdAcpiGpe1BlockAddress
+
+ gMinPlatformPkgTokenSpaceGuid.PcdLocalApicAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdIoApicAddress
+ gMinPlatformPkgTokenSpaceGuid.PcdIoApicId
+
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+ gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+
+ gMinPlatformPkgTokenSpaceGuid.PcdWsmtProtectionFlags
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+ gEfiMpServiceProtocolGuid ## CONSUMES
+ gEfiPciIoProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiGlobalVariableGuid ## CONSUMES
+ gEfiHobListGuid ## CONSUMES
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES
+
+[Depex]
+ gEfiAcpiTableProtocolGuid AND
+ gEfiMpServiceProtocolGuid AND
+ gEfiPciRootBridgeIoProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
+
+
diff --git a/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
new file mode 100644
index 0000000000..6a4fcb172b
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/AcpiTables/Platform.h
@@ -0,0 +1,75 @@
+/** @file
+ Platform specific defines for constructing ACPI tables
+
+ Copyright (c) 2013 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID 'S','I','M','I','C','S' // OEMID 6 bytes long
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('S','I','M','I','C','S','T','B') // OEM table id 8 bytes long
+#define EFI_ACPI_OEM_REVISION 0x02000820
+#define EFI_ACPI_CREATOR_ID SIGNATURE_32('Q','S','P',' ')
+#define EFI_ACPI_CREATOR_REVISION 0x00000097
+
+#define INT_MODEL 0x01
+#define SCI_INT_VECTOR 0x0009
+#define SMI_CMD_IO_PORT 0xB2
+#define ACPI_ENABLE 0x0E1
+#define ACPI_DISABLE 0x01E
+#define S4BIOS_REQ 0x00
+#define PM1a_EVT_BLK 0x00000400
+#define PM1b_EVT_BLK 0x00000000
+#define PM1a_CNT_BLK 0x00000404
+#define PM1b_CNT_BLK 0x00000000
+#define PM2_CNT_BLK 0x00000450
+#define PM_TMR_BLK 0x00000408
+#define GPE0_BLK 0x00000420
+#define GPE1_BLK 0x00000000
+#define PM1_EVT_LEN 0x04
+#define PM1_CNT_LEN 0x04
+#define PM2_CNT_LEN 0x01
+#define PM_TM_LEN 0x04
+#define GPE0_BLK_LEN 0x10
+#define GPE1_BLK_LEN 0x00
+#define GPE1_BASE 0x00
+#define RESERVED 0x00
+#define P_LVL2_LAT 0x0065
+#define P_LVL3_LAT 0x03E9
+#define FLUSH_SIZE 0x0400
+#define FLUSH_STRIDE 0x0010
+#define DUTY_OFFSET 0x00
+#define DUTY_WIDTH 0x00
+#define DAY_ALRM 0x0D
+#define MON_ALRM 0x00
+#define CENTURY 0x00
+#define FLAG (EFI_ACPI_2_0_WBINVD | \
+ EFI_ACPI_2_0_PROC_C1 | \
+ EFI_ACPI_2_0_SLP_BUTTON | \
+ EFI_ACPI_2_0_RTC_S4 | \
+ EFI_ACPI_2_0_RESET_REG_SUP)
+#define RESET_REG 0xCF9
+#define RESET_VALUE (BIT2 | BIT1) // PIIX3 Reset CPU + System Reset
+
+//
+// Byte-aligned IO port register block initializer for
+// EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE
+//
+#define GAS2_IO(Base, Size) { \
+ EFI_ACPI_2_0_SYSTEM_IO, /* AddressSpaceId */ \
+ (Size) * 8, /* RegisterBitWidth */ \
+ 0, /* RegisterBitOffset */ \
+ 0, /* Reserved */ \
+ (Base) /* Address */ \
+ }
+
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp b/Platform/Intel/SimicsOpenBoardPkg/Logo/Logo.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..86d7030833a096f545393735d931d9f4f2fbf8c0
GIT binary patch
literal 141078
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
TuM~Ktz$*n_Dey{xHWc`O(cS1K
literal 0
HcmV?d00001
diff --git a/Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec b/Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
new file mode 100644
index 0000000000..40487820fa
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/OpenBoardPkg.dec
@@ -0,0 +1,152 @@
+## @file
+# EFI/Framework Simics platform
+#
+# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = SimicsOpenBoardPkg
+ PACKAGE_GUID = E6A03E0D-5944-4dc6-9292-090D609EDD3A
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[Guids]
+ gBoardModuleTokenSpaceGuid = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
+ gSimicsBoardConfigGuid = {0xeed35f57, 0x4ff2, 0x4244, {0xb8, 0x3a, 0xea, 0x71, 0x5f, 0xd3, 0x59, 0xa5}}
+
+[PcdsFixedAtBuild]
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvBase|0x0|UINT32|0
+ gBoardModuleTokenSpaceGuid.PcdSimicsPeiMemFvSize|0x0|UINT32|1
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvBase|0x0|UINT32|0x15
+ gBoardModuleTokenSpaceGuid.PcdSimicsDxeMemFvSize|0x0|UINT32|0x16
+
+ #TODO: Remove these two when we integrate new PlatformPei
+ gBoardModuleTokenSpaceGuid.PcdSimicsMemFvBase|0x00800000|UINT32|2
+ gBoardModuleTokenSpaceGuid.PcdSimicsMemFvSize|0x00500000|UINT32|3
+
+ gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogBase|0x0|UINT32|0x8
+ gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageEventLogSize|0x0|UINT32|0x9
+ gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareFdSize|0x0|UINT32|0xa
+ gBoardModuleTokenSpaceGuid.PcdSimicsFirmwareBlockSize|0|UINT32|0xb
+ gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageVariableBase|0x0|UINT32|0xc
+ gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwSpareBase|0x0|UINT32|0xd
+ gBoardModuleTokenSpaceGuid.PcdSimicsFlashNvStorageFtwWorkingBase|0x0|UINT32|0xe
+ gBoardModuleTokenSpaceGuid.PcdSimicsFdBaseAddress|0x0|UINT32|0xf
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesBase|0x0|UINT32|0x11
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPageTablesSize|0x0|UINT32|0x12
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamBase|0x0|UINT32|0x13
+ gBoardModuleTokenSpaceGuid.PcdSimicsSecPeiTempRamSize|0x0|UINT32|0x14
+ gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageBase|0x0|UINT32|0x18
+ gBoardModuleTokenSpaceGuid.PcdSimicsLockBoxStorageSize|0x0|UINT32|0x19
+ gBoardModuleTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32|0x1a
+ gBoardModuleTokenSpaceGuid.PcdSimicsDecompressionScratchEnd|0x0|UINT32|0x1f
+
+[PcdsDynamic, PcdsDynamicEx]
+
+ # TODO: investigate whether next two Pcds are needed
+ gBoardModuleTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|0x28
+ gBoardModuleTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
+ gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId|0|UINT16|0x1b
+
+ ## The IO port aperture shared by all PCI root bridges.
+ #
+ gBoardModuleTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22
+ gBoardModuleTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x23
+
+ ## The 32-bit MMIO aperture shared by all PCI root bridges.
+ #
+ gBoardModuleTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT64|0x24
+ gBoardModuleTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT64|0x25
+
+ ## The 64-bit MMIO aperture shared by all PCI root bridges.
+ #
+ gBoardModuleTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x26
+ gBoardModuleTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x27
+
+[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule]
+ ## Pcd8259LegacyModeMask defines the default mask value for platform. This value is determined<BR><BR>
+ # 1) If platform only support pure UEFI, value should be set to 0xFFFF or 0xFFFE;
+ # Because only clock interrupt is allowed in legacy mode in pure UEFI platform.<BR>
+ # 2) If platform install CSM and use thunk module:<BR>
+ # a) If thunk call provided by CSM binary requires some legacy interrupt support, the corresponding bit
+ # should be opened as 0.<BR>
+ # For example, if keyboard interfaces provided CSM binary use legacy keyboard interrupt in 8259 bit 1, then
+ # the value should be set to 0xFFFC.<BR>
+ # b) If all thunk call provied by CSM binary do not require legacy interrupt support, value should be set
+ # to 0xFFFF or 0xFFFE.<BR>
+ #
+ # The default value of legacy mode mask could be changed by EFI_LEGACY_8259_PROTOCOL->SetMask(). But it is rarely
+ # need change it except some special cases such as when initializing the CSM binary, it should be set to 0xFFFF to
+ # mask all legacy interrupt. Please restore the original legacy mask value if changing is made for these special case.<BR>
+ # @Prompt 8259 Legacy Mode mask.
+ gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFF|UINT16|0x00000001
+
+ ## Pcd8259LegacyModeEdgeLevel defines the default edge level for legacy mode's interrrupt controller.
+ # For the corresponding bits, 0 = Edge triggered and 1 = Level triggered.
+ # @Prompt 8259 Legacy Mode edge level.
+ gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000|UINT16|0x00000002
+
+ ## Indicates if we need enable IsaAcpiCom1 device.<BR><BR>
+ # TRUE - Enables IsaAcpiCom1 device.<BR>
+ # FALSE - Doesn't enable IsaAcpiCom1 device.<BR>
+ # @Prompt Enable IsaAcpiCom1 device.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiCom1Enable|TRUE|BOOLEAN|0x00000003
+
+ ## Indicates if we need enable IsaAcpiCom2 device.<BR><BR>
+ # TRUE - Enables IsaAcpiCom2 device.<BR>
+ # FALSE - Doesn't enable IsaAcpiCom2 device.<BR>
+ # @Prompt Enable IsaAcpiCom12 device.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiCom2Enable|TRUE|BOOLEAN|0x00000004
+
+ ## Indicates if we need enable IsaAcpiPs2Keyboard device.<BR><BR>
+ # TRUE - Enables IsaAcpiPs2Keyboard device.<BR>
+ # FALSE - Doesn't enable IsaAcpiPs2Keyboard device.<BR>
+ # @Prompt Enable IsaAcpiPs2Keyboard device.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiPs2KeyboardEnable|TRUE|BOOLEAN|0x00000005
+
+ ## Indicates if we need enable IsaAcpiPs2Mouse device.<BR><BR>
+ # TRUE - Enables IsaAcpiPs2Mouse device.<BR>
+ # FALSE - Doesn't enable IsaAcpiPs2Mouse device.<BR>
+ # @Prompt Enable IsaAcpiPs2Mouse device.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiPs2MouseEnable|TRUE|BOOLEAN|0x00000006
+
+ ## Indicates if we need enable IsaAcpiFloppyA device.<BR><BR>
+ # TRUE - Enables IsaAcpiFloppyA device.<BR>
+ # FALSE - Doesn't enable IsaAcpiFloppyA device.<BR>
+ # @Prompt Enable IsaAcpiFloppyA device.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiFloppyAEnable|TRUE|BOOLEAN|0x00000007
+
+ ## Indicates if we need enable IsaAcpiFloppyB device.<BR><BR>
+ # TRUE - Enables IsaAcpiFloppyB device.<BR>
+ # FALSE - Doesn't enable IsaAcpiFloppyB device.<BR>
+ # @Prompt Enable IsaAcpiFloppyB device.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIsaAcpiFloppyBEnable|TRUE|BOOLEAN|0x00000008
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ ## FFS filename to find the shell application.
+ # @Prompt FFS Name of Shell Application
+ gBoardModuleTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }|VOID*|0x40000004
+
+ ## ISA Bus features to support DMA, SlaveDMA and ISA Memory. <BR><BR>
+ # BIT0 indicates if DMA is supported<BR>
+ # BIT1 indicates if only slave DMA is supported<BR>
+ # BIT2 indicates if ISA memory is supported<BR>
+ # Other BITs are reseved and must be zero.
+ # If more than one features are supported, the different BIT will be enabled at the same time.
+ # @Prompt ISA Bus Features
+ # @Expression 0x80000002 | (gBoardModuleTokenSpaceGuid.PcdIsaBusSupportedFeatures & 0xF8) == 0
+ gBoardModuleTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x00010040
+
+ gBoardModuleTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|0x00010037
+
+[Protocols]
+ ##
+ ## IntelFrameworkModulePkg
+ ##
+ gEfiOemBadgingProtocolGuid = { 0x170E13C0, 0xBF1B, 0x4218, { 0x87, 0x1D, 0x2A, 0xBD, 0xC6, 0xF8, 0x87, 0xBC }}
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
new file mode 100644
index 0000000000..f6ef44a14f
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/Simics.h
@@ -0,0 +1,507 @@
+/** @file
+ QEMU Video Controller Driver
+
+ Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// QEMU Video Controller Driver
+//
+
+#ifndef _QEMU_H_
+#define _QEMU_H_
+
+
+#include <Uefi.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/TimerLib.h>
+#include <Library/FrameBufferBltLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+
+#include <Library/S3BootScriptLib.h>
+
+//
+// QEMU Video PCI Configuration Header values
+//
+#define CIRRUS_LOGIC_VENDOR_ID 0x1013
+#define CIRRUS_LOGIC_5430_DEVICE_ID 0x00a8
+#define CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID 0x00a0
+#define CIRRUS_LOGIC_5446_DEVICE_ID 0x00b8
+
+//
+// QEMU Vide Graphical Mode Data
+//
+typedef struct {
+ UINT32 InternalModeIndex; // points into card-specific mode table
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 ColorDepth;
+} QEMU_VIDEO_MODE_DATA;
+
+#define PIXEL_RED_SHIFT 0
+#define PIXEL_GREEN_SHIFT 3
+#define PIXEL_BLUE_SHIFT 6
+
+#define PIXEL_RED_MASK (BIT7 | BIT6 | BIT5)
+#define PIXEL_GREEN_MASK (BIT4 | BIT3 | BIT2)
+#define PIXEL_BLUE_MASK (BIT1 | BIT0)
+
+#define PIXEL_TO_COLOR_BYTE(pixel, mask, shift) ((UINT8) ((pixel & mask) << shift))
+#define PIXEL_TO_RED_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_RED_MASK, PIXEL_RED_SHIFT)
+#define PIXEL_TO_GREEN_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_GREEN_MASK, PIXEL_GREEN_SHIFT)
+#define PIXEL_TO_BLUE_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_BLUE_MASK, PIXEL_BLUE_SHIFT)
+
+#define RGB_BYTES_TO_PIXEL(Red, Green, Blue) \
+ (UINT8) ( (((Red) >> PIXEL_RED_SHIFT) & PIXEL_RED_MASK) | \
+ (((Green) >> PIXEL_GREEN_SHIFT) & PIXEL_GREEN_MASK) | \
+ (((Blue) >> PIXEL_BLUE_SHIFT) & PIXEL_BLUE_MASK) )
+
+#define PIXEL24_RED_MASK 0x00ff0000
+#define PIXEL24_GREEN_MASK 0x0000ff00
+#define PIXEL24_BLUE_MASK 0x000000ff
+
+#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff
+
+//
+// QEMU Video Private Data Structure
+//
+#define QEMU_VIDEO_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('Q', 'V', 'I', 'D')
+
+typedef enum {
+ QEMU_VIDEO_CIRRUS_5430 = 1,
+ QEMU_VIDEO_CIRRUS_5446,
+ QEMU_VIDEO_BOCHS,
+ QEMU_VIDEO_BOCHS_MMIO,
+} QEMU_VIDEO_VARIANT;
+
+typedef struct {
+ UINT8 SubClass;
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ QEMU_VIDEO_VARIANT Variant;
+ CHAR16 *Name;
+} QEMU_VIDEO_CARD;
+
+typedef struct {
+ UINT64 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 OriginalPciAttributes;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ //
+ // The next two fields match the client-visible
+ // EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.MaxMode field.
+ //
+ UINTN MaxMode;
+ QEMU_VIDEO_MODE_DATA *ModeData;
+
+ QEMU_VIDEO_VARIANT Variant;
+ FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure;
+ UINTN FrameBufferBltConfigureSize;
+} QEMU_VIDEO_PRIVATE_DATA;
+
+///
+/// Card-specific Video Mode structures
+///
+typedef struct {
+ UINT32 Width;
+ UINT32 Height;
+ UINT32 ColorDepth;
+ UINT8 *CrtcSettings;
+ UINT16 *SeqSettings;
+ UINT8 MiscSetting;
+} QEMU_VIDEO_CIRRUS_MODES;
+
+typedef struct {
+ UINT32 Width;
+ UINT32 Height;
+ UINT32 ColorDepth;
+} QEMU_VIDEO_BOCHS_MODES;
+
+#define QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS(a) \
+ CR(a, QEMU_VIDEO_PRIVATE_DATA, GraphicsOutput, QEMU_VIDEO_PRIVATE_DATA_SIGNATURE)
+
+
+//
+// Global Variables
+//
+extern UINT8 AttributeController[];
+extern UINT8 GraphicsController[];
+extern UINT8 Crtc_640_480_256_60[];
+extern UINT16 Seq_640_480_256_60[];
+extern UINT8 Crtc_800_600_256_60[];
+extern UINT16 Seq_800_600_256_60[];
+extern UINT8 Crtc_1024_768_256_60[];
+extern UINT16 Seq_1024_768_256_60[];
+extern QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[];
+extern QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[];
+extern EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gQemuVideoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gQemuVideoComponentName2;
+extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gQemuVideoDriverSupportedEfiVersion;
+
+//
+// Io Registers defined by VGA
+//
+#define CRTC_ADDRESS_REGISTER 0x3d4
+#define CRTC_DATA_REGISTER 0x3d5
+#define SEQ_ADDRESS_REGISTER 0x3c4
+#define SEQ_DATA_REGISTER 0x3c5
+#define GRAPH_ADDRESS_REGISTER 0x3ce
+#define GRAPH_DATA_REGISTER 0x3cf
+#define ATT_ADDRESS_REGISTER 0x3c0
+#define MISC_OUTPUT_REGISTER 0x3c2
+#define INPUT_STATUS_1_REGISTER 0x3da
+#define DAC_PIXEL_MASK_REGISTER 0x3c6
+#define PALETTE_INDEX_REGISTER 0x3c8
+#define PALETTE_DATA_REGISTER 0x3c9
+
+#define VBE_DISPI_IOPORT_INDEX 0x01CE
+#define VBE_DISPI_IOPORT_DATA 0x01D0
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ID0 0xB0C0
+#define VBE_DISPI_ID1 0xB0C1
+#define VBE_DISPI_ID2 0xB0C2
+#define VBE_DISPI_ID3 0xB0C3
+#define VBE_DISPI_ID4 0xB0C4
+#define VBE_DISPI_ID5 0xB0C5
+
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_GETCAPS 0x02
+#define VBE_DISPI_8BIT_DAC 0x20
+#define VBE_DISPI_LFB_ENABLED 0x40
+#define VBE_DISPI_NOCLEARMEM 0x80
+
+//
+// Graphics Output Hardware abstraction internal worker functions
+//
+EFI_STATUS
+QemuVideoGraphicsOutputConstructor (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+QemuVideoGraphicsOutputDestructor (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ );
+
+
+//
+// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface
+//
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param RemainingDevicePath TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param RemainingDevicePath TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ TODO: Add function description
+
+ @param This TODO: add argument description
+ @param Controller TODO: add argument description
+ @param NumberOfChildren TODO: add argument description
+ @param ChildHandleBuffer TODO: add argument description
+
+ TODO: add return values
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+QemuVideoComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// Local Function Prototypes
+//
+VOID
+InitializeCirrusGraphicsMode (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ QEMU_VIDEO_CIRRUS_MODES *ModeData
+ );
+
+VOID
+InitializeBochsGraphicsMode (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ QEMU_VIDEO_BOCHS_MODES *ModeData
+ );
+
+VOID
+SetPaletteColor (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Index,
+ UINT8 Red,
+ UINT8 Green,
+ UINT8 Blue
+ );
+
+VOID
+SetDefaultPalette (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ );
+
+VOID
+DrawLogo (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN ScreenWidth,
+ UINTN ScreenHeight
+ );
+
+VOID
+outb (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT8 Data
+ );
+
+VOID
+outw (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT16 Data
+ );
+
+UINT8
+inb (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address
+ );
+
+UINT16
+inw (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Address
+ );
+
+VOID
+BochsWrite (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 Reg,
+ UINT16 Data
+ );
+
+UINT16
+BochsRead (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT16 Reg
+ );
+
+VOID
+VgaOutb (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINTN Reg,
+ UINT8 Data
+ );
+
+EFI_STATUS
+QemuVideoCirrusModeSetup (
+ QEMU_VIDEO_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+QemuVideoBochsModeSetup (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ BOOLEAN IsQxl
+ );
+
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ );
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
new file mode 100644
index 0000000000..002cb56826
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/SimicsVideoDxe.inf
@@ -0,0 +1,74 @@
+## @file
+# This driver is a sample implementation of the Graphics Output Protocol for
+# the QEMU (Cirrus Logic 5446) video controller.
+#
+# Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = QemuVideoDxe
+ FILE_GUID = e3752948-b9a1-4770-90c4-df41c38986be
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeQemuVideo
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+# DRIVER_BINDING = gQemuVideoDriverBinding
+# COMPONENT_NAME = gQemuVideoComponentName
+#
+
+[Sources.common]
+ ComponentName.c
+ Driver.c
+ DriverSupportedEfiVersion.c
+ Gop.c
+ Initialize.c
+ Simics.h
+
+[Sources.Ia32, Sources.X64]
+ VbeShim.c
+ VbeShim.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OptionRomPkg/OptionRomPkg.dec
+ OvmfPkg/OvmfPkg.dec
+ SimicsOpenBoardPkg/OpenBoardPkg.dec
+ SimicsIch10Pkg/Ich10Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ FrameBufferBltLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ PcdLib
+ PciLib
+ PrintLib
+ TimerLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ S3BootScriptLib
+
+[Protocols]
+ gEfiDriverSupportedEfiVersionProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL BY_START
+ gEfiDevicePathProtocolGuid # PROTOCOL BY_START
+ gEfiPciIoProtocolGuid # PROTOCOL TO_START
+ gEfiDxeSmmReadyToLockProtocolGuid
+
+[Pcd]
+ gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+ gBoardModuleTokenSpaceGuid.PcdSimicsX58HostBridgePciDevId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
new file mode 100644
index 0000000000..a82077e2d9
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.asm
@@ -0,0 +1,279 @@
+; @file
+; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
+; default VGA driver to switch to 1024x768x32, on the stdvga and QXL video
+; cards of QEMU.
+;
+; Copyright (C) 2014, Red Hat, Inc.
+; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+
+; enable this macro for debug messages
+;%define DEBUG
+
+%macro DebugLog 1
+%ifdef DEBUG
+ push si
+ mov si, %1
+ call PrintStringSi
+ pop si
+%endif
+%endmacro
+
+
+BITS 16
+ORG 0
+
+VbeInfo:
+TIMES 256 nop
+
+VbeModeInfo:
+TIMES 256 nop
+
+
+Handler:
+ cmp ax, 0x4f00
+ je GetInfo
+ cmp ax, 0x4f01
+ je GetModeInfo
+ cmp ax, 0x4f02
+ je SetMode
+ cmp ax, 0x4f03
+ je GetMode
+ cmp ax, 0x4f10
+ je GetPmCapabilities
+ cmp ax, 0x4f15
+ je ReadEdid
+ cmp ah, 0x00
+ je SetModeLegacy
+ DebugLog StrUnkownFunction
+Hang:
+ jmp Hang
+
+
+GetInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetInfo
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, VbeInfo
+ ; source (ds:si) set now
+
+ mov cx, 256
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+GetModeInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetModeInfo
+
+ and cx, ~0x4000 ; clear potentially set LFB bit in mode number
+ cmp cx, 0x00f1
+ je KnownMode1
+ DebugLog StrUnkownMode
+ jmp Hang
+KnownMode1:
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, VbeModeInfo
+ ; source (ds:si) set now
+
+ mov cx, 256
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+%define ATT_ADDRESS_REGISTER 0x03c0
+%define VBE_DISPI_IOPORT_INDEX 0x01ce
+%define VBE_DISPI_IOPORT_DATA 0x01d0
+
+%define VBE_DISPI_INDEX_XRES 0x1
+%define VBE_DISPI_INDEX_YRES 0x2
+%define VBE_DISPI_INDEX_BPP 0x3
+%define VBE_DISPI_INDEX_ENABLE 0x4
+%define VBE_DISPI_INDEX_BANK 0x5
+%define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+%define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+%define VBE_DISPI_INDEX_X_OFFSET 0x8
+%define VBE_DISPI_INDEX_Y_OFFSET 0x9
+
+%define VBE_DISPI_ENABLED 0x01
+%define VBE_DISPI_LFB_ENABLED 0x40
+
+%macro BochsWrite 2
+ push dx
+ push ax
+
+ mov dx, VBE_DISPI_IOPORT_INDEX
+ mov ax, %1
+ out dx, ax
+
+ mov dx, VBE_DISPI_IOPORT_DATA
+ mov ax, %2
+ out dx, ax
+
+ pop ax
+ pop dx
+%endmacro
+
+SetMode:
+ push dx
+ push ax
+
+ DebugLog StrEnterSetMode
+
+ cmp bx, 0x40f1
+ je KnownMode2
+ DebugLog StrUnkownMode
+ jmp Hang
+KnownMode2:
+
+ ; unblank
+ mov dx, ATT_ADDRESS_REGISTER
+ mov al, 0x20
+ out dx, al
+
+ BochsWrite VBE_DISPI_INDEX_ENABLE, 0
+ BochsWrite VBE_DISPI_INDEX_BANK, 0
+ BochsWrite VBE_DISPI_INDEX_X_OFFSET, 0
+ BochsWrite VBE_DISPI_INDEX_Y_OFFSET, 0
+ BochsWrite VBE_DISPI_INDEX_BPP, 32
+ BochsWrite VBE_DISPI_INDEX_XRES, 1024
+ BochsWrite VBE_DISPI_INDEX_VIRT_WIDTH, 1024
+ BochsWrite VBE_DISPI_INDEX_YRES, 768
+ BochsWrite VBE_DISPI_INDEX_VIRT_HEIGHT, 768
+ BochsWrite VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED
+
+ pop ax
+ pop dx
+ jmp Success
+
+
+GetMode:
+ DebugLog StrEnterGetMode
+ mov bx, 0x40f1
+ jmp Success
+
+
+GetPmCapabilities:
+ DebugLog StrGetPmCapabilities
+ jmp Unsupported
+
+
+ReadEdid:
+ DebugLog StrReadEdid
+ jmp Unsupported
+
+
+SetModeLegacy:
+ DebugLog StrEnterSetModeLegacy
+
+ cmp al, 0x03
+ je KnownMode3
+ cmp al, 0x12
+ je KnownMode4
+ DebugLog StrUnkownMode
+ jmp Hang
+KnownMode3:
+ mov al, 0x30
+ jmp SetModeLegacyDone
+KnownMode4:
+ mov al, 0x20
+SetModeLegacyDone:
+ DebugLog StrExitSuccess
+ iret
+
+
+Success:
+ DebugLog StrExitSuccess
+ mov ax, 0x004f
+ iret
+
+
+Unsupported:
+ DebugLog StrExitUnsupported
+ mov ax, 0x014f
+ iret
+
+
+%ifdef DEBUG
+PrintStringSi:
+ pusha
+ push ds ; save original
+ push cs
+ pop ds
+ mov dx, 0x0402
+PrintStringSiLoop:
+ lodsb
+ cmp al, 0
+ je PrintStringSiDone
+ out dx, al
+ jmp PrintStringSiLoop
+PrintStringSiDone:
+ pop ds ; restore original
+ popa
+ ret
+
+
+StrExitSuccess:
+ db 'Exit', 0x0a, 0
+
+StrExitUnsupported:
+ db 'Unsupported', 0x0a, 0
+
+StrUnkownFunction:
+ db 'Unknown Function', 0x0a, 0
+
+StrEnterGetInfo:
+ db 'GetInfo', 0x0a, 0
+
+StrEnterGetModeInfo:
+ db 'GetModeInfo', 0x0a, 0
+
+StrEnterGetMode:
+ db 'GetMode', 0x0a, 0
+
+StrEnterSetMode:
+ db 'SetMode', 0x0a, 0
+
+StrEnterSetModeLegacy:
+ db 'SetModeLegacy', 0x0a, 0
+
+StrUnkownMode:
+ db 'Unkown Mode', 0x0a, 0
+
+StrGetPmCapabilities:
+ db 'GetPmCapabilities', 0x0a, 0
+
+StrReadEdid:
+ db 'ReadEdid', 0x0a, 0
+%endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
new file mode 100644
index 0000000000..cc9b6e14cd
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.h
@@ -0,0 +1,701 @@
+//
+// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
+//
+#ifndef _VBE_SHIM_H_
+#define _VBE_SHIM_H_
+STATIC CONST UINT8 mVbeShim[] = {
+ /* 00000000 nop */ 0x90,
+ /* 00000001 nop */ 0x90,
+ /* 00000002 nop */ 0x90,
+ /* 00000003 nop */ 0x90,
+ /* 00000004 nop */ 0x90,
+ /* 00000005 nop */ 0x90,
+ /* 00000006 nop */ 0x90,
+ /* 00000007 nop */ 0x90,
+ /* 00000008 nop */ 0x90,
+ /* 00000009 nop */ 0x90,
+ /* 0000000A nop */ 0x90,
+ /* 0000000B nop */ 0x90,
+ /* 0000000C nop */ 0x90,
+ /* 0000000D nop */ 0x90,
+ /* 0000000E nop */ 0x90,
+ /* 0000000F nop */ 0x90,
+ /* 00000010 nop */ 0x90,
+ /* 00000011 nop */ 0x90,
+ /* 00000012 nop */ 0x90,
+ /* 00000013 nop */ 0x90,
+ /* 00000014 nop */ 0x90,
+ /* 00000015 nop */ 0x90,
+ /* 00000016 nop */ 0x90,
+ /* 00000017 nop */ 0x90,
+ /* 00000018 nop */ 0x90,
+ /* 00000019 nop */ 0x90,
+ /* 0000001A nop */ 0x90,
+ /* 0000001B nop */ 0x90,
+ /* 0000001C nop */ 0x90,
+ /* 0000001D nop */ 0x90,
+ /* 0000001E nop */ 0x90,
+ /* 0000001F nop */ 0x90,
+ /* 00000020 nop */ 0x90,
+ /* 00000021 nop */ 0x90,
+ /* 00000022 nop */ 0x90,
+ /* 00000023 nop */ 0x90,
+ /* 00000024 nop */ 0x90,
+ /* 00000025 nop */ 0x90,
+ /* 00000026 nop */ 0x90,
+ /* 00000027 nop */ 0x90,
+ /* 00000028 nop */ 0x90,
+ /* 00000029 nop */ 0x90,
+ /* 0000002A nop */ 0x90,
+ /* 0000002B nop */ 0x90,
+ /* 0000002C nop */ 0x90,
+ /* 0000002D nop */ 0x90,
+ /* 0000002E nop */ 0x90,
+ /* 0000002F nop */ 0x90,
+ /* 00000030 nop */ 0x90,
+ /* 00000031 nop */ 0x90,
+ /* 00000032 nop */ 0x90,
+ /* 00000033 nop */ 0x90,
+ /* 00000034 nop */ 0x90,
+ /* 00000035 nop */ 0x90,
+ /* 00000036 nop */ 0x90,
+ /* 00000037 nop */ 0x90,
+ /* 00000038 nop */ 0x90,
+ /* 00000039 nop */ 0x90,
+ /* 0000003A nop */ 0x90,
+ /* 0000003B nop */ 0x90,
+ /* 0000003C nop */ 0x90,
+ /* 0000003D nop */ 0x90,
+ /* 0000003E nop */ 0x90,
+ /* 0000003F nop */ 0x90,
+ /* 00000040 nop */ 0x90,
+ /* 00000041 nop */ 0x90,
+ /* 00000042 nop */ 0x90,
+ /* 00000043 nop */ 0x90,
+ /* 00000044 nop */ 0x90,
+ /* 00000045 nop */ 0x90,
+ /* 00000046 nop */ 0x90,
+ /* 00000047 nop */ 0x90,
+ /* 00000048 nop */ 0x90,
+ /* 00000049 nop */ 0x90,
+ /* 0000004A nop */ 0x90,
+ /* 0000004B nop */ 0x90,
+ /* 0000004C nop */ 0x90,
+ /* 0000004D nop */ 0x90,
+ /* 0000004E nop */ 0x90,
+ /* 0000004F nop */ 0x90,
+ /* 00000050 nop */ 0x90,
+ /* 00000051 nop */ 0x90,
+ /* 00000052 nop */ 0x90,
+ /* 00000053 nop */ 0x90,
+ /* 00000054 nop */ 0x90,
+ /* 00000055 nop */ 0x90,
+ /* 00000056 nop */ 0x90,
+ /* 00000057 nop */ 0x90,
+ /* 00000058 nop */ 0x90,
+ /* 00000059 nop */ 0x90,
+ /* 0000005A nop */ 0x90,
+ /* 0000005B nop */ 0x90,
+ /* 0000005C nop */ 0x90,
+ /* 0000005D nop */ 0x90,
+ /* 0000005E nop */ 0x90,
+ /* 0000005F nop */ 0x90,
+ /* 00000060 nop */ 0x90,
+ /* 00000061 nop */ 0x90,
+ /* 00000062 nop */ 0x90,
+ /* 00000063 nop */ 0x90,
+ /* 00000064 nop */ 0x90,
+ /* 00000065 nop */ 0x90,
+ /* 00000066 nop */ 0x90,
+ /* 00000067 nop */ 0x90,
+ /* 00000068 nop */ 0x90,
+ /* 00000069 nop */ 0x90,
+ /* 0000006A nop */ 0x90,
+ /* 0000006B nop */ 0x90,
+ /* 0000006C nop */ 0x90,
+ /* 0000006D nop */ 0x90,
+ /* 0000006E nop */ 0x90,
+ /* 0000006F nop */ 0x90,
+ /* 00000070 nop */ 0x90,
+ /* 00000071 nop */ 0x90,
+ /* 00000072 nop */ 0x90,
+ /* 00000073 nop */ 0x90,
+ /* 00000074 nop */ 0x90,
+ /* 00000075 nop */ 0x90,
+ /* 00000076 nop */ 0x90,
+ /* 00000077 nop */ 0x90,
+ /* 00000078 nop */ 0x90,
+ /* 00000079 nop */ 0x90,
+ /* 0000007A nop */ 0x90,
+ /* 0000007B nop */ 0x90,
+ /* 0000007C nop */ 0x90,
+ /* 0000007D nop */ 0x90,
+ /* 0000007E nop */ 0x90,
+ /* 0000007F nop */ 0x90,
+ /* 00000080 nop */ 0x90,
+ /* 00000081 nop */ 0x90,
+ /* 00000082 nop */ 0x90,
+ /* 00000083 nop */ 0x90,
+ /* 00000084 nop */ 0x90,
+ /* 00000085 nop */ 0x90,
+ /* 00000086 nop */ 0x90,
+ /* 00000087 nop */ 0x90,
+ /* 00000088 nop */ 0x90,
+ /* 00000089 nop */ 0x90,
+ /* 0000008A nop */ 0x90,
+ /* 0000008B nop */ 0x90,
+ /* 0000008C nop */ 0x90,
+ /* 0000008D nop */ 0x90,
+ /* 0000008E nop */ 0x90,
+ /* 0000008F nop */ 0x90,
+ /* 00000090 nop */ 0x90,
+ /* 00000091 nop */ 0x90,
+ /* 00000092 nop */ 0x90,
+ /* 00000093 nop */ 0x90,
+ /* 00000094 nop */ 0x90,
+ /* 00000095 nop */ 0x90,
+ /* 00000096 nop */ 0x90,
+ /* 00000097 nop */ 0x90,
+ /* 00000098 nop */ 0x90,
+ /* 00000099 nop */ 0x90,
+ /* 0000009A nop */ 0x90,
+ /* 0000009B nop */ 0x90,
+ /* 0000009C nop */ 0x90,
+ /* 0000009D nop */ 0x90,
+ /* 0000009E nop */ 0x90,
+ /* 0000009F nop */ 0x90,
+ /* 000000A0 nop */ 0x90,
+ /* 000000A1 nop */ 0x90,
+ /* 000000A2 nop */ 0x90,
+ /* 000000A3 nop */ 0x90,
+ /* 000000A4 nop */ 0x90,
+ /* 000000A5 nop */ 0x90,
+ /* 000000A6 nop */ 0x90,
+ /* 000000A7 nop */ 0x90,
+ /* 000000A8 nop */ 0x90,
+ /* 000000A9 nop */ 0x90,
+ /* 000000AA nop */ 0x90,
+ /* 000000AB nop */ 0x90,
+ /* 000000AC nop */ 0x90,
+ /* 000000AD nop */ 0x90,
+ /* 000000AE nop */ 0x90,
+ /* 000000AF nop */ 0x90,
+ /* 000000B0 nop */ 0x90,
+ /* 000000B1 nop */ 0x90,
+ /* 000000B2 nop */ 0x90,
+ /* 000000B3 nop */ 0x90,
+ /* 000000B4 nop */ 0x90,
+ /* 000000B5 nop */ 0x90,
+ /* 000000B6 nop */ 0x90,
+ /* 000000B7 nop */ 0x90,
+ /* 000000B8 nop */ 0x90,
+ /* 000000B9 nop */ 0x90,
+ /* 000000BA nop */ 0x90,
+ /* 000000BB nop */ 0x90,
+ /* 000000BC nop */ 0x90,
+ /* 000000BD nop */ 0x90,
+ /* 000000BE nop */ 0x90,
+ /* 000000BF nop */ 0x90,
+ /* 000000C0 nop */ 0x90,
+ /* 000000C1 nop */ 0x90,
+ /* 000000C2 nop */ 0x90,
+ /* 000000C3 nop */ 0x90,
+ /* 000000C4 nop */ 0x90,
+ /* 000000C5 nop */ 0x90,
+ /* 000000C6 nop */ 0x90,
+ /* 000000C7 nop */ 0x90,
+ /* 000000C8 nop */ 0x90,
+ /* 000000C9 nop */ 0x90,
+ /* 000000CA nop */ 0x90,
+ /* 000000CB nop */ 0x90,
+ /* 000000CC nop */ 0x90,
+ /* 000000CD nop */ 0x90,
+ /* 000000CE nop */ 0x90,
+ /* 000000CF nop */ 0x90,
+ /* 000000D0 nop */ 0x90,
+ /* 000000D1 nop */ 0x90,
+ /* 000000D2 nop */ 0x90,
+ /* 000000D3 nop */ 0x90,
+ /* 000000D4 nop */ 0x90,
+ /* 000000D5 nop */ 0x90,
+ /* 000000D6 nop */ 0x90,
+ /* 000000D7 nop */ 0x90,
+ /* 000000D8 nop */ 0x90,
+ /* 000000D9 nop */ 0x90,
+ /* 000000DA nop */ 0x90,
+ /* 000000DB nop */ 0x90,
+ /* 000000DC nop */ 0x90,
+ /* 000000DD nop */ 0x90,
+ /* 000000DE nop */ 0x90,
+ /* 000000DF nop */ 0x90,
+ /* 000000E0 nop */ 0x90,
+ /* 000000E1 nop */ 0x90,
+ /* 000000E2 nop */ 0x90,
+ /* 000000E3 nop */ 0x90,
+ /* 000000E4 nop */ 0x90,
+ /* 000000E5 nop */ 0x90,
+ /* 000000E6 nop */ 0x90,
+ /* 000000E7 nop */ 0x90,
+ /* 000000E8 nop */ 0x90,
+ /* 000000E9 nop */ 0x90,
+ /* 000000EA nop */ 0x90,
+ /* 000000EB nop */ 0x90,
+ /* 000000EC nop */ 0x90,
+ /* 000000ED nop */ 0x90,
+ /* 000000EE nop */ 0x90,
+ /* 000000EF nop */ 0x90,
+ /* 000000F0 nop */ 0x90,
+ /* 000000F1 nop */ 0x90,
+ /* 000000F2 nop */ 0x90,
+ /* 000000F3 nop */ 0x90,
+ /* 000000F4 nop */ 0x90,
+ /* 000000F5 nop */ 0x90,
+ /* 000000F6 nop */ 0x90,
+ /* 000000F7 nop */ 0x90,
+ /* 000000F8 nop */ 0x90,
+ /* 000000F9 nop */ 0x90,
+ /* 000000FA nop */ 0x90,
+ /* 000000FB nop */ 0x90,
+ /* 000000FC nop */ 0x90,
+ /* 000000FD nop */ 0x90,
+ /* 000000FE nop */ 0x90,
+ /* 000000FF nop */ 0x90,
+ /* 00000100 nop */ 0x90,
+ /* 00000101 nop */ 0x90,
+ /* 00000102 nop */ 0x90,
+ /* 00000103 nop */ 0x90,
+ /* 00000104 nop */ 0x90,
+ /* 00000105 nop */ 0x90,
+ /* 00000106 nop */ 0x90,
+ /* 00000107 nop */ 0x90,
+ /* 00000108 nop */ 0x90,
+ /* 00000109 nop */ 0x90,
+ /* 0000010A nop */ 0x90,
+ /* 0000010B nop */ 0x90,
+ /* 0000010C nop */ 0x90,
+ /* 0000010D nop */ 0x90,
+ /* 0000010E nop */ 0x90,
+ /* 0000010F nop */ 0x90,
+ /* 00000110 nop */ 0x90,
+ /* 00000111 nop */ 0x90,
+ /* 00000112 nop */ 0x90,
+ /* 00000113 nop */ 0x90,
+ /* 00000114 nop */ 0x90,
+ /* 00000115 nop */ 0x90,
+ /* 00000116 nop */ 0x90,
+ /* 00000117 nop */ 0x90,
+ /* 00000118 nop */ 0x90,
+ /* 00000119 nop */ 0x90,
+ /* 0000011A nop */ 0x90,
+ /* 0000011B nop */ 0x90,
+ /* 0000011C nop */ 0x90,
+ /* 0000011D nop */ 0x90,
+ /* 0000011E nop */ 0x90,
+ /* 0000011F nop */ 0x90,
+ /* 00000120 nop */ 0x90,
+ /* 00000121 nop */ 0x90,
+ /* 00000122 nop */ 0x90,
+ /* 00000123 nop */ 0x90,
+ /* 00000124 nop */ 0x90,
+ /* 00000125 nop */ 0x90,
+ /* 00000126 nop */ 0x90,
+ /* 00000127 nop */ 0x90,
+ /* 00000128 nop */ 0x90,
+ /* 00000129 nop */ 0x90,
+ /* 0000012A nop */ 0x90,
+ /* 0000012B nop */ 0x90,
+ /* 0000012C nop */ 0x90,
+ /* 0000012D nop */ 0x90,
+ /* 0000012E nop */ 0x90,
+ /* 0000012F nop */ 0x90,
+ /* 00000130 nop */ 0x90,
+ /* 00000131 nop */ 0x90,
+ /* 00000132 nop */ 0x90,
+ /* 00000133 nop */ 0x90,
+ /* 00000134 nop */ 0x90,
+ /* 00000135 nop */ 0x90,
+ /* 00000136 nop */ 0x90,
+ /* 00000137 nop */ 0x90,
+ /* 00000138 nop */ 0x90,
+ /* 00000139 nop */ 0x90,
+ /* 0000013A nop */ 0x90,
+ /* 0000013B nop */ 0x90,
+ /* 0000013C nop */ 0x90,
+ /* 0000013D nop */ 0x90,
+ /* 0000013E nop */ 0x90,
+ /* 0000013F nop */ 0x90,
+ /* 00000140 nop */ 0x90,
+ /* 00000141 nop */ 0x90,
+ /* 00000142 nop */ 0x90,
+ /* 00000143 nop */ 0x90,
+ /* 00000144 nop */ 0x90,
+ /* 00000145 nop */ 0x90,
+ /* 00000146 nop */ 0x90,
+ /* 00000147 nop */ 0x90,
+ /* 00000148 nop */ 0x90,
+ /* 00000149 nop */ 0x90,
+ /* 0000014A nop */ 0x90,
+ /* 0000014B nop */ 0x90,
+ /* 0000014C nop */ 0x90,
+ /* 0000014D nop */ 0x90,
+ /* 0000014E nop */ 0x90,
+ /* 0000014F nop */ 0x90,
+ /* 00000150 nop */ 0x90,
+ /* 00000151 nop */ 0x90,
+ /* 00000152 nop */ 0x90,
+ /* 00000153 nop */ 0x90,
+ /* 00000154 nop */ 0x90,
+ /* 00000155 nop */ 0x90,
+ /* 00000156 nop */ 0x90,
+ /* 00000157 nop */ 0x90,
+ /* 00000158 nop */ 0x90,
+ /* 00000159 nop */ 0x90,
+ /* 0000015A nop */ 0x90,
+ /* 0000015B nop */ 0x90,
+ /* 0000015C nop */ 0x90,
+ /* 0000015D nop */ 0x90,
+ /* 0000015E nop */ 0x90,
+ /* 0000015F nop */ 0x90,
+ /* 00000160 nop */ 0x90,
+ /* 00000161 nop */ 0x90,
+ /* 00000162 nop */ 0x90,
+ /* 00000163 nop */ 0x90,
+ /* 00000164 nop */ 0x90,
+ /* 00000165 nop */ 0x90,
+ /* 00000166 nop */ 0x90,
+ /* 00000167 nop */ 0x90,
+ /* 00000168 nop */ 0x90,
+ /* 00000169 nop */ 0x90,
+ /* 0000016A nop */ 0x90,
+ /* 0000016B nop */ 0x90,
+ /* 0000016C nop */ 0x90,
+ /* 0000016D nop */ 0x90,
+ /* 0000016E nop */ 0x90,
+ /* 0000016F nop */ 0x90,
+ /* 00000170 nop */ 0x90,
+ /* 00000171 nop */ 0x90,
+ /* 00000172 nop */ 0x90,
+ /* 00000173 nop */ 0x90,
+ /* 00000174 nop */ 0x90,
+ /* 00000175 nop */ 0x90,
+ /* 00000176 nop */ 0x90,
+ /* 00000177 nop */ 0x90,
+ /* 00000178 nop */ 0x90,
+ /* 00000179 nop */ 0x90,
+ /* 0000017A nop */ 0x90,
+ /* 0000017B nop */ 0x90,
+ /* 0000017C nop */ 0x90,
+ /* 0000017D nop */ 0x90,
+ /* 0000017E nop */ 0x90,
+ /* 0000017F nop */ 0x90,
+ /* 00000180 nop */ 0x90,
+ /* 00000181 nop */ 0x90,
+ /* 00000182 nop */ 0x90,
+ /* 00000183 nop */ 0x90,
+ /* 00000184 nop */ 0x90,
+ /* 00000185 nop */ 0x90,
+ /* 00000186 nop */ 0x90,
+ /* 00000187 nop */ 0x90,
+ /* 00000188 nop */ 0x90,
+ /* 00000189 nop */ 0x90,
+ /* 0000018A nop */ 0x90,
+ /* 0000018B nop */ 0x90,
+ /* 0000018C nop */ 0x90,
+ /* 0000018D nop */ 0x90,
+ /* 0000018E nop */ 0x90,
+ /* 0000018F nop */ 0x90,
+ /* 00000190 nop */ 0x90,
+ /* 00000191 nop */ 0x90,
+ /* 00000192 nop */ 0x90,
+ /* 00000193 nop */ 0x90,
+ /* 00000194 nop */ 0x90,
+ /* 00000195 nop */ 0x90,
+ /* 00000196 nop */ 0x90,
+ /* 00000197 nop */ 0x90,
+ /* 00000198 nop */ 0x90,
+ /* 00000199 nop */ 0x90,
+ /* 0000019A nop */ 0x90,
+ /* 0000019B nop */ 0x90,
+ /* 0000019C nop */ 0x90,
+ /* 0000019D nop */ 0x90,
+ /* 0000019E nop */ 0x90,
+ /* 0000019F nop */ 0x90,
+ /* 000001A0 nop */ 0x90,
+ /* 000001A1 nop */ 0x90,
+ /* 000001A2 nop */ 0x90,
+ /* 000001A3 nop */ 0x90,
+ /* 000001A4 nop */ 0x90,
+ /* 000001A5 nop */ 0x90,
+ /* 000001A6 nop */ 0x90,
+ /* 000001A7 nop */ 0x90,
+ /* 000001A8 nop */ 0x90,
+ /* 000001A9 nop */ 0x90,
+ /* 000001AA nop */ 0x90,
+ /* 000001AB nop */ 0x90,
+ /* 000001AC nop */ 0x90,
+ /* 000001AD nop */ 0x90,
+ /* 000001AE nop */ 0x90,
+ /* 000001AF nop */ 0x90,
+ /* 000001B0 nop */ 0x90,
+ /* 000001B1 nop */ 0x90,
+ /* 000001B2 nop */ 0x90,
+ /* 000001B3 nop */ 0x90,
+ /* 000001B4 nop */ 0x90,
+ /* 000001B5 nop */ 0x90,
+ /* 000001B6 nop */ 0x90,
+ /* 000001B7 nop */ 0x90,
+ /* 000001B8 nop */ 0x90,
+ /* 000001B9 nop */ 0x90,
+ /* 000001BA nop */ 0x90,
+ /* 000001BB nop */ 0x90,
+ /* 000001BC nop */ 0x90,
+ /* 000001BD nop */ 0x90,
+ /* 000001BE nop */ 0x90,
+ /* 000001BF nop */ 0x90,
+ /* 000001C0 nop */ 0x90,
+ /* 000001C1 nop */ 0x90,
+ /* 000001C2 nop */ 0x90,
+ /* 000001C3 nop */ 0x90,
+ /* 000001C4 nop */ 0x90,
+ /* 000001C5 nop */ 0x90,
+ /* 000001C6 nop */ 0x90,
+ /* 000001C7 nop */ 0x90,
+ /* 000001C8 nop */ 0x90,
+ /* 000001C9 nop */ 0x90,
+ /* 000001CA nop */ 0x90,
+ /* 000001CB nop */ 0x90,
+ /* 000001CC nop */ 0x90,
+ /* 000001CD nop */ 0x90,
+ /* 000001CE nop */ 0x90,
+ /* 000001CF nop */ 0x90,
+ /* 000001D0 nop */ 0x90,
+ /* 000001D1 nop */ 0x90,
+ /* 000001D2 nop */ 0x90,
+ /* 000001D3 nop */ 0x90,
+ /* 000001D4 nop */ 0x90,
+ /* 000001D5 nop */ 0x90,
+ /* 000001D6 nop */ 0x90,
+ /* 000001D7 nop */ 0x90,
+ /* 000001D8 nop */ 0x90,
+ /* 000001D9 nop */ 0x90,
+ /* 000001DA nop */ 0x90,
+ /* 000001DB nop */ 0x90,
+ /* 000001DC nop */ 0x90,
+ /* 000001DD nop */ 0x90,
+ /* 000001DE nop */ 0x90,
+ /* 000001DF nop */ 0x90,
+ /* 000001E0 nop */ 0x90,
+ /* 000001E1 nop */ 0x90,
+ /* 000001E2 nop */ 0x90,
+ /* 000001E3 nop */ 0x90,
+ /* 000001E4 nop */ 0x90,
+ /* 000001E5 nop */ 0x90,
+ /* 000001E6 nop */ 0x90,
+ /* 000001E7 nop */ 0x90,
+ /* 000001E8 nop */ 0x90,
+ /* 000001E9 nop */ 0x90,
+ /* 000001EA nop */ 0x90,
+ /* 000001EB nop */ 0x90,
+ /* 000001EC nop */ 0x90,
+ /* 000001ED nop */ 0x90,
+ /* 000001EE nop */ 0x90,
+ /* 000001EF nop */ 0x90,
+ /* 000001F0 nop */ 0x90,
+ /* 000001F1 nop */ 0x90,
+ /* 000001F2 nop */ 0x90,
+ /* 000001F3 nop */ 0x90,
+ /* 000001F4 nop */ 0x90,
+ /* 000001F5 nop */ 0x90,
+ /* 000001F6 nop */ 0x90,
+ /* 000001F7 nop */ 0x90,
+ /* 000001F8 nop */ 0x90,
+ /* 000001F9 nop */ 0x90,
+ /* 000001FA nop */ 0x90,
+ /* 000001FB nop */ 0x90,
+ /* 000001FC nop */ 0x90,
+ /* 000001FD nop */ 0x90,
+ /* 000001FE nop */ 0x90,
+ /* 000001FF nop */ 0x90,
+ /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
+ /* 00000203 jz 0x22d */ 0x74, 0x28,
+ /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
+ /* 00000208 jz 0x245 */ 0x74, 0x3B,
+ /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
+ /* 0000020D jz 0x269 */ 0x74, 0x5A,
+ /* 0000020F cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
+ /* 00000212 jz word 0x331 */ 0x0F, 0x84, 0x1B, 0x01,
+ /* 00000216 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
+ /* 00000219 jz word 0x336 */ 0x0F, 0x84, 0x19, 0x01,
+ /* 0000021D cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
+ /* 00000220 jz word 0x338 */ 0x0F, 0x84, 0x14, 0x01,
+ /* 00000224 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
+ /* 00000227 jz word 0x33a */ 0x0F, 0x84, 0x0F, 0x01,
+ /* 0000022B jmp short 0x22b */ 0xEB, 0xFE,
+ /* 0000022D push es */ 0x06,
+ /* 0000022E push di */ 0x57,
+ /* 0000022F push ds */ 0x1E,
+ /* 00000230 push si */ 0x56,
+ /* 00000231 push cx */ 0x51,
+ /* 00000232 push cs */ 0x0E,
+ /* 00000233 pop ds */ 0x1F,
+ /* 00000234 mov si,0x0 */ 0xBE, 0x00, 0x00,
+ /* 00000237 mov cx,0x100 */ 0xB9, 0x00, 0x01,
+ /* 0000023A cld */ 0xFC,
+ /* 0000023B rep movsb */ 0xF3, 0xA4,
+ /* 0000023D pop cx */ 0x59,
+ /* 0000023E pop si */ 0x5E,
+ /* 0000023F pop ds */ 0x1F,
+ /* 00000240 pop di */ 0x5F,
+ /* 00000241 pop es */ 0x07,
+ /* 00000242 jmp word 0x34c */ 0xE9, 0x07, 0x01,
+ /* 00000245 push es */ 0x06,
+ /* 00000246 push di */ 0x57,
+ /* 00000247 push ds */ 0x1E,
+ /* 00000248 push si */ 0x56,
+ /* 00000249 push cx */ 0x51,
+ /* 0000024A and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
+ /* 0000024E cmp cx,0xf1 */ 0x81, 0xF9, 0xF1, 0x00,
+ /* 00000252 jz 0x256 */ 0x74, 0x02,
+ /* 00000254 jmp short 0x22b */ 0xEB, 0xD5,
+ /* 00000256 push cs */ 0x0E,
+ /* 00000257 pop ds */ 0x1F,
+ /* 00000258 mov si,0x100 */ 0xBE, 0x00, 0x01,
+ /* 0000025B mov cx,0x100 */ 0xB9, 0x00, 0x01,
+ /* 0000025E cld */ 0xFC,
+ /* 0000025F rep movsb */ 0xF3, 0xA4,
+ /* 00000261 pop cx */ 0x59,
+ /* 00000262 pop si */ 0x5E,
+ /* 00000263 pop ds */ 0x1F,
+ /* 00000264 pop di */ 0x5F,
+ /* 00000265 pop es */ 0x07,
+ /* 00000266 jmp word 0x34c */ 0xE9, 0xE3, 0x00,
+ /* 00000269 push dx */ 0x52,
+ /* 0000026A push ax */ 0x50,
+ /* 0000026B cmp bx,0x40f1 */ 0x81, 0xFB, 0xF1, 0x40,
+ /* 0000026F jz 0x273 */ 0x74, 0x02,
+ /* 00000271 jmp short 0x22b */ 0xEB, 0xB8,
+ /* 00000273 mov dx,0x3c0 */ 0xBA, 0xC0, 0x03,
+ /* 00000276 mov al,0x20 */ 0xB0, 0x20,
+ /* 00000278 out dx,al */ 0xEE,
+ /* 00000279 push dx */ 0x52,
+ /* 0000027A push ax */ 0x50,
+ /* 0000027B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 0000027E mov ax,0x4 */ 0xB8, 0x04, 0x00,
+ /* 00000281 out dx,ax */ 0xEF,
+ /* 00000282 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 00000285 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 00000288 out dx,ax */ 0xEF,
+ /* 00000289 pop ax */ 0x58,
+ /* 0000028A pop dx */ 0x5A,
+ /* 0000028B push dx */ 0x52,
+ /* 0000028C push ax */ 0x50,
+ /* 0000028D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 00000290 mov ax,0x5 */ 0xB8, 0x05, 0x00,
+ /* 00000293 out dx,ax */ 0xEF,
+ /* 00000294 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 00000297 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 0000029A out dx,ax */ 0xEF,
+ /* 0000029B pop ax */ 0x58,
+ /* 0000029C pop dx */ 0x5A,
+ /* 0000029D push dx */ 0x52,
+ /* 0000029E push ax */ 0x50,
+ /* 0000029F mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 000002A2 mov ax,0x8 */ 0xB8, 0x08, 0x00,
+ /* 000002A5 out dx,ax */ 0xEF,
+ /* 000002A6 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 000002A9 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 000002AC out dx,ax */ 0xEF,
+ /* 000002AD pop ax */ 0x58,
+ /* 000002AE pop dx */ 0x5A,
+ /* 000002AF push dx */ 0x52,
+ /* 000002B0 push ax */ 0x50,
+ /* 000002B1 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 000002B4 mov ax,0x9 */ 0xB8, 0x09, 0x00,
+ /* 000002B7 out dx,ax */ 0xEF,
+ /* 000002B8 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 000002BB mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 000002BE out dx,ax */ 0xEF,
+ /* 000002BF pop ax */ 0x58,
+ /* 000002C0 pop dx */ 0x5A,
+ /* 000002C1 push dx */ 0x52,
+ /* 000002C2 push ax */ 0x50,
+ /* 000002C3 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 000002C6 mov ax,0x3 */ 0xB8, 0x03, 0x00,
+ /* 000002C9 out dx,ax */ 0xEF,
+ /* 000002CA mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 000002CD mov ax,0x20 */ 0xB8, 0x20, 0x00,
+ /* 000002D0 out dx,ax */ 0xEF,
+ /* 000002D1 pop ax */ 0x58,
+ /* 000002D2 pop dx */ 0x5A,
+ /* 000002D3 push dx */ 0x52,
+ /* 000002D4 push ax */ 0x50,
+ /* 000002D5 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 000002D8 mov ax,0x1 */ 0xB8, 0x01, 0x00,
+ /* 000002DB out dx,ax */ 0xEF,
+ /* 000002DC mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 000002DF mov ax,0x400 */ 0xB8, 0x00, 0x04,
+ /* 000002E2 out dx,ax */ 0xEF,
+ /* 000002E3 pop ax */ 0x58,
+ /* 000002E4 pop dx */ 0x5A,
+ /* 000002E5 push dx */ 0x52,
+ /* 000002E6 push ax */ 0x50,
+ /* 000002E7 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 000002EA mov ax,0x6 */ 0xB8, 0x06, 0x00,
+ /* 000002ED out dx,ax */ 0xEF,
+ /* 000002EE mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 000002F1 mov ax,0x400 */ 0xB8, 0x00, 0x04,
+ /* 000002F4 out dx,ax */ 0xEF,
+ /* 000002F5 pop ax */ 0x58,
+ /* 000002F6 pop dx */ 0x5A,
+ /* 000002F7 push dx */ 0x52,
+ /* 000002F8 push ax */ 0x50,
+ /* 000002F9 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 000002FC mov ax,0x2 */ 0xB8, 0x02, 0x00,
+ /* 000002FF out dx,ax */ 0xEF,
+ /* 00000300 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 00000303 mov ax,0x300 */ 0xB8, 0x00, 0x03,
+ /* 00000306 out dx,ax */ 0xEF,
+ /* 00000307 pop ax */ 0x58,
+ /* 00000308 pop dx */ 0x5A,
+ /* 00000309 push dx */ 0x52,
+ /* 0000030A push ax */ 0x50,
+ /* 0000030B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 0000030E mov ax,0x7 */ 0xB8, 0x07, 0x00,
+ /* 00000311 out dx,ax */ 0xEF,
+ /* 00000312 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 00000315 mov ax,0x300 */ 0xB8, 0x00, 0x03,
+ /* 00000318 out dx,ax */ 0xEF,
+ /* 00000319 pop ax */ 0x58,
+ /* 0000031A pop dx */ 0x5A,
+ /* 0000031B push dx */ 0x52,
+ /* 0000031C push ax */ 0x50,
+ /* 0000031D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
+ /* 00000320 mov ax,0x4 */ 0xB8, 0x04, 0x00,
+ /* 00000323 out dx,ax */ 0xEF,
+ /* 00000324 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
+ /* 00000327 mov ax,0x41 */ 0xB8, 0x41, 0x00,
+ /* 0000032A out dx,ax */ 0xEF,
+ /* 0000032B pop ax */ 0x58,
+ /* 0000032C pop dx */ 0x5A,
+ /* 0000032D pop ax */ 0x58,
+ /* 0000032E pop dx */ 0x5A,
+ /* 0000032F jmp short 0x34c */ 0xEB, 0x1B,
+ /* 00000331 mov bx,0x40f1 */ 0xBB, 0xF1, 0x40,
+ /* 00000334 jmp short 0x34c */ 0xEB, 0x16,
+ /* 00000336 jmp short 0x350 */ 0xEB, 0x18,
+ /* 00000338 jmp short 0x350 */ 0xEB, 0x16,
+ /* 0000033A cmp al,0x3 */ 0x3C, 0x03,
+ /* 0000033C jz 0x345 */ 0x74, 0x07,
+ /* 0000033E cmp al,0x12 */ 0x3C, 0x12,
+ /* 00000340 jz 0x349 */ 0x74, 0x07,
+ /* 00000342 jmp word 0x22b */ 0xE9, 0xE6, 0xFE,
+ /* 00000345 mov al,0x30 */ 0xB0, 0x30,
+ /* 00000347 jmp short 0x34b */ 0xEB, 0x02,
+ /* 00000349 mov al,0x20 */ 0xB0, 0x20,
+ /* 0000034B iretw */ 0xCF,
+ /* 0000034C mov ax,0x4f */ 0xB8, 0x4F, 0x00,
+ /* 0000034F iretw */ 0xCF,
+ /* 00000350 mov ax,0x14f */ 0xB8, 0x4F, 0x01,
+ /* 00000353 iretw */ 0xCF,
+};
+#endif
diff --git a/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh
new file mode 100644
index 0000000000..7669f8a219
--- /dev/null
+++ b/Platform/Intel/SimicsOpenBoardPkg/SimicsVideoDxe/VbeShim.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+set -e -u
+
+STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
+
+#
+# Install exit handler -- remove temporary files.
+#
+exit_handler()
+{
+ rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
+ "$STEM".bytes
+}
+trap exit_handler EXIT
+
+#
+# Assemble the source file.
+#
+nasm -o "$STEM".bin -- "$STEM".asm
+
+#
+# Disassemble it, in order to get a binary dump associated with the source.
+# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
+#
+ndisasm "$STEM".bin >"$STEM".disasm
+
+#
+# Create three files, each with one column of the disassembly.
+#
+# The first column contains the offsets, and it starts the comment.
+#
+cut -c 1-8 -- "$STEM".disasm \
+| sed -e 's,^, /* ,' >"$STEM".offsets
+
+#
+# The second column contains the assembly-language instructions, and it closes
+# the comment. We first pad it to 30 characters.
+#
+cut -c 29- -- "$STEM".disasm \
+| sed -e 's,$, ,' \
+ -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
+
+#
+# The third column contains the bytes corresponding to the instruction,
+# represented as C integer constants. First strip trailing whitespace from the
+# middle column of the input disassembly, then process pairs of nibbles.
+#
+cut -c 11-28 -- "$STEM".disasm \
+| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' >"$STEM".bytes
+
+#
+# Write the output file, recombining the columns. The output should have CRLF
+# line endings.
+#
+{
+ printf '//\n'
+ printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
+ "$(basename -- "$0")"
+ printf '//\n'
+ printf '#ifndef _VBE_SHIM_H_\n'
+ printf '#define _VBE_SHIM_H_\n'
+ printf 'STATIC CONST UINT8 mVbeShim[] = {\n'
+ paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
+ printf '};\n'
+ printf '#endif\n'
+} \
+| unix2dos >"$STEM".h
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 9+ messages in thread