From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.120, mailfrom: nathaniel.l.desimone@intel.com) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by groups.io with SMTP; Thu, 15 Aug 2019 01:34:39 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Aug 2019 01:34:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,388,1559545200"; d="scan'208";a="167687905" Received: from orsmsx109.amr.corp.intel.com ([10.22.240.7]) by orsmga007.jf.intel.com with ESMTP; 15 Aug 2019 01:34:39 -0700 Received: from orsmsx114.amr.corp.intel.com ([169.254.8.96]) by ORSMSX109.amr.corp.intel.com ([169.254.11.170]) with mapi id 14.03.0439.000; Thu, 15 Aug 2019 01:34:38 -0700 From: "Nate DeSimone" To: "Wei, David Y" , "devel@edk2.groups.io" CC: "Wu, Hao A" , "Gao, Liming" , "Sinha, Ankit" , "Agyeman, Prince" , "Kubacki, Michael A" , "Kinney, Michael D" Subject: Re: [edk2-platform patch 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 Thread-Topic: [edk2-platform patch 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX58 Thread-Index: AQHVTwRY7IyJyNu9tUScYU4Sd92qJKb73V2g Date: Thu, 15 Aug 2019 08:34:38 +0000 Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE07398@ORSMSX114.amr.corp.intel.com> References: In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMTgyZGI1YzYtMTI0My00ZmU0LTk5NWUtZWU3MzhiODMxOWUxIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoicWQ3UlwvQ2FCU0dJV09ObEh4THNOU1h6ZXMrckpFQkVOZGQyQmhHUDNTaXRaTXR6RndhOGE3bnZLQWNxaHdZZzIifQ== x-ctpclassification: CTP_NT x-originating-ip: [10.22.254.140] MIME-Version: 1.0 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi David, Here are my comments: 1. All of the copyright years need to be updated to 2019. 2. Please remove " Contributed-under: TianoCore Contribution Agreement 1.0"= from your commit message as it is no longer needed. 3. Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecMain.c - Pl= ease fix all the interspersed trailing white-space. 4. Silicon/Intel/SimicsX58SktPkg/SktPei.dsc - line 2 reads like this "Compo= nent description file for the SkyLake SiPkg PEI drivers.". This is Simics, = not Sky Lake, please update the comment. 5. Silicon/Intel/SimicsX58SktPkg/SktUefiBootInclude.fdf - lines 10 & 11 - p= lease remove the commented out code. Other than that, looks good! Please send an updated patch. Thanks, Nate -----Original Message----- From: Wei, David Y=20 Sent: Friday, August 9, 2019 3:47 PM To: devel@edk2.groups.io Cc: Wu, Hao A ; Gao, Liming ; Sin= ha, Ankit ; Agyeman, Prince ; Kubacki, Michael A ; Desimone, Nathaniel L= ; Kinney, Michael D Subject: [edk2-platform patch 1/7] SimicsX58SktPkg: Add CPU Pkg for SimicsX= 58 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/SecCo= re/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/SecCo= re/Ia32/SecEntry.nasm create mode 100644 Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCo= re/SecMain.inf create mode 100644 Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCo= re/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.i= nf create mode 100644 Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmramInternal.= h diff --git a/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/SecM= ain.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 =3D { + TemporaryRamMigration +}; + +EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] =3D { + { + (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 =3D { + { // 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 decompre= ssed + @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) =3D=3D 0); + + Fv =3D *BootFv; + Distance =3D (UINTN) (*BootFv)->FvLength; + do { + Fv =3D (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE); + Distance +=3D EFI_PAGE_SIZE; + if (Distance > SIZE_32MB) { + return EFI_NOT_FOUND; + } + + if (Fv->Signature !=3D EFI_FVH_SIGNATURE) { + continue; + } + + if ((UINTN) Fv->FvLength > Distance) { + continue; + } + + *BootFv =3D 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 =3D (EFI_PHYSICAL_ADDRESS)(UINTN) Sections; + EndOfSections =3D EndOfSection + SizeOfSections; + for (;;) { + if (EndOfSection =3D=3D EndOfSections) { + break; + } + CurrentAddress =3D (EndOfSection + 3) & ~(3ULL); + if (CurrentAddress >=3D EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + Section =3D (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type)); + + Size =3D SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfSection =3D CurrentAddress + Size; + if (EndOfSection > EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the requested section type + // + if (Section->Type =3D=3D SectionType) { + if (Instance =3D=3D 0) { + *FoundSection =3D Section; + return EFI_SUCCESS; + } else { + Instance--; + } + } + DEBUG ((EFI_D_INFO, "Section->Type (0x%x) !=3D 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 !=3D EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", F= v)); + return EFI_VOLUME_CORRUPTED; + } + + CurrentAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN) Fv; + EndOfFirmwareVolume =3D CurrentAddress + Fv->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile =3D CurrentAddress + Fv->HeaderLength; ; ) { + + CurrentAddress =3D (EndOfFile + 7) & ~(7ULL); + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + File =3D (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + Size =3D *(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 =3D CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the request file type + // + if (File->Type !=3D FileType) { + DEBUG ((EFI_D_INFO, "File->Type (0x%x) !=3D FileType (0x%x)\n", File= ->Type, FileType)); + continue; + } + + Status =3D FindFfsSectionInSections ( + (VOID*) (File + 1), + (UINTN) EndOfFile - (UINTN) (File + 1), + SectionType, + FoundSection + ); + if (!EFI_ERROR (Status) || (Status =3D=3D 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 =3D (EFI_COMMON_SECTION_HEADER*) NULL; + + DEBUG ((EFI_D_INFO, "Find and decompress FV image.\n")); + Status =3D 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 =3D ExtractGuidedSectionGetInfo ( + Section, + &OutputBufferSize, + &ScratchBufferSize, + &SectionAttribute + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n")); + return Status; + } + + OutputBuffer =3D (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdSimicsDxeMemFvBas= e) + SIZE_1MB); + ScratchBuffer =3D ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSiz= e, SIZE_1MB); + =20 + DEBUG ((EFI_D_INFO, "PcdSimicsDxeMemFvBase: 0x%x\n", PcdGet32 (PcdSimics= DxeMemFvBase))); + 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=3D0x%x\n", __FUNCTION__, OutputBuffe= r, + OutputBufferSize, ScratchBuffer, ScratchBufferSize, + PcdGet32 (PcdSimicsDecompressionScratchEnd))); + ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize =3D=3D + PcdGet32 (PcdSimicsDecompressionScratchEnd)); + + Status =3D ExtractGuidedSectionDecode ( + Section, + &OutputBuffer, + ScratchBuffer, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n")); + return Status; + } + + Status =3D 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) =3D=3D + (PcdGet32 (PcdSimicsPeiMemFvSize) + sizeof (*FvSection))); + ASSERT (FvSection->Type =3D=3D EFI_SECTION_FIRMWARE_VOLUME_IMAGE); + + PeiMemFv =3D (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsPei= MemFvBase); + CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdSimicsPeiMemFvS= ize)); + + if (PeiMemFv->Signature !=3D EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signa= ture\n", PeiMemFv)); + CpuDeadLoop (); + return EFI_VOLUME_CORRUPTED; + } + + Status =3D 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 =3D=3D EFI_SECTION_FIRMWARE_VOLUME_IMAGE); + + if (IS_SECTION2 (FvSection)) { + FvSectionSize =3D SECTION2_SIZE (FvSection); + FvHeaderSize =3D sizeof (EFI_COMMON_SECTION_HEADER2); + } else { + FvSectionSize =3D SECTION_SIZE (FvSection); + FvHeaderSize =3D sizeof (EFI_COMMON_SECTION_HEADER); + } + + ASSERT (FvSectionSize =3D=3D (PcdGet32 (PcdSimicsDxeMemFvSize) + FvHeade= rSize)); + + DxeMemFv =3D (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsDxe= MemFvBase); + CopyMem (DxeMemFv, (VOID*) ((UINTN)FvSection + FvHeaderSize), PcdGet32 (= PcdSimicsDxeMemFvSize)); + + if (DxeMemFv->Signature !=3D EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signa= ture\n", DxeMemFv)); + CpuDeadLoop (); + return EFI_VOLUME_CORRUPTED; + } + + *Fv =3D 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 =3D FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_PE32, + &Section + ); + if (EFI_ERROR (Status)) { + Status =3D 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 =3D (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 =3D %x\n", IoBitFieldRead16(ICH10_PMBASE_I= O + 4, 10, 12))); + return (IoBitFieldRead16(ICH10_PMBASE_IO + 4, 10, 12) =3D=3D 0x5); +} + + +STATIC +EFI_STATUS +GetS3ResumePeiFv ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv + ) +{ + *PeiFv =3D (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdSimicsPeiMe= mFvBase); + 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 =3D 0; + + S3Resume =3D IsS3Resume (); + if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) { + // + // A malicious runtime OS may have injected something into our previou= sly + // decoded PEI FV, but we don't care about that unless SMM/SMRAM is re= quired. + // + DEBUG ((EFI_D_INFO, "SEC: S3 resume\n")); + GetS3ResumePeiFv (BootFv); + } else { + // + // We're either not resuming, or resuming "securely" -- we'll decompre= ss + // 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 =3D 0; + + CurrentAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; + EndOfFirmwareVolume =3D CurrentAddress + BootFirmwareVolumePtr->FvLength= ; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile =3D CurrentAddress + BootFirmwareVolumePtr->HeaderLength;= ; ) { + + CurrentAddress =3D (EndOfFile + 7) & 0xfffffffffffffff8ULL; + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + File =3D (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + Size =3D *(UINT32*) File->Size & 0xffffff; + if (Size < sizeof (*File)) { + return EFI_NOT_FOUND; + } + + EndOfFile =3D CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + // + // Look for SEC Core + // + if (File->Type !=3D EFI_FV_FILETYPE_SECURITY_CORE) { + continue; + } + + // + // Loop through the FFS file sections within the FFS file + // + EndOfSection =3D (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1); + for (;;) { + CurrentAddress =3D (EndOfSection + 3) & 0xfffffffffffffffcULL; + Section =3D (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + + Size =3D *(UINT32*) Section->Size & 0xffffff; + if (Size < sizeof (*Section)) { + return EFI_NOT_FOUND; + } + + EndOfSection =3D CurrentAddress + Size; + if (EndOfSection > EndOfFile) { + return EFI_NOT_FOUND; + } + + // + // Look for executable sections + // + if (Section->Type =3D=3D EFI_SECTION_PE32 || Section->Type =3D=3D EF= I_SECTION_TE) { + if (File->Type =3D=3D EFI_FV_FILETYPE_SECURITY_CORE) { + *SecCoreImageBase =3D (PHYSICAL_ADDRESS) (UINTN) (Section + 1); + } + break; + } + } + + // + // SEC Core image found + // + if (*SecCoreImageBase !=3D 0) { + return EFI_SUCCESS; + } + } +} + +/* + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug information. It will report the= m 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 =3D FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase); + ASSERT_EFI_ERROR (Status); + + FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase); + =20 + ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + // + // Report SEC Core debug information when remote debug is enabled + // + ImageContext.ImageAddress =3D SecCoreImageBase; + ImageContext.PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) I= mageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Report PEI Core debug information when remote debug is enabled + // + ImageContext.ImageAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageB= ase; + ImageContext.PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) I= mageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Find PEI Core entry point + // + Status =3D PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase,= (VOID**) PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + *PeiCoreEntryPoint =3D 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; + =20 + // + // 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-ini= t of + // the BaseExtractGuidedSectionLib. Since this is before library contruc= tors + // are called, we must use a loop rather than SetMem. + // + Table =3D (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddr= ess); + for (Index =3D 0; + Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize); + ++Index) { + Table[Index] =3D 0; + } + + ProcessLibraryConstructorList (NULL, NULL); + + DEBUG ((EFI_D_INFO, + "SecCoreStartupWithStack(0x%x, 0x%x)\n", + (UINT32)(UINTN)BootFv, + (UINT32)(UINTN)TopOfCurrentStack + )); + =20 + // + // Initialize IDT + // + IdtTableInStack.PeiService =3D NULL; + for (Index =3D 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { + CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof = (mIdtEntryTemplate)); + } + + IdtDescriptor.Base =3D (UINTN)&IdtTableInStack.IdtTable; + IdtDescriptor.Limit =3D (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 () =3D=3D (UINTN) PcdGet32 (PcdSimicsSecPageTablesBas= e)); +#endif + + // + // |-------------| <-- TopOfCurrentStack + // | Stack | 32k + // |-------------| + // | Heap | 32k + // |-------------| <-- SecCoreData.TemporaryRamBase + // + + ASSERT ((UINTN) (PcdGet32 (PcdSimicsSecPeiTempRamBase) + + PcdGet32 (PcdSimicsSecPeiTempRamSize)) =3D=3D + (UINTN) TopOfCurrentStack); + + // + // Initialize SEC hand-off state + // + SecCoreData.DataSize =3D sizeof(EFI_SEC_PEI_HAND_OFF); + + SecCoreData.TemporaryRamSize =3D (UINTN) PcdGet32 (PcdSimicsSecPei= TempRamSize); + SecCoreData.TemporaryRamBase =3D (VOID*)((UINT8 *)TopOfCurrentStac= k - SecCoreData.TemporaryRamSize); + + SecCoreData.PeiTemporaryRamBase =3D SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize =3D SecCoreData.TemporaryRamSize >> 1= ; + + SecCoreData.StackBase =3D (UINT8 *)SecCoreData.TemporaryRam= Base + SecCoreData.PeiTemporaryRamSize; + SecCoreData.StackSize =3D SecCoreData.TemporaryRamSize >> 1= ; + + SecCoreData.BootFirmwareVolumeBase =3D BootFv; + SecCoreData.BootFirmwareVolumeSize =3D (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 phase= s before memory ready. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStar= tupPhase2); +} + +/** + Caller provided function to be invoked at the end of InitializeDebugAgen= t(). + + 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; + =20 + SecCoreData =3D (EFI_SEC_PEI_HAND_OFF *) Context; + + // + // Find PEI Core entry point. It will report SEC and Pei Core debug info= rmation if remote debug + // is enabled. + // + BootFv =3D (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolume= Base; + FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint); + SecCoreData->BootFirmwareVolumeBase =3D BootFv; + SecCoreData->BootFirmwareVolumeSize =3D (UINTN) BootFv->FvLength; + + // + // Transfer the control to the PEI core + // + (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDi= spatchTable); + =20 + // + // 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 =3D (VOID*)(UINTN)TemporaryMemoryBase; + NewHeap =3D (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1)); + + OldStack =3D (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1)); + NewStack =3D (VOID*)(UINTN)PermanentMemoryBase; + + DebugAgentContext.HeapMigrateOffset =3D (UINTN)NewHeap - (UINTN)OldHeap; + DebugAgentContext.StackMigrateOffset =3D (UINTN)NewStack - (UINTN)OldSta= ck; + + OldStatus =3D SaveAndSetDebugTimerInterrupt (FALSE); + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgent= Context, NULL); + + // + // Migrate Heap + // + CopyMem (NewHeap, OldHeap, CopySize >> 1); + + // + // Migrate Stack + // + CopyMem (NewStack, OldStack, CopySize >> 1); + =20 + // + // Rebase IDT table in permanent memory + // + AsmReadIdtr (&IdtDescriptor); + IdtDescriptor.Base =3D IdtDescriptor.Base - (UINTN)OldStack + (UINTN)New= Stack; + + AsmWriteIdtr (&IdtDescriptor); + + // + // Use SetJump()/LongJump() to switch to a new stack. + //=20 + if (SetJump (&JumpBuffer) =3D=3D 0) { +#if defined (MDE_CPU_IA32) + JumpBuffer.Esp =3D JumpBuffer.Esp + DebugAgentContext.StackMigrateOffs= et; +#endif +#if defined (MDE_CPU_X64) + JumpBuffer.Rsp =3D JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffs= et; +#endif + LongJump (&JumpBuffer, (UINTN)-1); + } + + SaveAndSetDebugTimerInterrupt (OldStatus); + + return EFI_SUCCESS; +} diff --git a/Silicon/Intel/SimicsX58SktPkg/Smm/Access/SmmAccess2Dxe.c b/Sil= icon/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_PROTOCO= L. + + X58 TSEG is expected to have been verified and set up by the SmmAccessPe= i + 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 SM= M. + The function should return EFI_UNSUPPORTED if the hardware does not supp= ort + hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRA= M + 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 closin= g 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 supp= ort + 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 closin= g 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 us= ually + 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 mem= ory + 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 =3D { + &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/Sili= con/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 ex= pose + it via the gEfiAcpiVariableGuid GUID HOB. + + This PEIM runs from RAM, so we can write to variables with static storag= e + 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 SM= M. + The function should return EFI_UNSUPPORTED if the hardware does not supp= ort + hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRA= M + configuration is locked. + + @param PeiServices General purpose services available to eve= ry + 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 lo= cked + 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 >=3D DescIdxCount) { + return EFI_INVALID_PARAMETER; + } + + // + // According to current practice, DescriptorIndex is not considered at a= ll, + // 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 supp= ort + hiding of SMRAM. + + @param PeiServices General purpose services available to e= very + 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 >=3D DescIdxCount) { + return EFI_INVALID_PARAMETER; + } + + // + // According to current practice, DescriptorIndex is not considered at a= ll, + // 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 us= ually + implemented such that it is a write-once operation. + + @param PeiServices General purpose services available to e= very + 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 >=3D DescIdxCount) { + return EFI_INVALID_PARAMETER; + } + + // + // According to current practice, DescriptorIndex is not considered at a= ll, + // 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 ever= y + PEIM. + @param This The pointer to the SmmAccessPpi Interface. + @param SmramMapSize The pointer to the variable containing siz= e 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 buff= er. + @retval EFI_SUCCESS The user provided a sufficiently-sized buf= fer. + +**/ +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 =3D { + &SmmAccessPeiOpen, + &SmmAccessPeiClose, + &SmmAccessPeiLock, + &SmmAccessPeiGetCapabilities +}; + + +STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList[] =3D { + { + 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 =3D CmosRead8 (0x34); + Cmos0x35 =3D 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 =3D PciRead16 (SIMICS_HOSTBRIDGE_DID); + if (HostBridgeDevId !=3D INTEL_ICH10_DEVICE_ID) { + DEBUG ((EFI_D_ERROR, "%a: no SMRAM with host bridge DID=3D0x%04x; only= " + "DID=3D0x%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-enabl= e + // bits are hard-coded as 1 by QEMU. + // + + TopOfLowRam =3D GetSystemMemorySizeBelow4gb (); + ASSERT ((TopOfLowRam & (SIZE_1MB - 1)) =3D=3D 0); + TopOfLowRamMb =3D TopOfLowRam >> 20; + DEBUG((EFI_D_ERROR, "TopOfLowRam =3D0x%x; TopOfLowRamMb =3D0x%x \n", Top= OfLowRam, TopOfLowRamMb)); + + + // + // Set Top of Low Usable DRAM. + // + PciWrite32 (DRAMC_REGISTER_X58(MCH_TOLUD), + TopOfLowRam); + DEBUG((EFI_D_ERROR, "MCH_TOLUD =3D0x%x; \n", PciRead32(DRAMC_REGISTER_X5= 8(MCH_TOLUD)))); + + // + // Set TSEG Memory Base. + // + EsmramcVal =3D (TopOfLowRamMb - FixedPcdGet8(PcdX58TsegMbytes)) << MCH_T= SEGMB_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 &=3D ~(UINT32)MCH_ESMRAMC_TSEG_MASK; + EsmramcVal |=3D FixedPcdGet8 (PcdX58TsegMbytes) =3D=3D 8 ? MCH_ESMRAMC_T= SEG_8MB : + FixedPcdGet8 (PcdX58TsegMbytes) =3D=3D 2 ? MCH_ESMRAMC_TSE= G_2MB : + MCH_ESMRAMC_TSEG_1MB; + EsmramcVal |=3D MCH_ESMRAMC_T_EN; + PciWrite32(DRAMC_REGISTER_X58(MCH_TSEGMB), EsmramcVal); + DEBUG((EFI_D_ERROR, "MCH_TSEGMB =3D0x%x; \n", PciRead32(DRAMC_REGISTER_X= 58(MCH_TSEGMB)))); + DEBUG((EFI_D_ERROR, "MCH_TSEGMB_1 =3D0x%x; MCH_TSEGMB_2 =3D0x%x;\n", ((T= opOfLowRamMb - FixedPcdGet8(PcdX58TsegMbytes)) << MCH_TSEGMB_MB_SHIFT), Esm= ramcVal)); + + // + // Create the GUID HOB and point it to the first SMRAM range. + // + GetStates (&mAccess.LockState, &mAccess.OpenState); + SmramMapSize =3D sizeof SmramMap; + Status =3D SmramAccessGetCapabilities (mAccess.LockState, mAccess.OpenSt= ate, + &SmramMapSize, SmramMap); + ASSERT_EFI_ERROR (Status); + + DEBUG_CODE_BEGIN (); + { + UINTN Count; + UINTN Idx; + + Count =3D SmramMapSize / sizeof SmramMap[0]; + DEBUG ((EFI_D_VERBOSE, "%a: SMRAM map follows, %d entries\n", __FUNCTI= ON__, + (INT32)Count)); + DEBUG ((EFI_D_VERBOSE, "% 20a % 20a % 20a % 20a\n", "PhysicalStart(0x)= ", + "PhysicalSize(0x)", "CpuStart(0x)", "RegionState(0x)")); + for (Idx =3D 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 =3D BuildGuidHob (&gEfiAcpiVariableGuid, + sizeof SmramMap[DescIdxSmmS3ResumeState]); + if (GuidHob =3D=3D 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 ca= n't + // roll back the above BuildGuidHob() allocation, because PEI doesn't su= pport + // 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/Sil= icon/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 ob= ject, + from the D_LCK and T_EN bits. + + PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rel= y on + the LockState and OpenState fields being up-to-date on entry, and they n= eed + to restore the same invariant on exit, if they touch the bits in questio= n. + + @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; T= RUE + iff SMRAM is open. +**/ +VOID +GetStates ( + OUT BOOLEAN *LockState, + OUT BOOLEAN *OpenState +) +{ + UINT8 EsmramcVal; + + EsmramcVal =3D PciRead8(DRAMC_REGISTER_X58(MCH_TSEGMB)); + + *OpenState =3D !(EsmramcVal & MCH_ESMRAMC_T_EN); + *LockState =3D !*OpenState; + + *OpenState =3D gOpenState; + *LockState =3D 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 i= n +// 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 =3D TRUE; + gLockState =3D !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 =3D FALSE; + gLockState =3D !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 =3D FALSE; + gLockState =3D !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 =3D *SmramMapSize; + *SmramMapSize =3D DescIdxCount * sizeof *SmramMap; + if (OriginalSize < *SmramMapSize) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // Read the TSEG Memory Base register. + // + TsegMemoryBaseMb =3D PciRead32(DRAMC_REGISTER_X58(MCH_TSEGMB)); + + TsegMemoryBaseMb =3D 0xDF800000; + + TsegMemoryBase =3D (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) << 20; + + // + // Precompute the region state bits that will be set for all regions. + // + CommonRegionState =3D (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 a= t 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 =3D TsegMemoryBase; + SmramMap[DescIdxSmmS3ResumeState].CpuStart =3D TsegMemoryBase; + SmramMap[DescIdxSmmS3ResumeState].PhysicalSize =3D + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE))); + SmramMap[DescIdxSmmS3ResumeState].RegionState =3D + CommonRegionState | EFI_ALLOCATED; + + // + // Get the TSEG size bits from the ESMRAMC register. + // + TsegSizeBits =3D PciRead8 (DRAMC_REGISTER_X58(MCH_TSEGMB)) & + MCH_ESMRAMC_TSEG_MASK; + + TsegSizeBits =3D MCH_ESMRAMC_TSEG_8MB; + + // + // The second region is the main one, following the first. + // + SmramMap[DescIdxMain].PhysicalStart =3D + SmramMap[DescIdxSmmS3ResumeState].PhysicalStart + + SmramMap[DescIdxSmmS3ResumeState].PhysicalSize; + SmramMap[DescIdxMain].CpuStart =3D SmramMap[DescIdxMain].PhysicalStart; + SmramMap[DescIdxMain].PhysicalSize =3D + (TsegSizeBits =3D=3D MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB : + TsegSizeBits =3D=3D MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB : + SIZE_1MB) - SmramMap[DescIdxSmmS3ResumeState].PhysicalSize; + SmramMap[DescIdxMain].RegionState =3D 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/SecEnt= ry.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 proce= ssor +; @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/SecM= ain.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 =3D 0x00010005 + BASE_NAME =3D SecMain + FILE_GUID =3D e67f156f-54c5-47f3-a35d-07c045881e14 + MODULE_TYPE =3D SEC + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D SecMain + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/X= 64/SecEntry.nasm new file mode 100644 index 0000000000..0eb86ec2ca --- /dev/null +++ b/Silicon/Intel/SimicsX58SktPkg/Override/UefiCpuPkg/SecCore/X64/SecEntr= y.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 proce= ssor +; @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/Simic= sX58SktPkg/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/LzmaCustomDecompre= ssLib.inf + } + UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf + UefiCpuPkg/CpuMpPei/CpuMpPei.inf diff --git a/Silicon/Intel/SimicsX58SktPkg/SktPostMemoryInclude.fdf b/Silic= on/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/Silico= n/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/Inte= l/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 sequ= ence. +# +INF RuleOverride=3DRESET_SECMAIN USE =3D IA32 $(SKT_PKG)/Override/UefiCpu= Pkg/SecCore/SecMain.inf +INF RuleOverride=3DRESET_VECTOR USE =3D 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 =3D=3D 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/S= ilicon/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_PROTOCO= L. +# +# X58 TSEG is expected to have been verified and set up by the SmmAccessPe= i +# driver. +# +# Copyright (C) 2013, 2015, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SmmAccess2Dxe + FILE_GUID =3D AC95AD3D-4366-44BF-9A62-E4B29D7A2206 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x00010400 + ENTRY_POINT =3D SmmAccess2DxeEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/Si= licon/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 ex= pose +# it via the gEfiAcpiVariableGuid GUIDed HOB. +# +# Copyright (C) 2013, 2015, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SmmAccessPei + FILE_GUID =3D 6C0E75B4-B0B9-44D1-8210-3377D7B4E066 + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D SmmAccessPeiEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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/Sil= icon/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 instanc= e 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 dri= vers. +// +typedef enum { + DescIdxSmmS3ResumeState =3D 0, + DescIdxMain =3D 1, + DescIdxCount =3D 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 ob= ject, + from the D_LCK and T_EN bits. + + PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rel= y on + the LockState and OpenState fields being up-to-date on entry, and they n= eed + to restore the same invariant on exit, if they touch the bits in questio= n. + + @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; T= RUE + 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 i= n +// 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 + ); --=20 2.16.2.windows.1