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 mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Fri, 09 Aug 2019 15:46:54 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Aug 2019 15:46:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,367,1559545200"; d="scan'208";a="199536437" Received: from ydwei-desk.amr.corp.intel.com ([10.24.15.168]) by fmsmga004.fm.intel.com with ESMTP; 09 Aug 2019 15:46:54 -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-platform patch 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 Date: Fri, 9 Aug 2019 15:46:47 -0700 Message-Id: X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: References: In-Reply-To: References: Add CPU Pkg for SimicsX58. It is added for simics QSP project support Cc: Hao Wu Cc: Liming Gao Cc: Ankit Sinha Cc: Agyeman Prince Cc: Kubacki Michael A Cc: Nate DeSimone Cc: Michael D Kinney Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: David Wei --- .../Override/UefiCpuPkg/SecCore/SecMain.c | 956 +++++++++++++++++++++ .../SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c | 148 ++++ .../SimicsX58SktPkg/Smm/Access/SmmAccessPei.c | 353 ++++++++ .../SimicsX58SktPkg/Smm/Access/SmramInternal.c | 199 +++++ .../Override/UefiCpuPkg/SecCore/Ia32/SecEntry.nasm | 45 + .../Override/UefiCpuPkg/SecCore/SecMain.inf | 71 ++ .../Override/UefiCpuPkg/SecCore/X64/SecEntry.nasm | 45 + Silicon/Intel/SimicsX58SktPkg/SktPei.dsc | 18 + .../Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf | 9 + .../Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf | 10 + Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf | 17 + .../Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf | 16 + .../SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf | 52 ++ .../SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf | 64 ++ .../SimicsX58SktPkg/Smm/Access/SmramInternal.h | 81 ++ 15 files changed, 2084 insertions(+) create mode 100644 Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.c create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c create mode 100644 Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/Ia32/SecEntry.nasm create mode 100644 Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.inf create mode 100644 Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/X64/SecEntry.nasm create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPei.dsc create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf create mode 100644 Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h diff --git a/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.c b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.c new file mode 100644 index 0000000000..c52d459ef2 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.c @@ -0,0 +1,956 @@ +/** @file + Main SEC phase code. Transitions to PEI. + + Copyright (c) 2008 - 2015, 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_INFO, "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_INFO, "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_INFO, "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_INFO, "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_INFO, "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_INFO, "PcdSimicsDxeMemFvBase: 0x%x\n", PcdGet32 (PcdSimicsDxeMemFvBase))); + DEBUG ((EFI_D_INFO, "OutputBuffer: 0x%x\n", OutputBuffer)); + DEBUG ((EFI_D_INFO, "OutputBufferSize: 0x%x\n", OutputBufferSize)); + DEBUG ((EFI_D_INFO, "ScratchBuffer: 0x%x\n", ScratchBuffer)); + DEBUG ((EFI_D_INFO, "ScratchBufferSize: 0x%x\n", ScratchBufferSize)); + DEBUG ((EFI_D_INFO, "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_ERROR, "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_INFO, "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_INFO, "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_INFO, "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_INFO, "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/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c new file mode 100644 index 0000000000..771fddb487 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c @@ -0,0 +1,148 @@ +/** @file + A DXE_DRIVER providing SMRAM access by producing EFI_SMM_ACCESS2_PROTOCOL. + + X58 TSEG is expected to have been verified and set up by the SmmAccessPei + driver. + + Copyright (C) 2013, 2015, Red Hat, Inc.
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include + +#include "SmramInternal.h" + +/** + Opens the SMRAM area to be accessible by a boot-service driver. + + This function "opens" SMRAM so that it is visible while not inside of SMM. + The function should return EFI_UNSUPPORTED if the hardware does not support + hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM + configuration is locked. + + @param[in] This The EFI_SMM_ACCESS2_PROTOCOL instance. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_UNSUPPORTED The system does not support opening and closing of + SMRAM. + @retval EFI_DEVICE_ERROR SMRAM cannot be opened, perhaps because it is + locked. +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccess2DxeOpen ( + IN EFI_SMM_ACCESS2_PROTOCOL *This + ) +{ + return SmramAccessOpen (&This->LockState, &This->OpenState); +} + +/** + Inhibits access to the SMRAM. + + This function "closes" SMRAM so that it is not visible while outside of SMM. + The function should return EFI_UNSUPPORTED if the hardware does not support + hiding of SMRAM. + + @param[in] This The EFI_SMM_ACCESS2_PROTOCOL instance. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_UNSUPPORTED The system does not support opening and closing of + SMRAM. + @retval EFI_DEVICE_ERROR SMRAM cannot be closed. +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccess2DxeClose ( + IN EFI_SMM_ACCESS2_PROTOCOL *This + ) +{ + return SmramAccessClose (&This->LockState, &This->OpenState); +} + +/** + Inhibits access to the SMRAM. + + This function prohibits access to the SMRAM region. This function is usually + implemented such that it is a write-once operation. + + @param[in] This The EFI_SMM_ACCESS2_PROTOCOL instance. + + @retval EFI_SUCCESS The device was successfully locked. + @retval EFI_UNSUPPORTED The system does not support locking of SMRAM. +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccess2DxeLock ( + IN EFI_SMM_ACCESS2_PROTOCOL *This + ) +{ + return SmramAccessLock (&This->LockState, &This->OpenState); +} + +/** + Queries the memory controller for the possible regions that will support + SMRAM. + + @param[in] This The EFI_SMM_ACCESS2_PROTOCOL instance. + @param[in,out] SmramMapSize A pointer to the size, in bytes, of the + SmramMemoryMap buffer. + @param[in,out] SmramMap A pointer to the buffer in which firmware + places the current memory map. + + @retval EFI_SUCCESS The chipset supported the given resource. + @retval EFI_BUFFER_TOO_SMALL The SmramMap parameter was too small. The + current buffer size needed to hold the memory + map is returned in SmramMapSize. +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccess2DxeGetCapabilities ( + IN CONST EFI_SMM_ACCESS2_PROTOCOL *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +{ + return SmramAccessGetCapabilities (This->LockState, This->OpenState, + SmramMapSize, SmramMap); +} + +// +// LockState and OpenState will be filled in by the entry point. +// +STATIC EFI_SMM_ACCESS2_PROTOCOL mAccess2 = { + &SmmAccess2DxeOpen, + &SmmAccess2DxeClose, + &SmmAccess2DxeLock, + &SmmAccess2DxeGetCapabilities +}; + +// +// Entry point of this driver. +// +EFI_STATUS +EFIAPI +SmmAccess2DxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // This module should only be included if SMRAM support is required. + // + ASSERT (FeaturePcdGet (PcdSmmSmramRequire)); + + GetStates (&mAccess2.LockState, &mAccess2.OpenState); + return gBS->InstallMultipleProtocolInterfaces (&ImageHandle, + &gEfiSmmAccess2ProtocolGuid, &mAccess2, + NULL); +} diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c new file mode 100644 index 0000000000..d07d88142a --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.c @@ -0,0 +1,353 @@ +/** @file + A PEIM with the following responsibilities: + + - verify & configure the X58 TSEG in the entry point, + - provide SMRAM access by producing PEI_SMM_ACCESS_PPI, + - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose + it via the gEfiAcpiVariableGuid GUID HOB. + + This PEIM runs from RAM, so we can write to variables with static storage + duration. + + Copyright (C) 2013, 2015, Red Hat, Inc.
+ Copyright (c) 2010, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "SmramInternal.h" + +// +// PEI_SMM_ACCESS_PPI implementation. +// + +/** + Opens the SMRAM area to be accessible by a PEIM driver. + + This function "opens" SMRAM so that it is visible while not inside of SMM. + The function should return EFI_UNSUPPORTED if the hardware does not support + hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM + configuration is locked. + + @param PeiServices General purpose services available to every + PEIM. + @param This The pointer to the SMM Access Interface. + @param DescriptorIndex The region of SMRAM to Open. + + @retval EFI_SUCCESS The region was successfully opened. + @retval EFI_DEVICE_ERROR The region could not be opened because locked + by chipset. + @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds. + +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccessPeiOpen ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +{ + if (DescriptorIndex >= DescIdxCount) { + return EFI_INVALID_PARAMETER; + } + + // + // According to current practice, DescriptorIndex is not considered at all, + // beyond validating it. + // + return SmramAccessOpen (&This->LockState, &This->OpenState); +} + +/** + Inhibits access to the SMRAM. + + This function "closes" SMRAM so that it is not visible while outside of SMM. + The function should return EFI_UNSUPPORTED if the hardware does not support + hiding of SMRAM. + + @param PeiServices General purpose services available to every + PEIM. + @param This The pointer to the SMM Access Interface. + @param DescriptorIndex The region of SMRAM to Close. + + @retval EFI_SUCCESS The region was successfully closed. + @retval EFI_DEVICE_ERROR The region could not be closed because + locked by chipset. + @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds. + +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccessPeiClose ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +{ + if (DescriptorIndex >= DescIdxCount) { + return EFI_INVALID_PARAMETER; + } + + // + // According to current practice, DescriptorIndex is not considered at all, + // beyond validating it. + // + return SmramAccessClose (&This->LockState, &This->OpenState); +} + +/** + Inhibits access to the SMRAM. + + This function prohibits access to the SMRAM region. This function is usually + implemented such that it is a write-once operation. + + @param PeiServices General purpose services available to every + PEIM. + @param This The pointer to the SMM Access Interface. + @param DescriptorIndex The region of SMRAM to Close. + + @retval EFI_SUCCESS The region was successfully locked. + @retval EFI_DEVICE_ERROR The region could not be locked because at + least one range is still open. + @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds. + +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccessPeiLock ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +{ + if (DescriptorIndex >= DescIdxCount) { + return EFI_INVALID_PARAMETER; + } + + // + // According to current practice, DescriptorIndex is not considered at all, + // beyond validating it. + // + return SmramAccessLock (&This->LockState, &This->OpenState); +} + +/** + Queries the memory controller for the possible regions that will support + SMRAM. + + @param PeiServices General purpose services available to every + PEIM. + @param This The pointer to the SmmAccessPpi Interface. + @param SmramMapSize The pointer to the variable containing size of + the buffer to contain the description + information. + @param SmramMap The buffer containing the data describing the + Smram region descriptors. + + @retval EFI_BUFFER_TOO_SMALL The user did not provide a sufficient buffer. + @retval EFI_SUCCESS The user provided a sufficiently-sized buffer. + +**/ +STATIC +EFI_STATUS +EFIAPI +SmmAccessPeiGetCapabilities ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +{ + return SmramAccessGetCapabilities (This->LockState, This->OpenState, + SmramMapSize, SmramMap); +} + +// +// LockState and OpenState will be filled in by the entry point. +// +STATIC PEI_SMM_ACCESS_PPI mAccess = { + &SmmAccessPeiOpen, + &SmmAccessPeiClose, + &SmmAccessPeiLock, + &SmmAccessPeiGetCapabilities +}; + + +STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiSmmAccessPpiGuid, &mAccess + } +}; + + +// +// Utility functions. +// +STATIC +UINT8 +CmosRead8 ( + IN UINT8 Index + ) +{ + IoWrite8 (0x70, Index); + return IoRead8 (0x71); +} + +STATIC +UINT32 +GetSystemMemorySizeBelow4gb ( + VOID + ) +{ + UINT32 Cmos0x34; + UINT32 Cmos0x35; + + Cmos0x34 = CmosRead8 (0x34); + Cmos0x35 = CmosRead8 (0x35); + + return ((Cmos0x35 << 8 | Cmos0x34) << 16) + SIZE_16MB; +} + + +// +// Entry point of this driver. +// +EFI_STATUS +EFIAPI +SmmAccessPeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINT16 HostBridgeDevId; + UINT32 EsmramcVal; + UINT32 TopOfLowRam, TopOfLowRamMb; + EFI_STATUS Status; + UINTN SmramMapSize; + EFI_SMRAM_DESCRIPTOR SmramMap[DescIdxCount]; + VOID *GuidHob; + + // + // This module should only be included if SMRAM support is required. + // + ASSERT (FeaturePcdGet (PcdSmmSmramRequire)); + + // + // Verify if we're running on a X58 machine type. + // + HostBridgeDevId = PciRead16 (SIMICS_HOSTBRIDGE_DID); + if (HostBridgeDevId != INTEL_ICH10_DEVICE_ID) { + DEBUG ((EFI_D_ERROR, "%a: no SMRAM with host bridge DID=0x%04x; only " + "DID=0x%04x (X58) is supported\n", __FUNCTION__, HostBridgeDevId, + INTEL_ICH10_DEVICE_ID)); + goto WrongConfig; + } + + // + // Confirm if QEMU supports SMRAM. + // + // With no support for it, the ESMRAMC (Extended System Management RAM + // Control) register reads as zero. If there is support, the cache-enable + // bits are hard-coded as 1 by QEMU. + // + + TopOfLowRam = GetSystemMemorySizeBelow4gb (); + ASSERT ((TopOfLowRam & (SIZE_1MB - 1)) == 0); + TopOfLowRamMb = TopOfLowRam >> 20; + DEBUG((EFI_D_ERROR, "TopOfLowRam =0x%x; TopOfLowRamMb =0x%x \n", TopOfLowRam, TopOfLowRamMb)); + + + // + // Set Top of Low Usable DRAM. + // + PciWrite32 (DRAMC_REGISTER_X58(MCH_TOLUD), + TopOfLowRam); + DEBUG((EFI_D_ERROR, "MCH_TOLUD =0x%x; \n", PciRead32(DRAMC_REGISTER_X58(MCH_TOLUD)))); + + // + // Set TSEG Memory Base. + // + EsmramcVal = (TopOfLowRamMb - FixedPcdGet8(PcdX58TsegMbytes)) << MCH_TSEGMB_MB_SHIFT; + // + // Set TSEG size, and disable TSEG visibility outside of SMM. Note that the + // T_EN bit has inverse meaning; when T_EN is set, then TSEG visibility is + // *restricted* to SMM. + // + EsmramcVal &= ~(UINT32)MCH_ESMRAMC_TSEG_MASK; + EsmramcVal |= FixedPcdGet8 (PcdX58TsegMbytes) == 8 ? MCH_ESMRAMC_TSEG_8MB : + FixedPcdGet8 (PcdX58TsegMbytes) == 2 ? MCH_ESMRAMC_TSEG_2MB : + MCH_ESMRAMC_TSEG_1MB; + EsmramcVal |= MCH_ESMRAMC_T_EN; + PciWrite32(DRAMC_REGISTER_X58(MCH_TSEGMB), EsmramcVal); + DEBUG((EFI_D_ERROR, "MCH_TSEGMB =0x%x; \n", PciRead32(DRAMC_REGISTER_X58(MCH_TSEGMB)))); + DEBUG((EFI_D_ERROR, "MCH_TSEGMB_1 =0x%x; MCH_TSEGMB_2 =0x%x;\n", ((TopOfLowRamMb - FixedPcdGet8(PcdX58TsegMbytes)) << MCH_TSEGMB_MB_SHIFT), EsmramcVal)); + + // + // Create the GUID HOB and point it to the first SMRAM range. + // + GetStates (&mAccess.LockState, &mAccess.OpenState); + SmramMapSize = sizeof SmramMap; + Status = SmramAccessGetCapabilities (mAccess.LockState, mAccess.OpenState, + &SmramMapSize, SmramMap); + ASSERT_EFI_ERROR (Status); + + DEBUG_CODE_BEGIN (); + { + UINTN Count; + UINTN Idx; + + Count = SmramMapSize / sizeof SmramMap[0]; + DEBUG ((EFI_D_VERBOSE, "%a: SMRAM map follows, %d entries\n", __FUNCTION__, + (INT32)Count)); + DEBUG ((EFI_D_VERBOSE, "% 20a % 20a % 20a % 20a\n", "PhysicalStart(0x)", + "PhysicalSize(0x)", "CpuStart(0x)", "RegionState(0x)")); + for (Idx = 0; Idx < Count; ++Idx) { + DEBUG ((EFI_D_VERBOSE, "% 20Lx % 20Lx % 20Lx % 20Lx\n", + SmramMap[Idx].PhysicalStart, SmramMap[Idx].PhysicalSize, + SmramMap[Idx].CpuStart, SmramMap[Idx].RegionState)); + } + } + DEBUG_CODE_END (); + + GuidHob = BuildGuidHob (&gEfiAcpiVariableGuid, + sizeof SmramMap[DescIdxSmmS3ResumeState]); + if (GuidHob == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (GuidHob, &SmramMap[DescIdxSmmS3ResumeState], + sizeof SmramMap[DescIdxSmmS3ResumeState]); + + // + // We're done. The next step should succeed, but even if it fails, we can't + // roll back the above BuildGuidHob() allocation, because PEI doesn't support + // releasing memory. + // + return PeiServicesInstallPpi (mPpiList); + +WrongConfig: + // + // We really don't want to continue in this case. + // + ASSERT (FALSE); + CpuDeadLoop (); + return EFI_UNSUPPORTED; +} diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c new file mode 100644 index 0000000000..898fc25084 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.c @@ -0,0 +1,199 @@ +/** @file + Functions and types shared by the SMM accessor PEI and DXE modules. + + Copyright (C) 2015, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include + +#include "SmramInternal.h" + +BOOLEAN gLockState; +BOOLEAN gOpenState; + +/** + Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and + OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object, + from the D_LCK and T_EN bits. + + PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on + the LockState and OpenState fields being up-to-date on entry, and they need + to restore the same invariant on exit, if they touch the bits in question. + + @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is + locked. + @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE + iff SMRAM is open. +**/ +VOID +GetStates ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState +) +{ + UINT8 EsmramcVal; + + EsmramcVal = PciRead8(DRAMC_REGISTER_X58(MCH_TSEGMB)); + + *OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN); + *LockState = !*OpenState; + + *OpenState = gOpenState; + *LockState = gLockState; +} + +// +// The functions below follow the PEI_SMM_ACCESS_PPI and +// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This +// pointers are removed (TSEG doesn't depend on them), and so is the +// DescriptorIndex parameter (TSEG doesn't support range-wise locking). +// +// The LockState and OpenState members that are common to both +// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in +// isolation from the rest of the (non-shared) members. +// + +EFI_STATUS +SmramAccessOpen ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState + ) +{ + + // + // Open TSEG by clearing T_EN. + // + PciAnd8(DRAMC_REGISTER_X58(MCH_TSEGMB), + (UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff)); + + gOpenState = TRUE; + gLockState = !gOpenState; + + GetStates (LockState, OpenState); + if (!*OpenState) { + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +EFI_STATUS +SmramAccessClose ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState + ) +{ + // + // Close TSEG by setting T_EN. + // + PciOr8(DRAMC_REGISTER_X58(MCH_TSEGMB), MCH_ESMRAMC_T_EN); + + gOpenState = FALSE; + gLockState = !gOpenState; + + GetStates (LockState, OpenState); + if (*OpenState) { + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +EFI_STATUS +SmramAccessLock ( + OUT BOOLEAN *LockState, + IN OUT BOOLEAN *OpenState + ) +{ + if (*OpenState) { + return EFI_DEVICE_ERROR; + } + + // + // Close & lock TSEG by setting T_EN and D_LCK. + // + PciOr8 (DRAMC_REGISTER_X58(MCH_TSEGMB), MCH_ESMRAMC_T_EN); + + gOpenState = FALSE; + gLockState = !gOpenState; + + GetStates (LockState, OpenState); + if (*OpenState || !*LockState) { + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +EFI_STATUS +SmramAccessGetCapabilities ( + IN BOOLEAN LockState, + IN BOOLEAN OpenState, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +{ + UINTN OriginalSize; + UINT32 TsegMemoryBaseMb, TsegMemoryBase; + UINT64 CommonRegionState; + UINT8 TsegSizeBits; + + OriginalSize = *SmramMapSize; + *SmramMapSize = DescIdxCount * sizeof *SmramMap; + if (OriginalSize < *SmramMapSize) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // Read the TSEG Memory Base register. + // + TsegMemoryBaseMb = PciRead32(DRAMC_REGISTER_X58(MCH_TSEGMB)); + + TsegMemoryBaseMb = 0xDF800000; + + TsegMemoryBase = (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) << 20; + + // + // Precompute the region state bits that will be set for all regions. + // + CommonRegionState = (OpenState ? EFI_SMRAM_OPEN : EFI_SMRAM_CLOSED) | + (LockState ? EFI_SMRAM_LOCKED : 0) | + EFI_CACHEABLE; + + // + // The first region hosts an SMM_S3_RESUME_STATE object. It is located at the + // start of TSEG. We round up the size to whole pages, and we report it as + // EFI_ALLOCATED, so that the SMM_CORE stays away from it. + // + SmramMap[DescIdxSmmS3ResumeState].PhysicalStart = TsegMemoryBase; + SmramMap[DescIdxSmmS3ResumeState].CpuStart = TsegMemoryBase; + SmramMap[DescIdxSmmS3ResumeState].PhysicalSize = + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE))); + SmramMap[DescIdxSmmS3ResumeState].RegionState = + CommonRegionState | EFI_ALLOCATED; + + // + // Get the TSEG size bits from the ESMRAMC register. + // + TsegSizeBits = PciRead8 (DRAMC_REGISTER_X58(MCH_TSEGMB)) & + MCH_ESMRAMC_TSEG_MASK; + + TsegSizeBits = MCH_ESMRAMC_TSEG_8MB; + + // + // The second region is the main one, following the first. + // + SmramMap[DescIdxMain].PhysicalStart = + SmramMap[DescIdxSmmS3ResumeState].PhysicalStart + + SmramMap[DescIdxSmmS3ResumeState].PhysicalSize; + SmramMap[DescIdxMain].CpuStart = SmramMap[DescIdxMain].PhysicalStart; + SmramMap[DescIdxMain].PhysicalSize = + (TsegSizeBits == MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB : + TsegSizeBits == MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB : + SIZE_1MB) - SmramMap[DescIdxSmmS3ResumeState].PhysicalSize; + SmramMap[DescIdxMain].RegionState = CommonRegionState; + + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/Ia32/SecEntry.nasm b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/Ia32/SecEntry.nasm new file mode 100644 index 0000000000..19ffb6f86d --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/Ia32/SecEntry.nasm @@ -0,0 +1,45 @@ +; @file +; Copyright (c) 2006 - 2013 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/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.inf b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.inf new file mode 100644 index 0000000000..ac993ac1ce --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.inf @@ -0,0 +1,71 @@ +## @file +# SEC Driver +# +# Copyright (c) 2008 - 2018 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 + SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + PeiServicesLib + PcdLib + UefiCpuLib + DebugAgentLib + IoLib + PeCoffLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + ExtractGuidedSectionLib + LocalApicLib + PciCf8Lib + +[Ppis] + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + +[Pcd] + gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvBase + gSimicsX58PkgTokenSpaceGuid.PcdSimicsPeiMemFvSize + gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvBase + gSimicsX58PkgTokenSpaceGuid.PcdSimicsDxeMemFvSize + gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPageTablesBase + gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPeiTempRamBase + gSimicsX58PkgTokenSpaceGuid.PcdSimicsSecPeiTempRamSize + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress + gSimicsX58PkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize + gSimicsX58PkgTokenSpaceGuid.PcdSimicsDecompressionScratchEnd + +[FeaturePcd] + gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire diff --git a/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/X64/SecEntry.nasm b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/X64/SecEntry.nasm new file mode 100644 index 0000000000..0eb86ec2ca --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/X64/SecEntry.nasm @@ -0,0 +1,45 @@ +; @file +; Copyright (c) 2006 - 2013 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/Silicon/Intel/SimicsX58SktPkg/SktPei.dsc b/Silicon/Intel/SimicsX58SktPkg/SktPei.dsc new file mode 100644 index 0000000000..0be8be4966 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/SktPei.dsc @@ -0,0 +1,18 @@ +## @file +# Component description file for the SkyLake SiPkg PEI drivers. +# +# Copyright (c) 2017 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + # + # SEC Phase modules + # + $(SKT_PKG)/Override/UefiCpuPkg/SecCore/SecMain.inf { + + NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf + UefiCpuPkg/CpuMpPei/CpuMpPei.inf diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf new file mode 100644 index 0000000000..78eca21a43 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf @@ -0,0 +1,9 @@ +## @file +# Component description file for the SkyLake SiPkg DXE drivers. +# +# Copyright (c) 2017 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf new file mode 100644 index 0000000000..9f037e99d4 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/SktPreMemoryInclude.fdf @@ -0,0 +1,10 @@ +## @file +# Component description file for the SkyLake SiPkg PEI drivers. +# +# Copyright (c) 2017 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf diff --git a/Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf new file mode 100644 index 0000000000..596d633cd3 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/SktSecInclude.fdf @@ -0,0 +1,17 @@ +## @file +# Component description file for the SkyLake SiPkg PEI drivers. +# +# Copyright (c) 2017 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +# +# SEC Phase modules +# +# The code in this FV handles the initial firmware startup, and +# decompresses the PEI and DXE FVs which handles the rest of the boot sequence. +# +INF RuleOverride=RESET_SECMAIN USE = IA32 $(SKT_PKG)/Override/UefiCpuPkg/SecCore/SecMain.inf +INF RuleOverride=RESET_VECTOR USE = IA32 UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf diff --git a/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf new file mode 100644 index 0000000000..9004b9cb83 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf @@ -0,0 +1,16 @@ +## @file +# Component description file for the SkyLake SiPkg DXE drivers. +# +# Copyright (c) 2017 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +#INF $(SKT_PKG)/Override/IA32FamilyCpuPkg/CpuArchDxe/CpuArchDxe.inf +#INF $(SKT_PKG)/Override/IA32FamilyCpuPkg/CpuMpDxe/CpuMpDxe.inf +!if gMinPlatformPkgTokenSpaceGuid.PcdBootToShellOnly == FALSE + INF $(SKT_PKG)/Smm/Access/SmmAccess2Dxe.inf + INF UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf +!endif +INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf new file mode 100644 index 0000000000..2f630b4b95 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.inf @@ -0,0 +1,52 @@ +## @file +# A DXE_DRIVER providing SMRAM access by producing EFI_SMM_ACCESS2_PROTOCOL. +# +# X58 TSEG is expected to have been verified and set up by the SmmAccessPei +# driver. +# +# Copyright (C) 2013, 2015, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmAccess2Dxe + FILE_GUID = AC95AD3D-4366-44BF-9A62-E4B29D7A2206 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010400 + ENTRY_POINT = SmmAccess2DxeEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmAccess2Dxe.c + SmramInternal.c + SmramInternal.h + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec + +[LibraryClasses] + DebugLib + PcdLib + PciLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiSmmAccess2ProtocolGuid ## PRODUCES + +[FeaturePcd] + gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire + +[Depex] + TRUE diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf new file mode 100644 index 0000000000..1d3b028c85 --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccessPei.inf @@ -0,0 +1,64 @@ +## @file +# A PEIM with the following responsibilities: +# +# - provide SMRAM access by producing PEI_SMM_ACCESS_PPI, +# - verify & configure the X58 TSEG in the entry point, +# - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose +# it via the gEfiAcpiVariableGuid GUIDed HOB. +# +# Copyright (C) 2013, 2015, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmAccessPei + FILE_GUID = 6C0E75B4-B0B9-44D1-8210-3377D7B4E066 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = SmmAccessPeiEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmAccessPei.c + SmramInternal.c + SmramInternal.h + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + SimicsOpenBoardPkg/SimicsOpenBoardPkg.dec + OvmfPkg/OvmfPkg.dec + +[Guids] + gEfiAcpiVariableGuid + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + HobLib + IoLib + PcdLib + PciLib + PeiServicesLib + PeimEntryPoint + +[FeaturePcd] + gSimicsX58PkgTokenSpaceGuid.PcdSmmSmramRequire + +[FixedPcd] + gSimicsX58PkgTokenSpaceGuid.PcdX58TsegMbytes + +[Ppis] + gPeiSmmAccessPpiGuid ## PRODUCES + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h new file mode 100644 index 0000000000..43a79b295f --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.h @@ -0,0 +1,81 @@ +/** @file + Functions and types shared by the SMM accessor PEI and DXE modules. + + Copyright (C) 2015, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +// +// We'll have two SMRAM ranges. +// +// The first is a tiny one that hosts an SMM_S3_RESUME_STATE object, to be +// filled in by the CPU SMM driver during normal boot, for the PEI instance of +// the LockBox library (which will rely on the object during S3 resume). +// +// The other SMRAM range is the main one, for the SMM core and the SMM drivers. +// +typedef enum { + DescIdxSmmS3ResumeState = 0, + DescIdxMain = 1, + DescIdxCount = 2 +} DESCRIPTOR_INDEX; + +/** + Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and + OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object, + from the D_LCK and T_EN bits. + + PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on + the LockState and OpenState fields being up-to-date on entry, and they need + to restore the same invariant on exit, if they touch the bits in question. + + @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is + locked. + @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE + iff SMRAM is open. +**/ +VOID +GetStates ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState + ); + +// +// The functions below follow the PEI_SMM_ACCESS_PPI and +// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This +// pointers are removed (TSEG doesn't depend on them), and so is the +// DescriptorIndex parameter (TSEG doesn't support range-wise locking). +// +// The LockState and OpenState members that are common to both +// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in +// isolation from the rest of the (non-shared) members. +// + +EFI_STATUS +SmramAccessOpen ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState + ); + +EFI_STATUS +SmramAccessClose ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState + ); + +EFI_STATUS +SmramAccessLock ( + OUT BOOLEAN *LockState, + IN OUT BOOLEAN *OpenState + ); + +EFI_STATUS +SmramAccessGetCapabilities ( + IN BOOLEAN LockState, + IN BOOLEAN OpenState, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ); -- 2.16.2.windows.1