From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: david.y.wei@intel.com) Received: from mga14.intel.com (mga14.intel.com []) by groups.io with SMTP; Fri, 30 Aug 2019 14:19:23 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2019 14:19:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,447,1559545200"; d="scan'208";a="265437435" Received: from ydwei-desk.amr.corp.intel.com ([10.24.15.168]) by orsmga001.jf.intel.com with ESMTP; 30 Aug 2019 14:19:21 -0700 From: "David Wei" To: devel@edk2.groups.io Cc: Hao Wu , Liming Gao , Ankit Sinha , Agyeman Prince , Kubacki Michael A , Nate DeSimone , Michael D Kinney Subject: [edk2-platforms PATCH v4 3/7] SimicsOpenBoardPkg: Add SimicsOpenBoardPkg and its modules Date: Fri, 30 Aug 2019 14:19:15 -0700 Message-Id: X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: References: MIME-Version: 1.0 In-Reply-To: References: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add modules Include, Library, SimicsDxe, SimicsPei, Policy, SmbiosPlatformDxe and SecCore for Simics QSP platform support Cc: Hao Wu Cc: Liming Gao Cc: Ankit Sinha Cc: Agyeman Prince Cc: Kubacki Michael A Cc: Nate DeSimone Cc: Michael D Kinney Signed-off-by: David Wei --- .../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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + 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.
+ + 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.
+ + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "NvVarsFileLib.h" + +#include +#include +#include + + +/** + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "NvVarsFileLib.h" +#include +#include + +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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PiPei.h" +#include +#include +#include +#include + +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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "BdsPlatform.h" +#include +#include + +#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"" : 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""; + 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.
+ + 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.
+ + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include + +/** + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include + +/** + 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.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Platform.h" +#include "PlatformConfig.h" +#include +// +// 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 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 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 + 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 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#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.
+ + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include + +#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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +// +// The package level header files this module uses +// +#include + +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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.
+ Copyright (c) 2011, Andrei Warkentin + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +// +// The package level header files this module uses +// +#include + +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.
+ + 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.
+ + 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 + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __I440FX_PIIX4_H__ +#define __I440FX_PIIX4_H__ + +#include + +// +// 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.
+ + 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.
+ 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.
+ + 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 + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __SIMICS_PLATFORMS_H__ +#define __SIMICS_PLATFORMS_H__ + +#include +#include +#include +#include + +// +// 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.
+# +# 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.
+ + 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.
+# +# 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.
+; +; 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _LOAD_LINUX_LIB_INCLUDED_ +#define _LOAD_LINUX_LIB_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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.
+; +; 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __NV_VARS_FILE_LIB_INSTANCE__ +#define __NV_VARS_FILE_LIB_INSTANCE__ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/** + 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.
+# +# 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.
+ + 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.
+# +# 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.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_ +#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_ + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +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.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __SERIALIZE_VARIABLES_LIB_INSTANCE__ +#define __SERIALIZE_VARIABLES_LIB_INSTANCE__ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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.
+# +# 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.
+# +# 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.
+# +# 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.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + +#include + + 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.
+# +# 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.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; + +#include + +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.
+ + 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.
+// +// 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PLATFORM_CONFIG_H_ +#define _PLATFORM_CONFIG_H_ + +#include + +// +// 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.
+// +// 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 +#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.
+# +# 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.
+ + 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.
+ + 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.
+# +# 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 + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _SMBIOS_PLATFORM_DXE_H_ +#define _SMBIOS_PLATFORM_DXE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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 +# Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.
+# +# 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