diff options
Diffstat (limited to 'IntelFspPkg')
64 files changed, 8155 insertions, 0 deletions
diff --git a/IntelFspPkg/FspDxeIpl/DxeIpl.c b/IntelFspPkg/FspDxeIpl/DxeIpl.c new file mode 100644 index 0000000000..24e6ef75cd --- /dev/null +++ b/IntelFspPkg/FspDxeIpl/DxeIpl.c @@ -0,0 +1,464 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "DxeIpl.h"
+
+
+//
+// Module Globals used in the DXE to PEI hand off
+// These must be module globals, so the stack can be switched
+//
+CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
+ DxeLoadCore
+};
+
+CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
+ CustomGuidedSectionExtract
+};
+
+CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
+ Decompress
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiDxeIplPpiGuid,
+ (VOID *) &mDxeIplPpi
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiDecompressPpiGuid,
+ (VOID *) &mDecompressPpi
+ }
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ NULL
+};
+
+/**
+ Entry point of DXE IPL PEIM.
+
+ This function installs DXE IPL PPI and Decompress PPI. It also reloads
+ itself to memory on non-S3 resume boot path.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
+ @retval Others Some error occurs during the execution of this function.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimInitializeDxeIpl (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID *ExtractHandlerGuidTable;
+ UINTN ExtractHandlerNumber;
+ EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
+
+ //
+ // Get custom extract guided section method guid list
+ //
+ ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
+
+ //
+ // Install custom extraction guid PPI
+ //
+ if (ExtractHandlerNumber > 0) {
+ GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ ASSERT (GuidPpi != NULL);
+ while (ExtractHandlerNumber-- > 0) {
+ GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;
+ GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];
+ Status = PeiServicesInstallPpi (GuidPpi++);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+
+ //
+ // Install DxeIpl and Decompress PPIs.
+ //
+ Status = PeiServicesInstallPpi (mPpiList);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+/**
+ The ExtractSection() function processes the input section and
+ returns a pointer to the section contents. If the section being
+ extracted does not require processing (if the section
+ GuidedSectionHeader.Attributes has the
+ EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
+ OutputBuffer is just updated to point to the start of the
+ section's contents. Otherwise, *Buffer must be allocated
+ from PEI permanent memory.
+
+ @param[in] This Indicates the
+ EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
+ Buffer containing the input GUIDed section to be
+ processed. OutputBuffer OutputBuffer is
+ allocated from PEI permanent memory and contains
+ the new section stream.
+ @param[in] InputSection A pointer to the input buffer, which contains
+ the input section to be processed.
+ @param[out] OutputBuffer A pointer to a caller-allocated buffer, whose
+ size is specified by the contents of OutputSize.
+ @param[out] OutputSize A pointer to a caller-allocated
+ UINTN in which the size of *OutputBuffer
+ allocation is stored. If the function
+ returns anything other than EFI_SUCCESS,
+ the value of OutputSize is undefined.
+ @param[out] AuthenticationStatus A pointer to a caller-allocated
+ UINT32 that indicates the
+ authentication status of the
+ output buffer. If the input
+ section's GuidedSectionHeader.
+ Attributes field has the
+ EFI_GUIDED_SECTION_AUTH_STATUS_VALID
+ bit as clear,
+ AuthenticationStatus must return
+ zero. These bits reflect the
+ status of the extraction
+ operation. If the function
+ returns anything other than
+ EFI_SUCCESS, the value of
+ AuthenticationStatus is
+ undefined.
+
+ @retval EFI_SUCCESS The InputSection was
+ successfully processed and the
+ section contents were returned.
+
+ @retval EFI_OUT_OF_RESOURCES The system has insufficient
+ resources to process the request.
+
+ @retval EFI_INVALID_PARAMETER The GUID in InputSection does
+ not match this instance of the
+ GUIDed Section Extraction PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+CustomGuidedSectionExtract (
+ IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
+ IN CONST VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize,
+ OUT UINT32 *AuthenticationStatus
+)
+{
+ EFI_STATUS Status;
+ UINT8 *ScratchBuffer;
+ UINT32 ScratchBufferSize;
+ UINT32 OutputBufferSize;
+ UINT16 SectionAttribute;
+
+ //
+ // Init local variable
+ //
+ ScratchBuffer = NULL;
+
+ //
+ // Call GetInfo to get the size and attribute of input guided section data.
+ //
+ Status = ExtractGuidedSectionGetInfo (
+ InputSection,
+ &OutputBufferSize,
+ &ScratchBufferSize,
+ &SectionAttribute
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
+ return Status;
+ }
+
+ if (ScratchBufferSize != 0) {
+ //
+ // Allocate scratch buffer
+ //
+ ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ if (ScratchBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
+ //
+ // Allocate output buffer
+ //
+ *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
+ if (*OutputBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
+ //
+ // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
+ // skip EFI section header to make section data at page alignment.
+ //
+ *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
+ }
+
+ Status = ExtractGuidedSectionDecode (
+ InputSection,
+ OutputBuffer,
+ ScratchBuffer,
+ AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Decode failed
+ //
+ DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
+ return Status;
+ }
+
+ *OutputSize = (UINTN) OutputBufferSize;
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Decompresses a section to the output buffer.
+
+ This function looks up the compression type field in the input section and
+ applies the appropriate compression algorithm to compress the section to a
+ callee allocated buffer.
+
+ @param[in] This Points to this instance of the
+ EFI_PEI_DECOMPRESS_PEI PPI.
+ @param[in] CompressionSection Points to the compressed section.
+ @param[out] OutputBuffer Holds the returned pointer to the decompressed
+ sections.
+ @param[out] OutputSize Holds the returned size of the decompress
+ section streams.
+
+ @retval EFI_SUCCESS The section was decompressed successfully.
+ OutputBuffer contains the resulting data and
+ OutputSize contains the resulting size.
+
+**/
+EFI_STATUS
+EFIAPI
+Decompress (
+ IN CONST EFI_PEI_DECOMPRESS_PPI *This,
+ IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *DstBuffer;
+ UINT8 *ScratchBuffer;
+ UINT32 DstBufferSize;
+ UINT32 ScratchBufferSize;
+ VOID *CompressionSource;
+ UINT32 CompressionSourceSize;
+ UINT32 UncompressedLength;
+ UINT8 CompressionType;
+
+ if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IS_SECTION2 (CompressionSection)) {
+ CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
+ CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
+ UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;
+ CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;
+ } else {
+ CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
+ CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
+ UncompressedLength = CompressionSection->UncompressedLength;
+ CompressionType = CompressionSection->CompressionType;
+ }
+
+ //
+ // This is a compression set, expand it
+ //
+ switch (CompressionType) {
+ case EFI_STANDARD_COMPRESSION:
+ if (TRUE) {
+ //
+ // Load EFI standard compression.
+ // For compressed data, decompress them to destination buffer.
+ //
+ Status = UefiDecompressGetInfo (
+ CompressionSource,
+ CompressionSourceSize,
+ &DstBufferSize,
+ &ScratchBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // GetInfo failed
+ //
+ DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Allocate scratch buffer
+ //
+ ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ if (ScratchBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Allocate destination buffer, extra one page for adjustment
+ //
+ DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
+ // to make section data at page alignment.
+ //
+ DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
+ //
+ // Call decompress function
+ //
+ Status = UefiDecompress (
+ CompressionSource,
+ DstBuffer,
+ ScratchBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Decompress failed
+ //
+ DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
+ return EFI_NOT_FOUND;
+ }
+ break;
+ } else {
+ //
+ // PcdDxeIplSupportUefiDecompress is FALSE
+ // Don't support UEFI decompression algorithm.
+ //
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+
+ case EFI_NOT_COMPRESSED:
+ //
+ // Allocate destination buffer
+ //
+ DstBufferSize = UncompressedLength;
+ DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
+ if (DstBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Adjust DstBuffer offset, skip EFI section header
+ // to make section data at page alignment.
+ //
+ DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
+ //
+ // stream is not actually compressed, just encapsulated. So just copy it.
+ //
+ CopyMem (DstBuffer, CompressionSource, DstBufferSize);
+ break;
+
+ default:
+ //
+ // Don't support other unknown compression type.
+ //
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+
+ *OutputSize = DstBufferSize;
+ *OutputBuffer = DstBuffer;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Main entry point to last PEIM.
+
+ This function finds DXE Core in the firmware volume and transfer the control to
+ DXE core.
+
+ @param[in] This Entry point for DXE IPL PPI.
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] HobList Address to the Pei HOB list.
+
+ @return EFI_SUCCESS DXE core was successfully loaded.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeLoadCore (
+ IN CONST EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList));
+
+ //
+ // Give control back to bootloader after FspInit
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n"));
+ FspInitDone ();
+
+ //
+ // Bootloader called FSP again through NotifyPhase
+ //
+ FspWaitForNotify ();
+
+ //
+ // End of PEI phase signal
+ //
+ Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Give control back to the boot loader framework caller
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "============= PEIM FSP is Completed =============\n\n"));
+
+ SetFspApiReturnStatus(EFI_SUCCESS);
+
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT);
+
+ Pei2LoaderSwitchStack();
+
+ //
+ // Should not come here
+ //
+ while (TRUE) {
+ DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n"));
+ SetFspApiReturnStatus(EFI_UNSUPPORTED);
+ Pei2LoaderSwitchStack();
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFspPkg/FspDxeIpl/DxeIpl.h b/IntelFspPkg/FspDxeIpl/DxeIpl.h new file mode 100644 index 0000000000..0aded7271b --- /dev/null +++ b/IntelFspPkg/FspDxeIpl/DxeIpl.h @@ -0,0 +1,192 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PEI_DXEIPL_H__
+#define __PEI_DXEIPL_H__
+
+#include <PiPei.h>
+#include <Ppi/DxeIpl.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/Decompress.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Ppi/GuidedSectionExtraction.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/UefiDecompressLib.h>
+#include <Library/ExtractGuidedSectionLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/FspSwitchStackLib.h>
+#include <Library/FspCommonLib.h>
+#include <Library/FspPlatformLib.h>
+
+/**
+ Main entry point to last PEIM.
+
+ This function finds DXE Core in the firmware volume and transfer the control to
+ DXE core.
+
+ @param[in] This Entry point for DXE IPL PPI.
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] HobList Address to the Pei HOB list.
+
+ @return EFI_SUCCESS DXE core was successfully loaded.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeLoadCore (
+ IN CONST EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ );
+
+
+
+/**
+ Transfers control to DxeCore.
+
+ This function performs a CPU architecture specific operations to execute
+ the entry point of DxeCore with the parameters of HobList.
+ It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.
+
+ @param[in] DxeCoreEntryPoint The entry point of DxeCore.
+ @param[in] HobList The start of HobList passed to DxeCore.
+
+**/
+VOID
+HandOffToDxeCore (
+ IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,
+ IN EFI_PEI_HOB_POINTERS HobList
+ );
+
+
+
+/**
+ Updates the Stack HOB passed to DXE phase.
+
+ This function traverses the whole HOB list and update the stack HOB to
+ reflect the real stack that is used by DXE core.
+
+ @param[in] BaseAddress The lower address of stack used by DxeCore.
+ @param[in] Length The length of stack used by DxeCore.
+
+**/
+VOID
+UpdateStackHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ The ExtractSection() function processes the input section and
+ returns a pointer to the section contents. If the section being
+ extracted does not require processing (if the section
+ GuidedSectionHeader.Attributes has the
+ EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
+ OutputBuffer is just updated to point to the start of the
+ section's contents. Otherwise, *Buffer must be allocated
+ from PEI permanent memory.
+
+ @param[in] This Indicates the
+ EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
+ Buffer containing the input GUIDed section to be
+ processed. OutputBuffer OutputBuffer is
+ allocated from PEI permanent memory and contains
+ the new section stream.
+ @param[in] InputSection A pointer to the input buffer, which contains
+ the input section to be processed.
+ @param[out] OutputBuffer A pointer to a caller-allocated buffer, whose
+ size is specified by the contents of OutputSize.
+ @param[out] OutputSize A pointer to a caller-allocated
+ UINTN in which the size of *OutputBuffer
+ allocation is stored. If the function
+ returns anything other than EFI_SUCCESS,
+ the value of OutputSize is undefined.
+ @param[out] AuthenticationStatus A pointer to a caller-allocated
+ UINT32 that indicates the
+ authentication status of the
+ output buffer. If the input
+ section's GuidedSectionHeader.
+ Attributes field has the
+ EFI_GUIDED_SECTION_AUTH_STATUS_VALID
+ bit as clear,
+ AuthenticationStatus must return
+ zero. These bits reflect the
+ status of the extraction
+ operation. If the function
+ returns anything other than
+ EFI_SUCCESS, the value of
+ AuthenticationStatus is
+ undefined.
+
+ @retval EFI_SUCCESS The InputSection was
+ successfully processed and the
+ section contents were returned.
+
+ @retval EFI_OUT_OF_RESOURCES The system has insufficient
+ resources to process the request.
+
+ @retval EFI_INVALID_PARAMETER The GUID in InputSection does
+ not match this instance of the
+ GUIDed Section Extraction PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+CustomGuidedSectionExtract (
+ IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
+ IN CONST VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+/**
+ Decompresses a section to the output buffer.
+
+ This function looks up the compression type field in the input section and
+ applies the appropriate compression algorithm to compress the section to a
+ callee allocated buffer.
+
+ @param[in] This Points to this instance of the
+ EFI_PEI_DECOMPRESS_PEI PPI.
+ @param[in] CompressionSection Points to the compressed section.
+ @param[out] OutputBuffer Holds the returned pointer to the decompressed
+ sections.
+ @param[out] OutputSize Holds the returned size of the decompress
+ section streams.
+
+ @retval EFI_SUCCESS The section was decompressed successfully.
+ OutputBuffer contains the resulting data and
+ OutputSize contains the resulting size.
+
+**/
+EFI_STATUS
+EFIAPI
+Decompress (
+ IN CONST EFI_PEI_DECOMPRESS_PPI *This,
+ IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize
+ );
+
+#endif
diff --git a/IntelFspPkg/FspDxeIpl/FspDxeIpl.inf b/IntelFspPkg/FspDxeIpl/FspDxeIpl.inf new file mode 100644 index 0000000000..49317af8e2 --- /dev/null +++ b/IntelFspPkg/FspDxeIpl/FspDxeIpl.inf @@ -0,0 +1,70 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspDxeIpl
+ FILE_GUID = 86D70125-BAA3-4296-A62F-602BEBBB9081
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PeimInitializeDxeIpl
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ DxeIpl.h
+ DxeIpl.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ ExtractGuidedSectionLib
+ UefiDecompressLib
+ ReportStatusCodeLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ FspSwitchStackLib
+ UefiDecompressLib
+ FspCommonLib
+ FspPlatformLib
+
+[Ppis]
+ gEfiDxeIplPpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_PRODUCES(Not produced on S3 boot path)
+ gEfiPeiDecompressPpiGuid
+
+[Protocols]
+ gEfiPciEnumerationCompleteProtocolGuid # ALWAYS_PRODUCED
+
+[Guids]
+ gEfiEventReadyToBootGuid # ALWAYS_PRODUCED
+
+[FixedPcd]
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiLoadFilePpiGuid
diff --git a/IntelFspPkg/FspSecCore/FspSecCore.inf b/IntelFspPkg/FspSecCore/FspSecCore.inf new file mode 100644 index 0000000000..d3ec2fc64f --- /dev/null +++ b/IntelFspPkg/FspSecCore/FspSecCore.inf @@ -0,0 +1,76 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspSecCore
+ FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ SecMain.c
+ SecMain.h
+ SecFsp.c
+ SecFsp.h
+
+[Sources.IA32]
+ Ia32/ResetVec.asm16 | MSFT
+ Ia32/Stack.asm | MSFT
+ Ia32/InitializeFpu.asm | MSFT
+ Ia32/FspApiEntry.asm | MSFT
+
+ Ia32/Stacks.s | GCC
+ Ia32/InitializeFpu.s | GCC
+ Ia32/FspApiEntry.s | GCC
+
+[Binaries.Ia32]
+ RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Binaries.X64]
+ RAW|Vtf0/Bin/ResetVec.x64.raw |GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ PciCf8Lib
+ SerialPortLib
+ FspSwitchStackLib
+ FspCommonLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gIntelFspPkgTokenSpaceGuid.PcdGlobalDataPointerAddress
+ gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamBase
+ gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamSize
+ gIntelFspPkgTokenSpaceGuid.PcdFspTemporaryRamSize
+
+[FixedPcd]
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+
diff --git a/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm new file mode 100644 index 0000000000..8ad9744ab4 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm @@ -0,0 +1,552 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+; Provide FSP API entry points.
+;
+;------------------------------------------------------------------------------
+
+ .586p
+ .model flat,C
+ .code
+ .xmm
+
+INCLUDE SaveRestoreSse.inc
+INCLUDE UcodeLoad.inc
+
+;
+; Following are fixed PCDs
+;
+EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
+EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
+EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
+
+;
+; Following functions will be provided in C
+;
+EXTERN FspImageSizeOffset:DWORD
+EXTERN SecStartup:PROC
+EXTERN FspApiCallingCheck:PROC
+
+;
+; Following functions will be provided in PlatformSecLib
+;
+EXTERN GetFspBaseAddress:PROC
+EXTERN GetBootFirmwareVolumeOffset:PROC
+EXTERN PlatformTempRamInit:PROC
+EXTERN Pei2LoaderSwitchStack:PROC
+EXTERN FspSelfCheck(FspSelfCheckDflt):PROC
+EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC
+EXTERN LoadUcode(LoadUcodeDflt):PROC
+
+;
+; Define the data length that we saved on the stack top
+;
+DATA_LEN_OF_PER0 EQU 18h
+DATA_LEN_OF_MCUD EQU 18h
+DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
+
+;------------------------------------------------------------------------------
+FspSelfCheckDflt PROC NEAR PUBLIC
+ ; Inputs:
+ ; eax -> Return address
+ ; Outputs:
+ ; eax -> 0 - Successful, Non-zero - Failed.
+ ; Register Usage:
+ ; eax is cleared and ebp is used for return address.
+ ; All others reserved.
+
+ ; Save return address to EBP
+ mov ebp, eax
+
+ xor eax, eax
+exit:
+ jmp ebp
+FspSelfCheckDflt ENDP
+
+;------------------------------------------------------------------------------
+PlatformBasicInitDflt PROC NEAR PUBLIC
+ ; Inputs:
+ ; eax -> Return address
+ ; Outputs:
+ ; eax -> 0 - Successful, Non-zero - Failed.
+ ; Register Usage:
+ ; eax is cleared and ebp is used for return address.
+ ; All others reserved.
+
+ ; Save return address to EBP
+ mov ebp, eax
+
+ xor eax, eax
+exit:
+ jmp ebp
+PlatformBasicInitDflt ENDP
+
+;------------------------------------------------------------------------------
+LoadUcodeDflt PROC NEAR PUBLIC
+ ; Inputs:
+ ; esp -> LOAD_UCODE_PARAMS pointer
+ ; Register Usage:
+ ; esp Preserved
+ ; All others destroyed
+ ; Assumptions:
+ ; No memory available, stack is hard-coded and used for return address
+ ; Executed by SBSP and NBSP
+ ; Beginning of microcode update region starts on paragraph boundary
+
+ ;
+ ;
+ ; Save return address to EBP
+ mov ebp, eax
+
+ cmp esp, 0
+ jz paramerror
+ mov eax, dword ptr [esp] ; Parameter pointer
+ cmp eax, 0
+ jz paramerror
+ mov esp, eax
+ mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
+ cmp esi, 0
+ jnz check_main_header
+
+paramerror:
+ mov eax, 080000002h
+ jmp exit
+
+ mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
+
+check_main_header:
+ ; Get processor signature and platform ID from the installed processor
+ ; and save into registers for later use
+ ; ebx = processor signature
+ ; edx = platform ID
+ mov eax, 1
+ cpuid
+ mov ebx, eax
+ mov ecx, MSR_IA32_PLATFORM_ID
+ rdmsr
+ mov ecx, edx
+ shr ecx, 50-32
+ and ecx, 7h
+ mov edx, 1
+ shl edx, cl
+
+ ; Current register usage
+ ; esp -> stack with paramters
+ ; esi -> microcode update to check
+ ; ebx = processor signature
+ ; edx = platform ID
+
+ ; Check for valid microcode header
+ ; Minimal test checking for header version and loader version as 1
+ mov eax, dword ptr 1
+ cmp [esi].ucode_hdr.version, eax
+ jne advance_fixed_size
+ cmp [esi].ucode_hdr.loader, eax
+ jne advance_fixed_size
+
+ ; Check if signature and plaform ID match
+ cmp ebx, [esi].ucode_hdr.processor
+ jne @f
+ test edx, [esi].ucode_hdr.flags
+ jnz load_check ; Jif signature and platform ID match
+
+@@:
+ ; Check if extended header exists
+ ; First check if total_size and data_size are valid
+ xor eax, eax
+ cmp [esi].ucode_hdr.total_size, eax
+ je next_microcode
+ cmp [esi].ucode_hdr.data_size, eax
+ je next_microcode
+
+ ; Then verify total size - sizeof header > data size
+ mov ecx, [esi].ucode_hdr.total_size
+ sub ecx, sizeof ucode_hdr
+ cmp ecx, [esi].ucode_hdr.data_size
+ jng next_microcode ; Jif extended header does not exist
+
+ ; Set edi -> extended header
+ mov edi, esi
+ add edi, sizeof ucode_hdr
+ add edi, [esi].ucode_hdr.data_size
+
+ ; Get count of extended structures
+ mov ecx, [edi].ext_sig_hdr.count
+
+ ; Move pointer to first signature structure
+ add edi, sizeof ext_sig_hdr
+
+check_ext_sig:
+ ; Check if extended signature and platform ID match
+ cmp [edi].ext_sig.processor, ebx
+ jne @f
+ test [edi].ext_sig.flags, edx
+ jnz load_check ; Jif signature and platform ID match
+@@:
+ ; Check if any more extended signatures exist
+ add edi, sizeof ext_sig
+ loop check_ext_sig
+
+next_microcode:
+ ; Advance just after end of this microcode
+ xor eax, eax
+ cmp [esi].ucode_hdr.total_size, eax
+ je @f
+ add esi, [esi].ucode_hdr.total_size
+ jmp check_address
+@@:
+ add esi, dword ptr 2048
+ jmp check_address
+
+advance_fixed_size:
+ ; Advance by 4X dwords
+ add esi, dword ptr 1024
+
+check_address:
+ ; Is valid Microcode start point ?
+ cmp dword ptr [esi], 0ffffffffh
+ jz done
+
+ ; Address >= microcode region address + microcode region size?
+ mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
+ add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size
+ cmp esi, eax
+ jae done ;Jif address is outside of ucode region
+ jmp check_main_header
+
+load_check:
+ ; Get the revision of the current microcode update loaded
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ xor eax, eax ; Clear EAX
+ xor edx, edx ; Clear EDX
+ wrmsr ; Load 0 to MSR at 8Bh
+
+ mov eax, 1
+ cpuid
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ rdmsr ; Get current microcode signature
+
+ ; Verify this microcode update is not already loaded
+ cmp [esi].ucode_hdr.revision, edx
+ je continue
+
+load_microcode:
+ ; EAX contains the linear address of the start of the Update Data
+ ; EDX contains zero
+ ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
+ ; Start microcode load with wrmsr
+ mov eax, esi
+ add eax, sizeof ucode_hdr
+ xor edx, edx
+ mov ecx, MSR_IA32_BIOS_UPDT_TRIG
+ wrmsr
+ mov eax, 1
+ cpuid
+
+continue:
+ jmp next_microcode
+
+done:
+ mov eax, 1
+ cpuid
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ rdmsr ; Get current microcode signature
+ xor eax, eax
+ cmp edx, 0
+ jnz exit
+ mov eax, 08000000Eh
+
+exit:
+ jmp ebp
+
+LoadUcodeDflt ENDP
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; This FSP API will load the microcode update, enable code caching for the
+; region specified by the boot loader and also setup a temporary stack to be
+; used till main memory is initialized.
+;
+;----------------------------------------------------------------------------
+TempRamInitApi PROC NEAR PUBLIC
+ ;
+ ; Ensure SSE is enabled
+ ;
+ ENABLE_SSE
+
+ ;
+ ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
+ ;
+ SAVE_REGS
+
+ ;
+ ; Save timestamp into XMM4 & XMM5
+ ;
+ rdtsc
+ SAVE_EAX
+ SAVE_EDX
+
+ ;
+ ; Check Parameter
+ ;
+ mov eax, dword ptr [esp + 4]
+ cmp eax, 0
+ mov eax, 80000002h
+ jz NemInitExit
+
+ ;
+ ; CPUID/DeviceID check
+ ;
+ mov eax, @F
+ jmp FspSelfCheck ; Note: ESP can not be changed.
+@@:
+ cmp eax, 0
+ jnz NemInitExit
+
+ ;
+ ; Platform Basic Init.
+ ;
+ mov eax, @F
+ jmp PlatformBasicInit
+@@:
+ cmp eax, 0
+ jnz NemInitExit
+
+ ;
+ ; Load microcode
+ ;
+ mov eax, @F
+ add esp, 4
+ jmp LoadUcode
+@@:
+ LOAD_ESP
+ cmp eax, 0
+ jnz NemInitExit
+
+ ;
+ ; Call platform NEM init
+ ;
+ mov eax, @F
+ add esp, 4
+ jmp PlatformTempRamInit
+@@:
+ LOAD_ESP
+ cmp eax, 0
+ jnz NemInitExit
+
+ ;
+ ; Save parameter pointer in edx
+ ;
+ mov edx, dword ptr [esp + 4]
+
+ ;
+ ; Enable FSP STACK
+ ;
+ mov esp, PcdGet32(PcdTemporaryRamBase)
+ add esp, PcdGet32(PcdTemporaryRamSize)
+
+ push DATA_LEN_OF_MCUD ; Size of the data region
+ push 4455434Dh ; Signature of the data region 'MCUD'
+ push dword ptr [edx + 4] ; Microcode size
+ push dword ptr [edx + 0] ; Microcode base
+ push dword ptr [edx + 12] ; Code size
+ push dword ptr [edx + 8] ; Code base
+
+ ;
+ ; Save API entry/exit timestamp into stack
+ ;
+ push DATA_LEN_OF_PER0 ; Size of the data region
+ push 30524550h ; Signature of the data region 'PER0'
+ rdtsc
+ push edx
+ push eax
+ LOAD_EAX
+ LOAD_EDX
+ push edx
+ push eax
+
+ ;
+ ; Terminator for the data on stack
+ ;
+ push 0
+
+ ;
+ ; Set ECX/EDX to the bootloader temporary memory range
+ ;
+ mov ecx, PcdGet32(PcdTemporaryRamBase)
+ mov edx, ecx
+ add edx, PcdGet32(PcdTemporaryRamSize)
+ sub edx, PcdGet32(PcdFspTemporaryRamSize)
+
+ xor eax, eax
+
+NemInitExit:
+ ;
+ ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
+ ;
+ LOAD_REGS
+ ret
+TempRamInitApi ENDP
+
+;----------------------------------------------------------------------------
+; FspInit API
+;
+; This FSP API will perform the processor and chipset initialization.
+; This API will not return. Instead, it transfers the control to the
+; ContinuationFunc provided in the parameter.
+;
+;----------------------------------------------------------------------------
+FspInitApi PROC NEAR PUBLIC
+ ;
+ ; Stack must be ready
+ ;
+ push 087654321h
+ pop eax
+ cmp eax, 087654321h
+ jz @F
+ mov eax, 080000003h
+ jmp exit
+
+@@:
+ ;
+ ; Additional check
+ ;
+ pushad
+ push 1
+ call FspApiCallingCheck
+ add esp, 4
+ mov dword ptr [esp + 4 * 7], eax
+ popad
+ cmp eax, 0
+ jz @F
+ jmp exit
+
+@@:
+ ;
+ ; Store the address in FSP which will return control to the BL
+ ;
+ push offset exit
+
+ ;
+ ; Create a Task Frame in the stack for the Boot Loader
+ ;
+ pushfd ; 2 pushf for 4 byte alignment
+ cli
+ pushad
+
+ ; Reserve 8 bytes for IDT save/restore
+ sub esp, 8
+ sidt fword ptr [esp]
+
+ ;
+ ; Setup new FSP stack
+ ;
+ mov eax, esp
+ mov esp, PcdGet32(PcdTemporaryRamBase)
+ add esp, PcdGet32(PcdTemporaryRamSize)
+ sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
+
+ ;
+ ; Save the bootloader's stack pointer
+ ;
+ push eax
+
+ ;
+ ; Pass entry point of the PEI core
+ ;
+ call GetFspBaseAddress
+ mov edi, FspImageSizeOffset
+ mov edi, DWORD PTR [eax + edi]
+ add edi, eax
+ sub edi, 20h
+ add eax, DWORD PTR [edi]
+ push eax
+
+ ;
+ ; Pass BFV into the PEI Core
+ ; It uses relative address to calucate the actual boot FV base
+ ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
+ ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
+ ; they are different. The code below can handle both cases.
+ ;
+ call GetFspBaseAddress
+ mov edi, eax
+ call GetBootFirmwareVolumeOffset
+ add eax, edi
+ push eax
+
+ ;
+ ; Pass stack base and size into the PEI Core
+ ;
+ mov eax, PcdGet32(PcdTemporaryRamBase)
+ add eax, PcdGet32(PcdTemporaryRamSize)
+ sub eax, PcdGet32(PcdFspTemporaryRamSize)
+ push eax
+ push PcdGet32(PcdFspTemporaryRamSize)
+
+ ;
+ ; Pass Control into the PEI Core
+ ;
+ call SecStartup
+
+exit:
+ ret
+
+FspInitApi ENDP
+
+;----------------------------------------------------------------------------
+; NotifyPhase API
+;
+; This FSP API will notify the FSP about the different phases in the boot
+; process
+;
+;----------------------------------------------------------------------------
+NotifyPhaseApi PROC C PUBLIC
+ ;
+ ; Stack must be ready
+ ;
+ push 087654321h
+ pop eax
+ cmp eax, 087654321h
+ jz @F
+ mov eax, 080000003h
+ jmp err_exit
+
+@@:
+ ;
+ ; Verify the calling condition
+ ;
+ pushad
+ push 2
+ call FspApiCallingCheck
+ add esp, 4
+ mov dword ptr [esp + 4 * 7], eax
+ popad
+
+ cmp eax, 0
+ jz @F
+
+ ;
+ ; Error return
+ ;
+err_exit:
+ ret
+
+@@:
+ jmp Pei2LoaderSwitchStack
+
+NotifyPhaseApi ENDP
+
+
+END
diff --git a/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s new file mode 100644 index 0000000000..433ef921c4 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s @@ -0,0 +1,611 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Abstract:
+#
+# Provide FSP API entry points.
+#
+#------------------------------------------------------------------------------
+
+#.INCLUDE "UcodeLoad.inc"
+
+#
+# Following are fixed PCDs
+#
+
+.equ MSR_IA32_PLATFORM_ID, 0x000000017
+.equ MSR_IA32_BIOS_UPDT_TRIG, 0x000000079
+.equ MSR_IA32_BIOS_SIGN_ID, 0x00000008b
+
+ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
+ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
+ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
+ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspAreaSize)
+
+
+#
+# Following functions will be provided in C
+#
+#EXTERNDEF SecStartup:PROC
+#EXTERNDEF FspApiCallingCheck:PROC
+
+#
+# Following functions will be provided in PlatformSecLib
+#
+#EXTERNDEF GetFspBaseAddress:PROC
+#EXTERNDEF GetBootFirmwareVolumeOffset:PROC
+#EXTERNDEF PlatformTempRamInit:PROC
+#EXTERNDEF Pei2LoaderSwitchStack:PROC
+#EXTERN FspSelfCheck(FspSelfCheckDflt):PROC
+#EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC
+
+#
+# Define the data length that we saved on the stack top
+#
+.equ DATA_LEN_OF_PER0, 0x018
+.equ DATA_LEN_OF_MCUD, 0x018
+.equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
+
+#
+# Define SSE macros
+#
+.macro ENABLE_SSE
+ movl %cr4, %eax
+ orl $0x00000600,%eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
+ movl %eax,%cr4
+.endm
+
+.macro SAVE_REGS
+ movd %ebp, %xmm7
+ pshufd $0x93, %xmm7, %xmm7
+ movd %ebx, %xmm6
+ por %xmm6, %xmm7
+ pshufd $0x93, %xmm7, %xmm7
+ movd %esi,%xmm6
+ por %xmm6, %xmm7
+ pshufd $0x93, %xmm7, %xmm7
+ movd %edi, %xmm6
+ por %xmm6, %xmm7
+ movd %esp, %xmm6
+.endm
+
+.macro LOAD_REGS
+ movd %xmm6, %esp
+ movd %xmm7, %edi
+ pshufd $0x39,%xmm7, %xmm7
+ movd %xmm7, %esi
+ pshufd $0x39,%xmm7, %xmm7
+ movd %xmm7, %ebx
+ pshufd $0x39, %xmm7, %xmm7
+ movd %xmm7, %ebp
+.endm
+
+.macro LOAD_ESP
+ movd %xmm6, %esp
+.endm
+
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)
+ASM_PFX(FspSelfCheckDflt):
+ # Inputs:
+ # eax -> Return address
+ # Outputs:
+ # eax -> 0 - Successful, Non-zero - Failed.
+ # Register Usage:
+ # eax is cleared and ebp is used for return address.
+ # All others reserved.
+
+ # Save return address to EBP
+ movl %eax, %ebp
+ xorl %eax, %eax
+exit:
+ jmp *%ebp
+#FspSelfCheckDflt ENDP
+
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)
+ASM_PFX(PlatformBasicInitDflt):
+ # Inputs:
+ # eax -> Return address
+ # Outputs:
+ # eax -> 0 - Successful, Non-zero - Failed.
+ # Register Usage:
+ # eax is cleared and ebp is used for return address.
+ # All others reserved.
+
+ # Save return address to EBP
+ movl %eax, %ebp
+ xorl %eax, %eax
+exit2:
+ jmp *%ebp
+#PlatformBasicInitDflt ENDP
+
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(LoadUcode)
+ASM_PFX(LoadUcode):
+ # Inputs:
+ # esp -> LOAD_UCODE_PARAMS pointer
+ # Register Usage:
+ # esp Preserved
+ # All others destroyed
+ # Assumptions:
+ # No memory available, stack is hard-coded and used for return address
+ # Executed by SBSP and NBSP
+ # Beginning of microcode update region starts on paragraph boundary
+
+ #
+ #
+ # Save return address to EBP
+ movl %eax, %ebp
+ cmpl $0, %esp
+ jz paramerror
+ movl (%esp), %eax #dword ptr [] Parameter pointer
+ cmpl $0, %eax
+ jz paramerror
+ movl %eax, %esp
+ movl (%esp), %esi #LOAD_UCODE_PARAMS.ucode_code_addr
+ cmpl $0, %esi
+ jnz L0
+
+paramerror:
+ movl $0x080000002, %eax
+ jmp exit4
+
+ movl (%esp), %esi #.LOAD_UCODE_PARAMS.ucode_code_addr
+
+check_main_header:
+ # Get processor signature and platform ID from the installed processor
+ # and save into registers for later use
+ # ebx = processor signature
+ # edx = platform ID
+ movl $1, %eax
+ cpuid
+ movl %eax, %ebx
+ movl MSR_IA32_PLATFORM_ID, %ecx
+ rdmsr
+ movl %edx, %ecx
+ #--------------------------------------------------------------------------------------------------------------------
+ shrl $18, %ecx #($50-$32)
+ andl $0x7, %ecx
+ movl $1, %edx
+ shll %cl,%edx
+
+ # Current register usage
+ # esp -> stack with paramters
+ # esi -> microcode update to check
+ # ebx = processor signature
+ # edx = platform ID
+
+ # Check for valid microcode header
+ # Minimal test checking for header version and loader version as 1
+ movl $1, %eax
+ cmpl %eax, (%esi) #.ucode_hdr.version
+ jne advance_fixed_size
+ cmpl %eax, 0x18(%esi) #.ucode_hdr.loader
+ jne advance_fixed_size
+
+ # Check if signature and plaform ID match
+ #--------------------------------------------------------------------------------------------------------------------------
+ cmpl 0x10(%esi), %ebx #(%esi).ucode_hdr.processor
+ jne L0
+ testl 0x1c(%esi) , %edx #(%esi).ucode_hdr.flags
+ jnz load_check # Jif signature and platform ID match
+
+L0:
+ # Check if extended header exists
+ # First check if total_size and data_size are valid
+ xorl %eax, %eax
+ cmpl %eax,0x24(%esi) #(%esi).ucode_hdr.total_size
+ je next_microcode
+ cmpl %eax,0x20(%esi) #(%esi) .ucode_hdr.data_size
+ je next_microcode
+
+ # Then verify total size - sizeof header > data size
+ movl 0x24(%esi), %ecx #(%esi).ucode_hdr.total_size
+ subl $0x30, %ecx #sizeof ucode_hdr = 48
+ cmpl 0x20(%esi), %ecx #(%esi).ucode_hdr.data_size
+ jz load_check
+ jb next_microcode # Jif extended header does not exist
+
+ # Check if total size fits in microcode region
+ movl %esi , %edi
+ addl 0x24(%esi), %edi # (%esi).ucode_hdr.total_size
+ movl (%esp), %ecx # (%esp).LOAD_UCODE_PARAMS.ucode_code_addr
+ addl 4(%esp), %ecx #.LOAD_UCODE_PARAMS.ucode_code_size
+ cmpl %ecx , %edi
+ xorl %eax, %eax
+ ja exit4 # Jif address is outside of ucode region
+
+ # Set edi -> extended header
+ movl %esi , %edi
+ addl $0x30 , %edi #sizeof ucode_hdr = 48
+ addl 0x20(%esi), %edi #%esi.ucode_hdr.data_size
+
+ # Get count of extended structures
+ movl (%edi), %ecx #(%edi).ext_sig_hdr.count
+
+ # Move pointer to first signature structure
+ addl $0x20, %edi # sizeof ext_sig_hdr = 20
+
+check_ext_sig:
+ # Check if extended signature and platform ID match
+ cmpl %ebx, (%edi) #[edi].ext_sig.processor
+ jne L1
+ test %edx, 4(%edi) #[edi].ext_sig.flags
+ jnz load_check # Jif signature and platform ID match
+L9:
+ # Check if any more extended signatures exist
+ addl $0xc, %edi #sizeof ext_sig = 12
+ loop check_ext_sig
+
+next_microcode:
+ # Advance just after end of this microcode
+ xorl %eax, %eax
+ cmpl %eax, 0x24(%esi) #(%esi).ucode_hdr.total_size
+ je L2
+ add 0x24(%esi) , %esi #(%esi).ucode_hdr.total_size
+ jmp check_address
+L10:
+ addl $0x800, %esi
+ jmp check_address
+
+advance_fixed_size:
+ # Advance by 4X dwords
+ addl $0x400, %esi
+
+check_address:
+ # Is valid Microcode start point ?
+ cmp $0x0ffffffff , %esi
+ jz done
+
+ # Address >= microcode region address + microcode region size?
+ movl (%esp), %eax #(%esp).LOAD_UCODE_PARAMS.ucode_code_addr
+ addl 4(%esp), %eax #(%esp).LOAD_UCODE_PARAMS.ucode_code_size
+ cmpl %eax, %esi
+ jae done #Jif address is outside of ucode region
+ jmp check_main_header
+
+load_check:
+ # Get the revision of the current microcode update loaded
+ movl MSR_IA32_BIOS_SIGN_ID, %ecx
+ xorl %eax, %eax # Clear EAX
+ xorl %edx, %edx # Clear EDX
+ wrmsr # Load 0 to MSR at 8Bh
+
+ movl $1, %eax
+ cpuid
+ movl MSR_IA32_BIOS_SIGN_ID, %ecx
+ rdmsr # Get current microcode signature
+
+ # Verify this microcode update is not already loaded
+ cmpl %edx, 4(%esi) #(%esi).ucode_hdr.revision
+ je continue
+
+load_microcode:
+ # EAX contains the linear address of the start of the Update Data
+ # EDX contains zero
+ # ECX contains 79h (IA32_BIOS_UPDT_TRIG)
+ # Start microcode load with wrmsr
+ mov %esi, %eax
+ add $0x30, %eax #sizeof ucode_hdr = 48
+ xorl %edx, %edx
+ mov MSR_IA32_BIOS_UPDT_TRIG,%ecx
+ wrmsr
+ mov $1, %eax
+ cpuid
+
+continue:
+ jmp next_microcode
+
+done:
+ mov $1, %eax
+ cpuid
+ mov MSR_IA32_BIOS_SIGN_ID, %ecx
+ rdmsr # Get current microcode signature
+ xorl %eax, %eax
+ cmp $0 , %edx
+ jnz exit4
+ mov $0x08000000E, %eax
+
+exit4:
+ jmp *%ebp
+
+#LoadUcode ENDP
+
+#----------------------------------------------------------------------------
+# TempRamInit API
+#
+# This FSP API will load the microcode update, enable code caching for the
+# region specified by the boot loader and also setup a temporary stack to be
+# used till main memory is initialized.
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ #
+ # Ensure SSE is enabled
+ #
+ ENABLE_SSE
+
+ #
+ # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
+ #
+ SAVE_REGS
+
+ #
+ # Save timestamp into XMM4 & XMM5
+ #
+ rdtsc
+ movd %edx, %xmm4
+ movd %eax, %xmm5
+
+ #
+ # CPUID/DeviceID check
+ #
+ movl L11, %eax
+ jmp ASM_PFX(FspSelfCheck) # Note: ESP can not be changed.
+L11:
+ cmpl $0, %eax
+ jnz NemInitExit
+
+ #
+ # Platform Basic Init.
+ #
+ movl L1, %eax
+ jmp ASM_PFX(PlatformBasicInitDflt)
+L1:
+ cmp $0, %eax
+ jnz NemInitExit
+
+ #
+ # Load microcode
+ #
+ movl L2, %eax
+ addl $4, %esp
+ jmp LoadUcode
+L2:
+ LOAD_ESP
+ cmpl $0, %eax
+ jnz NemInitExit
+
+ #
+ # Call platform NEM init
+ #-------------------------------------------------------------------------------------------------------------------------
+ movl L3, %eax
+ addl $4, %esp
+ jmp ASM_PFX(PlatformTempRamInit)
+L3:
+ subl $4, %esp
+ cmpl $0, %eax
+ jnz NemInitExit
+
+ #
+ # Save parameter pointer in edx
+ #
+ movl 4(%esp), %edx
+
+ #
+ # Enable FSP STACK
+ #
+ movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
+ addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp
+
+ pushl $DATA_LEN_OF_MCUD # Size of the data region
+ pushl 0x4455434D # Signature of the data region 'MCUD'
+ pushl 12(%edx) # Code size
+ pushl 8(%edx) # Code base
+ cmpl $0, %edx # Is parameter pointer valid ?
+ jz InvalidMicrocodeRegion
+ pushl 4(%edx) # Microcode size
+ pushl (%edx) # Microcode base
+ jmp L4
+
+InvalidMicrocodeRegion:
+ pushl $0 # Microcode size
+ pushl $0 # Microcode base
+
+L4:
+ #
+ # Save API entry/exit timestamp into stack
+ #
+ pushl DATA_LEN_OF_PER0 # Size of the data region
+ pushl 0x30524550 # Signature of the data region 'PER0'
+ movd %xmm4, %eax
+ pushl %eax
+ movd %xmm5, %eax
+ pushl %eax
+ rdtsc
+ pushl %edx
+ pushl %eax
+
+ #
+ # Terminator for the data on stack
+ #
+ pushl $0
+
+ #
+ # Set ECX/EDX to the bootloader temporary memory range
+ #
+ movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %ecx
+ movl %ecx, %edx
+ addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %edx
+ subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %edx
+
+ xorl %eax, %eax
+
+NemInitExit:
+ #
+ # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
+ #
+ LOAD_REGS
+ ret
+#TempRamInitApi ENDP
+
+#----------------------------------------------------------------------------
+# FspInit API
+#
+# This FSP API will perform the processor and chipset initialization.
+# This API will not return. Instead, it transfers the control to the
+# ContinuationFunc provided in the parameter.
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(FspInitApi)
+ASM_PFX(FspInitApi):
+ #
+ # Stack must be ready
+ #
+ pushl $0x087654321
+ pop %eax
+ cmpl $0x087654321, %eax
+ jz L5
+ movl $0x080000003, %eax
+ jmp exit3
+
+L5:
+ #
+ # Additional check
+ #
+ pusha
+ pushl $1
+ call ASM_PFX(FspApiCallingCheck)
+ addl $4, %esp
+ movl %eax, 28(%esp)
+ popa
+ cmpl $0 , %eax
+ jz L6
+ jmp exit3
+
+L6:
+ #
+ # Save the Platform Data Pointer in EDI
+ #
+ movl 4(%esp), %edi
+
+ #
+ # Store the address in FSP which will return control to the BL
+ #
+ pushl $exit3
+
+ #
+ # Create a Task Frame in the stack for the Boot Loader
+ #
+ pushfl
+ pushfl # 2 pushf for 4 byte alignment
+ cli
+ pushal
+
+ # Reserve 8 bytes for IDT save/restore
+ pushl $0
+ pushl $0
+ sidt (%esp)
+
+ #
+ # Setup new FSP stack
+ #
+ movl %esp, %eax
+ movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
+ addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize) , %esp
+ subl DATA_LEN_AT_STACK_TOP, %esp
+ addl $0x0FFFFFFC0, %esp
+
+ #
+ # Save the bootloader's stack pointer
+ #
+ pushl %eax
+
+ #
+ # Pass entry point of the PEI core
+ #
+ call ASM_PFX(GetFspBaseAddress)
+ movl %eax, %edi
+ addl ASM_PFX(_gPcd_FixedAtBuild_PcdFspAreaSize), %edi
+ subl $0x20, %edi
+ addl %ds:(%edi), %eax
+ pushl %eax
+
+ #
+ # Pass BFV into the PEI Core
+ # It uses relative address to calucate the actual boot FV base
+ # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
+ # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
+ # they are different. The code below can handle both cases.
+ #
+ call ASM_PFX(GetFspBaseAddress)
+ movl %eax , %edi
+ call ASM_PFX(GetBootFirmwareVolumeOffset)
+ addl %edi ,%eax
+ pushl %eax
+
+ #
+ # Pass stack base and size into the PEI Core
+ #
+ movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %eax
+ addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %eax
+ subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %eax
+ pushl %eax
+ pushl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
+
+ #
+ # Pass Control into the PEI Core
+ #
+ call ASM_PFX(SecStartup)
+
+exit3:
+ ret
+
+# FspInitApi ENDP
+
+#----------------------------------------------------------------------------
+# NotifyPhase API
+#
+# This FSP API will notify the FSP about the different phases in the boot
+# process
+#
+#----------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
+ASM_PFX(NotifyPhaseApi):
+ #
+ # Stack must be ready
+ #
+ pushl $0x0087654321
+ pop %eax
+ cmpl $0x087654321, %eax
+ jz L7
+ movl $0x080000003, %eax
+ jmp err_exit
+
+L7:
+ #
+ # Verify the calling condition
+ #
+ pusha
+ pushl $2
+ call ASM_PFX(FspApiCallingCheck)
+ add $4, %esp
+ mov %eax, 28(%esp)
+ popa
+
+ cmpl $0, %eax
+ jz L8
+
+ #
+ # Error return
+ #
+err_exit:
+ ret
+
+L8:
+ jmp ASM_PFX(Pei2LoaderSwitchStack)
+
+#NotifyPhaseApi ENDP
+
+
+#END
diff --git a/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm new file mode 100644 index 0000000000..07f504da4b --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm @@ -0,0 +1,79 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+;------------------------------------------------------------------------------
+
+ .686
+ .model flat,C
+ .const
+;
+; Float control word initial value:
+; all exceptions masked, double-precision, round-to-nearest
+;
+mFpuControlWord DW 027Fh
+;
+; Multimedia-extensions control word:
+; all exceptions masked, round-to-nearest, flush to zero for masked underflow
+;
+mMmxControlWord DD 01F80h
+
+ .xmm
+ .code
+
+;
+; Initializes floating point units for requirement of UEFI specification.
+;
+; This function initializes floating-point control word to 0x027F (all exceptions
+; masked,double-precision, round-to-nearest) and multimedia-extensions control word
+; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+; for masked underflow).
+;
+InitializeFloatingPointUnits PROC PUBLIC
+
+ push ebx
+
+ ;
+ ; Initialize floating point units
+ ;
+ finit
+ fldcw mFpuControlWord
+
+ ;
+ ; Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ ; whether the processor supports SSE instruction.
+ ;
+ mov eax, 1
+ cpuid
+ bt edx, 25
+ jnc Done
+
+ ;
+ ; Set OSFXSR bit 9 in CR4
+ ;
+ mov eax, cr4
+ or eax, BIT9
+ mov cr4, eax
+
+ ;
+ ; The processor should support SSE instruction and we can use
+ ; ldmxcsr instruction
+ ;
+ ldmxcsr mMmxControlWord
+Done:
+ pop ebx
+
+ ret
+
+InitializeFloatingPointUnits ENDP
+
+END
diff --git a/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s new file mode 100644 index 0000000000..cfec8d7df5 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s @@ -0,0 +1,73 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Abstract:
+#
+#------------------------------------------------------------------------------
+
+#
+# Float control word initial value:
+# all exceptions masked, double-precision, round-to-nearest
+#
+ASM_PFX(mFpuControlWord): .word 0x027F
+#
+# Multimedia-extensions control word:
+# all exceptions masked, round-to-nearest, flush to zero for masked underflow
+#
+ASM_PFX(mMmxControlWord): .long 0x01F80
+
+
+
+#
+# Initializes floating point units for requirement of UEFI specification.
+#
+# This function initializes floating-point control word to 0x027F (all exceptions
+# masked,double-precision, round-to-nearest) and multimedia-extensions control word
+# (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+# for masked underflow).
+#
+ASM_GLOBAL ASM_PFX(InitializeFloatingPointUnits)
+ASM_PFX(InitializeFloatingPointUnits):
+
+ pushl %ebx
+
+ #
+ # Initialize floating point units
+ #
+ finit
+ fldcw ASM_PFX(mFpuControlWord)
+
+ #
+ # Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ # whether the processor supports SSE instruction.
+ #
+ movl $1, %eax
+ cpuid
+ btl $25, %edx
+ jnc Done
+
+ #
+ # Set OSFXSR bit 9 in CR4
+ #
+ movl %cr4, %eax
+ or BIT9, %eax
+ movl %eax, %cr4
+
+ #
+ # The processor should support SSE instruction and we can use
+ # ldmxcsr instruction
+ #
+ ldmxcsr ASM_PFX(mMmxControlWord)
+
+Done:
+ popl %ebx
+
+ ret
diff --git a/IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16 b/IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16 new file mode 100644 index 0000000000..f77c9a46dd --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16 @@ -0,0 +1,103 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+; Reset Vector Data structure
+; This structure is located at 0xFFFFFFC0
+;
+;------------------------------------------------------------------------------
+
+ .model tiny
+ .686p
+ .stack 0h
+ .code
+
+;
+; The layout of this file is fixed. The build tool makes assumption of the layout.
+;
+
+ ORG 0h
+;
+; Reserved
+;
+ReservedData DD 0eeeeeeeeh, 0eeeeeeeeh
+
+ ORG 10h
+;
+; This is located at 0xFFFFFFD0h
+;
+ mov di, "AP"
+ jmp ApStartup
+
+ ORG 20h
+;
+; Pointer to the entry point of the PEI core
+; It is located at 0xFFFFFFE0, and is fixed up by some build tool
+; So if the value 8..1 appears in the final FD image, tool failure occurs.
+;
+PeiCoreEntryPoint DD 12345678h
+
+;
+; This is the handler for all kinds of exceptions. Since it's for debugging
+; purpose only, nothing except a deadloop would be done here. Developers could
+; analyze the cause of the exception if a debugger had been attached.
+;
+InterruptHandler PROC
+ jmp $
+ iret
+InterruptHandler ENDP
+
+ ORG 30h
+;
+; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+; Execution starts here upon power-on/platform-reset.
+;
+ResetHandler:
+ nop
+ nop
+
+ApStartup:
+ ;
+ ; Jmp Rel16 instruction
+ ; Use machine code directly in case of the assembler optimization
+ ; SEC entry point relatvie address will be fixed up by some build tool.
+ ;
+ ; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ ; SecEntry.asm
+ ;
+ DB 0e9h
+ DW -3
+
+
+ ORG 38h
+;
+; Ap reset vector segment address is at 0xFFFFFFF8
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs
+;
+ApSegAddress dd 12345678h
+
+ ORG 3ch
+;
+; BFV Base is at 0xFFFFFFFC
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs.
+;
+BfvBase DD 12345678h
+
+;
+; Nothing can go here, otherwise the layout of this file would change.
+;
+
+ END
diff --git a/IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc b/IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc new file mode 100644 index 0000000000..a3d5c47ffa --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc @@ -0,0 +1,103 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+; Provide macro for register save/restore using SSE registers
+;
+;------------------------------------------------------------------------------
+
+;
+; Define SSE instruction set
+;
+IFDEF USE_SSE41_FLAG
+;
+; Define SSE macros using SSE 4.1 instructions
+;
+SXMMN MACRO XMM, IDX, REG
+ pinsrd XMM, REG, (IDX AND 3)
+ ENDM
+
+LXMMN MACRO XMM, REG, IDX
+ pextrd REG, XMM, (IDX AND 3)
+ ENDM
+ELSE
+;
+; Define SSE macros using SSE 2 instructions
+;
+SXMMN MACRO XMM, IDX, REG
+ pinsrw XMM, REG, (IDX AND 3) * 2
+ ror REG, 16
+ pinsrw XMM, REG, (IDX AND 3) * 2 + 1
+ rol REG, 16
+ ENDM
+
+LXMMN MACRO XMM, REG, IDX
+ pshufd XMM, XMM, (0E4E4E4h SHR (IDX * 2)) AND 0FFh
+ movd REG, XMM
+ pshufd XMM, XMM, (0E4E4E4h SHR (IDX * 2 + (IDX AND 1) * 4)) AND 0FFh
+ ENDM
+ENDIF
+
+
+SAVE_REGS MACRO
+ SXMMN xmm7, 0, ebp
+ SXMMN xmm7, 1, ebx
+ SXMMN xmm7, 2, esi
+ SXMMN xmm7, 3, edi
+ SAVE_ESP
+ ENDM
+
+LOAD_REGS MACRO
+ LXMMN xmm7, ebp, 0
+ LXMMN xmm7, ebx, 1
+ LXMMN xmm7, esi, 2
+ LXMMN xmm7, edi, 3
+ LOAD_ESP
+ ENDM
+
+LOAD_EAX MACRO
+ LXMMN xmm6, eax, 1
+ ENDM
+
+SAVE_EAX MACRO
+ SXMMN xmm6, 1, eax
+ ENDM
+
+LOAD_EDX MACRO
+ LXMMN xmm6, edx, 2
+ ENDM
+
+SAVE_EDX MACRO
+ SXMMN xmm6, 2, edx
+ ENDM
+
+SAVE_ECX MACRO
+ SXMMN xmm6, 3, ecx
+ ENDM
+
+LOAD_ECX MACRO
+ LXMMN xmm6, ecx, 3
+ ENDM
+
+SAVE_ESP MACRO
+ SXMMN xmm6, 0, esp
+ ENDM
+
+LOAD_ESP MACRO
+ movd esp, xmm6
+ ENDM
+
+ENABLE_SSE MACRO
+ mov eax, cr4
+ or eax, 00000600h
+ mov cr4, eax
+ ENDM
diff --git a/IntelFspPkg/FspSecCore/Ia32/Stack.asm b/IntelFspPkg/FspSecCore/Ia32/Stack.asm new file mode 100644 index 0000000000..f96a55f040 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/Stack.asm @@ -0,0 +1,82 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+; Switch the stack from temporary memory to permenent memory.
+;
+;------------------------------------------------------------------------------
+
+ .586p
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; SecSwitchStack (
+; UINT32 TemporaryMemoryBase,
+; UINT32 PermenentMemoryBase
+; );
+;------------------------------------------------------------------------------
+SecSwitchStack PROC
+ ;
+ ; Save three register: eax, ebx, ecx
+ ;
+ push eax
+ push ebx
+ push ecx
+ push edx
+
+ ;
+ ; !!CAUTION!! this function address's is pushed into stack after
+ ; migration of whole temporary memory, so need save it to permenent
+ ; memory at first!
+ ;
+
+ mov ebx, [esp + 20] ; Save the first parameter
+ mov ecx, [esp + 24] ; Save the second parameter
+
+ ;
+ ; Save this function's return address into permenent memory at first.
+ ; Then, Fixup the esp point to permenent memory
+ ;
+ mov eax, esp
+ sub eax, ebx
+ add eax, ecx
+ mov edx, dword ptr [esp] ; copy pushed register's value to permenent memory
+ mov dword ptr [eax], edx
+ mov edx, dword ptr [esp + 4]
+ mov dword ptr [eax + 4], edx
+ mov edx, dword ptr [esp + 8]
+ mov dword ptr [eax + 8], edx
+ mov edx, dword ptr [esp + 12]
+ mov dword ptr [eax + 12], edx
+ mov edx, dword ptr [esp + 16] ; Update this function's return address into permenent memory
+ mov dword ptr [eax + 16], edx
+ mov esp, eax ; From now, esp is pointed to permenent memory
+
+ ;
+ ; Fixup the ebp point to permenent memory
+ ;
+ mov eax, ebp
+ sub eax, ebx
+ add eax, ecx
+ mov ebp, eax ; From now, ebp is pointed to permenent memory
+
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ ret
+SecSwitchStack ENDP
+
+ END
diff --git a/IntelFspPkg/FspSecCore/Ia32/Stacks.s b/IntelFspPkg/FspSecCore/Ia32/Stacks.s new file mode 100644 index 0000000000..6c36c25d2b --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/Stacks.s @@ -0,0 +1,88 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Abstract:
+#
+# Switch the stack from temporary memory to permenent memory.
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(SecSwitchStack)
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# SecSwitchStack (
+# UINT32 TemporaryMemoryBase,
+# UINT32 PermenentMemoryBase
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+#
+# Save three register: eax, ebx, ecx
+#
+ push %eax
+ push %ebx
+ push %ecx
+ push %edx
+
+#
+# !!CAUTION!! this function address's is pushed into stack after
+# migration of whole temporary memory, so need save it to permenent
+# memory at first!
+#
+
+ movl 20(%esp), %ebx # Save the first parameter
+ movl 24(%esp), %ecx # Save the second parameter
+
+#
+# Save this function's return address into permenent memory at first.
+# Then, Fixup the esp point to permenent memory
+#
+
+ movl %esp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl (%esp), %edx # copy pushed register's value to permenent memory
+ movl %edx, (%eax)
+ movl 4(%esp), %edx
+ movl %edx, 4(%eax)
+ movl 8(%esp), %edx
+ movl %edx, 8(%eax)
+ movl 12(%esp), %edx
+ movl %edx, 12(%eax)
+ movl 16(%esp), %edx # Update this function's return address into permenent memory
+ movl %edx, 16(%eax)
+ movl %eax, %esp # From now, esp is pointed to permenent memory
+
+#
+# Fixup the ebp point to permenent memory
+#
+
+ movl %ebp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl %eax, %ebp # From now, ebp is pointed to permenent memory
+
+#
+# Fixup callee's ebp point for PeiDispatch
+#
+ movl %ebp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl %eax, %ebp # From now, ebp is pointed to permenent memory
+
+ pop %edx
+ pop %ecx
+ pop %ebx
+ pop %eax
+ ret
\ No newline at end of file diff --git a/IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc b/IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc new file mode 100644 index 0000000000..6be6ed097b --- /dev/null +++ b/IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+;------------------------------------------------------------------------------
+
+MSR_IA32_PLATFORM_ID EQU 000000017h
+MSR_IA32_BIOS_UPDT_TRIG EQU 000000079h
+MSR_IA32_BIOS_SIGN_ID EQU 00000008bh
+
+ucode STRUCT 1t
+ version DWORD ?
+ revision DWORD ?
+ date DWORD ?
+ processor DWORD ?
+ checksum DWORD ?
+ loader DWORD ?
+ rsvd DWORD 6t DUP (?)
+ data DWORD 500t DUP (?)
+ucode ENDS
+ucode_t TYPEDEF ucode
+
+ucode_hdr STRUCT 1t
+ version DWORD ?
+ revision DWORD ?
+ date DWORD ?
+ processor DWORD ?
+ checksum DWORD ?
+ loader DWORD ?
+ flags DWORD ?
+ data_size DWORD ?
+ total_size DWORD ?
+ rsvd DWORD 3t DUP (?)
+ucode_hdr ENDS
+ucode_hdr_t TYPEDEF ucode_hdr
+
+ext_sig_hdr STRUCT 1t
+ count DWORD ?
+ checksum DWORD ?
+ rsvd DWORD 3t DUP (?)
+ext_sig_hdr ENDS
+ext_sig_hdr_t TYPEDEF ext_sig_hdr
+
+ext_sig STRUCT 1t
+ processor DWORD ?
+ flags DWORD ?
+ checksum DWORD ?
+ext_sig ENDS
+ext_sig_t TYPEDEF ext_sig
+
+LOAD_UCODE_PARAMS STRUCT 1t
+ ucode_code_addr DWORD ?
+ ucode_code_size DWORD ?
+LOAD_UCODE_PARAMS ENDS
diff --git a/IntelFspPkg/FspSecCore/SecFsp.c b/IntelFspPkg/FspSecCore/SecFsp.c new file mode 100644 index 0000000000..00eb224c6f --- /dev/null +++ b/IntelFspPkg/FspSecCore/SecFsp.c @@ -0,0 +1,268 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SecFsp.h"
+
+UINT32 FspImageSizeOffset = FSP_INFO_HEADER_OFF + OFFSET_IN_FSP_INFO_HEADER(ImageSize);
+
+/**
+
+ Calculate the FSP IDT gate descriptor.
+
+ @param[in] IdtEntryTemplate IDT gate descriptor template.
+
+ @return FSP specific IDT gate descriptor.
+
+**/
+UINT64
+FspGetExceptionHandler(
+ IN UINT64 IdtEntryTemplate
+ )
+{
+ UINT32 Entry;
+ UINT64 ExceptionHandler;
+ IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor;
+ FSP_INFO_HEADER *FspInfoHeader;
+
+ FspInfoHeader = (FSP_INFO_HEADER *)(GetFspBaseAddress() + FSP_INFO_HEADER_OFF);
+ ExceptionHandler = IdtEntryTemplate;
+ IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler;
+ Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow;
+ Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1);
+ IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16);
+ IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry;
+
+ return ExceptionHandler;
+}
+
+/**
+ This function gets the FSP UPD region offset in flash.
+
+ @return the offset of the UPD region.
+
+**/
+UINT32
+EFIAPI
+GetFspUpdRegionOffset (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+ UINT32 *Offset;
+
+ FspData = GetFspGlobalDataPointer ();
+
+ //
+ // It is required to put PcdUpdRegionOffset at offset 0x000C
+ // for all FSPs.
+ // gPlatformFspPkgTokenSpaceGuid.PcdUpdRegionOffset | 0x000C | 0x12345678
+ //
+ Offset = (UINT32 *)(FspData->FspInfoHeader->ImageBase + \
+ FspData->FspInfoHeader->CfgRegionOffset + 0x0C);
+
+ return *Offset;
+}
+
+/**
+ This interface fills platform specific data.
+
+ @param[in,out] FspData Pointer to the FSP global data.
+
+**/
+VOID
+EFIAPI
+SecGetPlatformData (
+ IN OUT FSP_GLOBAL_DATA *FspData
+ )
+{
+ FSP_PLAT_DATA *FspPlatformData;
+ UINT32 TopOfCar;
+ UINT32 *StackPtr;
+ UINT32 DwordSize;
+
+ FspPlatformData = &FspData->PlatformData;
+
+ //
+ // The entries of platform information, together with the number of them,
+ // reside in the bottom of stack, left untouched by normal stack operation.
+ //
+ TopOfCar = PcdGet32 (PcdTemporaryRamBase) + PcdGet32 (PcdTemporaryRamSize);
+
+ FspPlatformData->DataPtr = NULL;
+ FspPlatformData->CodeRegionSize = 0;
+ FspPlatformData->CodeRegionBase = 0;
+ FspPlatformData->MicorcodeRegionBase = 0;
+ FspPlatformData->MicorcodeRegionSize = 0;
+
+ //
+ // Pointer to the size field
+ //
+ StackPtr = (UINT32 *)(TopOfCar - sizeof(UINT32));
+
+ while (*StackPtr != 0) {
+ if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) {
+ //
+ // This following data was pushed onto stack after TempRamInit API
+ //
+ DwordSize = 4;
+ StackPtr = StackPtr - 1 - DwordSize;
+ CopyMem (&(FspPlatformData->CodeRegionBase), StackPtr, (DwordSize << 2));
+ StackPtr--;
+ } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) {
+ //
+ // This is the performance data for InitTempMemory API entry/exit
+ //
+ DwordSize = 4;
+ StackPtr = StackPtr - 1 - DwordSize;
+ CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2));
+ ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TMPRAMINIT_ENTRY;
+ ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TMPRAMINIT_EXIT;
+ StackPtr--;
+ } else {
+ StackPtr -= (*StackPtr);
+ }
+ }
+}
+
+/**
+
+ Initialize the FSP global data region.
+ It needs to be done as soon as possible after the stack is setup.
+
+ @param[in,out] PeiFspData Pointer of the FSP global data.
+ @param[in] BootFirmwareVolume Point to the address of BootFirmwareVolume in stack.
+
+**/
+VOID
+FspGlobalDataInit (
+ IN OUT FSP_GLOBAL_DATA *PeiFspData,
+ IN VOID **BootFirmwareVolume
+ )
+{
+ VOID *UpdDataRgnPtr;
+ FSP_INIT_PARAMS *FspInitParams;
+ CHAR8 ImageId[9];
+ UINTN Idx;
+
+ //
+ // Init PCIE_BAR with value and set global FSP data pointer.
+ // PciExpress Base should have been programmed by platform already.
+ //
+ SetFspGlobalDataPointer (PeiFspData);
+ ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA));
+
+ PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE;
+ PeiFspData->CoreStack = *(UINTN *)(BootFirmwareVolume + 2);
+ PeiFspData->PerfIdx = 2;
+
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_ENTRY);
+
+ //
+ // Get FSP Header offset
+ // It may have multiple FVs, so look into the last one for FSP header
+ //
+ PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)(GetFspBaseAddress() + FSP_INFO_HEADER_OFF);
+ SecGetPlatformData (PeiFspData);
+
+ //
+ // Initialize UPD pointer.
+ //
+ FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
+ UpdDataRgnPtr = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr)->UpdDataRgnPtr;
+ if (UpdDataRgnPtr == NULL) {
+ UpdDataRgnPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + GetFspUpdRegionOffset());
+ }
+ SetFspUpdDataPointer (UpdDataRgnPtr);
+
+ //
+ // Initialize serial port
+ // It might have been done in ProcessLibraryConstructorList(), however,
+ // the FSP global data is not initialized at that time. So do it again
+ // for safe.
+ //
+ SerialPortInitialize ();
+
+ //
+ // Ensure the golbal data pointer is valid
+ //
+ ASSERT (GetFspGlobalDataPointer () == PeiFspData);
+
+ for (Idx = 0; Idx < 8; Idx++) {
+ ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx];
+ }
+ ImageId[Idx] = 0;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= PEIM FSP (%a 0x%08X) =============\n", \
+ ImageId, PeiFspData->FspInfoHeader->ImageRevision));
+
+}
+
+/**
+
+ Adjust the FSP data pointers after the stack is migrated to memory.
+
+ @param[in] OffsetGap The offset gap between the old stack and the new stack.
+
+**/
+VOID
+FspDataPointerFixUp (
+ IN UINT32 OffsetGap
+ )
+{
+ FSP_GLOBAL_DATA *NewFspData;
+
+ NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap);
+ SetFspGlobalDataPointer (NewFspData);
+}
+
+/**
+ This function check the FSP API calling condition.
+
+ @param[in] ApiIdx Internal index of the FSP API.
+
+**/
+EFI_STATUS
+EFIAPI
+FspApiCallingCheck (
+ UINT32 ApiIdx
+ )
+{
+ EFI_STATUS Status;
+ FSP_GLOBAL_DATA *FspData;
+
+ Status = EFI_SUCCESS;
+ FspData = GetFspGlobalDataPointer ();
+ if (ApiIdx == 1) {
+ //
+ // FspInit check
+ //
+ if ((UINT32)FspData != 0xFFFFFFFF) {
+ Status = EFI_UNSUPPORTED;
+ }
+ } else if (ApiIdx == 2) {
+ //
+ // NotifyPhase check
+ //
+ if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
diff --git a/IntelFspPkg/FspSecCore/SecFsp.h b/IntelFspPkg/FspSecCore/SecFsp.h new file mode 100644 index 0000000000..9e129e4d5d --- /dev/null +++ b/IntelFspPkg/FspSecCore/SecFsp.h @@ -0,0 +1,97 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SEC_FSP_H_
+#define _SEC_FSPE_H_
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/FspCommonLib.h>
+
+#include <FspApi.h>
+
+#define FSP_MCUD_SIGNATURE SIGNATURE_32 ('M', 'C', 'U', 'D')
+#define FSP_PER0_SIGNATURE SIGNATURE_32 ('P', 'E', 'R', '0')
+
+/**
+
+ Calculate the FSP IDT gate descriptor.
+
+ @param[in] IdtEntryTemplate IDT gate descriptor template.
+
+ @return FSP specific IDT gate descriptor.
+
+**/
+UINT64
+FspGetExceptionHandler(
+ IN UINT64 IdtEntryTemplate
+ );
+
+/**
+
+ Initialize the FSP global data region.
+ It needs to be done as soon as possible after the stack is setup.
+
+ @param[in,out] PeiFspData Pointer of the FSP global data.
+ @param[in] BootFirmwareVolume Point to the address of BootFirmwareVolume in stack.
+
+**/
+VOID
+FspGlobalDataInit (
+ IN OUT FSP_GLOBAL_DATA *PeiFspData,
+ IN VOID **BootFirmwareVolume
+ );
+
+
+/**
+
+ Adjust the FSP data pointers after the stack is migrated to memory.
+
+ @param[in] OffsetGap The offset gap between the old stack and the new stack.
+
+**/
+VOID
+FspDataPointerFixUp (
+ IN UINT32 OffsetGap
+ );
+
+
+/**
+ This interface returns the base address of FSP binary.
+
+ @return FSP binary base address.
+
+**/
+UINT32
+EFIAPI
+GetFspBaseAddress (
+ VOID
+ );
+
+/**
+ This function gets the FSP UPD region offset in flash.
+
+ @return the offset of the UPD region.
+
+**/
+UINT32
+EFIAPI
+GetFspUpdRegionOffset (
+ VOID
+ );
+
+#endif
diff --git a/IntelFspPkg/FspSecCore/SecMain.c b/IntelFspPkg/FspSecCore/SecMain.c new file mode 100644 index 0000000000..22706c8a8b --- /dev/null +++ b/IntelFspPkg/FspSecCore/SecMain.c @@ -0,0 +1,208 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SecMain.h"
+#include "SecFsp.h"
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
+ SecTemporaryRamSupport
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamSupportPpiGuid,
+ &gSecTemporaryRamSupportPpi
+ }
+};
+
+//
+// These are IDT entries pointing to 08:FFFFFFE4h.
+//
+UINT64 mIdtEntryTemplate = 0xffff8e000008ffe4ULL;
+
+/**
+
+ 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] SizeOfRam Size of the temporary memory available for use.
+ @param[in] TempRamBase Base address of tempory ram
+ @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
+
+ @return This function never returns.
+
+**/
+VOID
+EFIAPI
+SecStartup (
+ IN UINT32 SizeOfRam,
+ IN UINT32 TempRamBase,
+ IN VOID *BootFirmwareVolume
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ IA32_DESCRIPTOR IdtDescriptor;
+ SEC_IDT_TABLE IdtTableInStack;
+ UINT32 Index;
+ FSP_GLOBAL_DATA PeiFspData;
+ PEI_CORE_ENTRY PeiCore;
+ UINT64 ExceptionHandler;
+
+ //
+ // Process all libraries constructor function linked to SecCore.
+ //
+ ProcessLibraryConstructorList ();
+
+ //
+ // Initialize floating point operating environment
+ // to be compliant with UEFI spec.
+ //
+ InitializeFloatingPointUnits ();
+
+
+ // |-------------------|---->
+ // |Idt Table |
+ // |-------------------|
+ // |PeiService Pointer | PeiStackSize
+ // |-------------------|
+ // | |
+ // | Stack |
+ // |-------------------|---->
+ // | |
+ // | |
+ // | Heap | PeiTemporayRamSize
+ // | |
+ // | |
+ // |-------------------|----> TempRamBase
+ IdtTableInStack.PeiService = NULL;
+ ExceptionHandler = FspGetExceptionHandler(mIdtEntryTemplate);
+ for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
+ CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&ExceptionHandler, sizeof (UINT64));
+ }
+
+ IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
+ IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+ //
+ // Iniitalize the global FSP data region
+ //
+ FspGlobalDataInit (&PeiFspData, &BootFirmwareVolume);
+
+ //
+ // Update the base address and length of Pei temporary memory
+ //
+ SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
+ SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
+ SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
+ SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
+ SecCoreData.TemporaryRamSize = SizeOfRam;
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = SizeOfRam >> 1;
+ SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
+ SecCoreData.StackSize = SizeOfRam >> 1;
+
+ //
+ // Call PeiCore Entry
+ //
+ PeiCore = (PEI_CORE_ENTRY)(*(UINTN *)((&BootFirmwareVolume) + 1));
+ PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi);
+
+ //
+ // Should never be here
+ //
+ CpuDeadLoop ();
+}
+
+/**
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupport (
+ 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;
+
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase + CopySize / 2);
+
+ OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize / 2);
+ NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+ //
+ // Migrate Heap
+ //
+ CopyMem (NewHeap, OldHeap, CopySize / 2);
+
+ //
+ // Migrate Stack
+ //
+ CopyMem (NewStack, OldStack, CopySize / 2);
+
+
+ //
+ // We need *not* fix the return address because currently,
+ // The PeiCore is executed in flash.
+ //
+
+ //
+ // Rebase IDT table in permanent memory
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+ //
+ // Fixed the FSP data pointer
+ //
+ FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack);
+
+ //
+ // SecSwitchStack function must be invoked after the memory migration
+ // immediatly, also we need fixup the stack change caused by new call into
+ // permenent memory.
+ //
+ SecSwitchStack (
+ (UINT32) (UINTN) OldStack,
+ (UINT32) (UINTN) NewStack
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFspPkg/FspSecCore/SecMain.h b/IntelFspPkg/FspSecCore/SecMain.h new file mode 100644 index 0000000000..4dfbc850b3 --- /dev/null +++ b/IntelFspPkg/FspSecCore/SecMain.h @@ -0,0 +1,134 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SEC_CORE_H_
+#define _SEC_CORE_H_
+
+
+#include <PiPei.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/FspSwitchStackLib.h>
+#include <Library/FspCommonLib.h>
+#include <FspApi.h>
+
+#define SEC_IDT_ENTRY_COUNT 34
+
+typedef VOID (*PEI_CORE_ENTRY) ( \
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, \
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList \
+);
+
+typedef struct _SEC_IDT_TABLE {
+ EFI_PEI_SERVICES *PeiService;
+ UINT64 IdtTable[SEC_IDT_ENTRY_COUNT];
+} SEC_IDT_TABLE;
+
+/**
+ Switch the stack in the temporary memory to the one in the permanent memory.
+
+ This function must be invoked after the memory migration immediately. The relative
+ position of the stack in the temporary and permanent memory is same.
+
+ @param[in] TemporaryMemoryBase Base address of the temporary memory.
+ @param[in] PermenentMemoryBase Base address of the permanent memory.
+**/
+VOID
+EFIAPI
+SecSwitchStack (
+ IN UINT32 TemporaryMemoryBase,
+ IN UINT32 PermenentMemoryBase
+ );
+
+/**
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+/**
+ Initializes floating point units for requirement of UEFI specification.
+
+ This function initializes floating-point control word to 0x027F (all exceptions
+ masked,double-precision, round-to-nearest) and multimedia-extensions control word
+ (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+ for masked underflow).
+
+**/
+VOID
+EFIAPI
+InitializeFloatingPointUnits (
+ VOID
+ );
+
+/**
+
+ 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] SizeOfRam Size of the temporary memory available for use.
+ @param[in] TempRamBase Base address of tempory ram
+ @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
+
+ @return This function never returns.
+
+**/
+VOID
+EFIAPI
+SecStartup (
+ IN UINT32 SizeOfRam,
+ IN UINT32 TempRamBase,
+ IN VOID *BootFirmwareVolume
+ );
+
+/**
+ Autogenerated function that calls the library constructors for all of the module's
+ dependent libraries. This function must be called by the SEC Core once a stack has
+ been established.
+
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+ VOID
+ );
+
+#endif
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw b/IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw Binary files differnew file mode 100644 index 0000000000..2dc9f178d3 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw diff --git a/IntelFspPkg/FspSecCore/Vtf0/Build.py b/IntelFspPkg/FspSecCore/Vtf0/Build.py new file mode 100644 index 0000000000..3018391445 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Vtf0/Build.py @@ -0,0 +1,53 @@ +## @file
+# Automate the process of building the various reset vector types
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+import glob
+import os
+import subprocess
+import sys
+
+def RunCommand(commandLine):
+ #print ' '.join(commandLine)
+ return subprocess.call(commandLine)
+
+for filename in glob.glob(os.path.join('Bin', '*.raw')):
+ os.remove(filename)
+
+arch = 'ia32'
+debugType = None
+output = os.path.join('Bin', 'ResetVec')
+output += '.' + arch
+if debugType is not None:
+ output += '.' + debugType
+output += '.raw'
+commandLine = (
+ 'nasm',
+ '-D', 'ARCH_%s' % arch.upper(),
+ '-D', 'DEBUG_%s' % str(debugType).upper(),
+ '-o', output,
+ 'ResetVectorCode.asm',
+ )
+ret = RunCommand(commandLine)
+print '\tASM\t' + output
+if ret != 0: sys.exit(ret)
+
+commandLine = (
+ 'python',
+ 'Tools/FixupForRawSection.py',
+ output,
+ )
+print '\tFIXUP\t' + output
+ret = RunCommand(commandLine)
+if ret != 0: sys.exit(ret)
+
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 b/IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 new file mode 100644 index 0000000000..585876fa86 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 @@ -0,0 +1,103 @@ +;; @file
+; Reset Vector Data structure
+; This structure is located at 0xFFFFFFC0
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;;
+
+BITS 16
+
+
+;
+; The layout of this file is fixed. The build tool makes assumption of the layout.
+;
+
+ORG 0x0
+;
+; Reserved
+;
+ReservedData: DD 0eeeeeeeeh, 0eeeeeeeeh
+
+ ; ORG 0x10
+ TIMES 0x10-($-$$) DB 0
+;
+; This is located at 0xFFFFFFD0h
+;
+ mov di, "AP"
+ jmp ApStartup
+
+ ; ORG 0x20
+
+ TIMES 0x20-($-$$) DB 0
+
+; Pointer to the entry point of the PEI core
+; It is located at 0xFFFFFFE0, and is fixed up by some build tool
+; So if the value 8..1 appears in the final FD image, tool failure occurs.
+;
+PeiCoreEntryPoint: DD 0x12345678
+
+;
+; This is the handler for all kinds of exceptions. Since it's for debugging
+; purpose only, nothing except a deadloop would be done here. Developers could
+; analyze the cause of the exception if a debugger had been attached.
+;
+InterruptHandler:
+ jmp $
+ iret
+
+ ; ORG 0x30
+ TIMES 0x30-($-$$) DB 0
+;
+; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+; Execution starts here upon power-on/platform-reset.
+;
+ResetHandler:
+ nop
+ nop
+
+ApStartup:
+ ;
+ ; Jmp Rel16 instruction
+ ; Use machine code directly in case of the assembler optimization
+ ; SEC entry point relatvie address will be fixed up by some build tool.
+ ;
+ ; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ ; SecEntry.asm
+ ;
+ DB 0x0e9
+ DW -3
+
+ ; ORG 0x38
+
+ TIMES 0x38-($-$$) DB 0
+;
+; Ap reset vector segment address is at 0xFFFFFFF8
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs
+;
+ApSegAddress: dd 0x12345678
+
+ ; ORG 0x3c
+ TIMES 0x3c-($-$$) DB 0
+;
+; BFV Base is at 0xFFFFFFFC
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs.
+;
+BfvBase: DD 0x12345678
+
+;
+; Nothing can go here, otherwise the layout of this file would change.
+;
+
+ ; END
diff --git a/IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm b/IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm new file mode 100644 index 0000000000..72b252491f --- /dev/null +++ b/IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm @@ -0,0 +1,17 @@ +;------------------------------------------------------------------------------
+; @file
+; This file includes all other code files to assemble the reset vector code
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;------------------------------------------------------------------------------
+
+
+%include "Ia16/ResetVec.asm16"
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py b/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py new file mode 100644 index 0000000000..8e7c20b401 --- /dev/null +++ b/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py @@ -0,0 +1,110 @@ +## @file
+# Apply fixup to VTF binary image for FFS Raw section
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+import sys
+
+filename = sys.argv[1]
+
+if filename.lower().find('ia32') >= 0:
+ d = open(sys.argv[1], 'rb').read()
+ c = ((len(d) + 4 + 7) & ~7) - 4
+ if c > len(d):
+ c -= len(d)
+ f = open(sys.argv[1], 'wb')
+ f.write('\x90' * c)
+ f.write(d)
+ f.close()
+else:
+ from struct import pack
+
+ PAGE_PRESENT = 0x01
+ PAGE_READ_WRITE = 0x02
+ PAGE_USER_SUPERVISOR = 0x04
+ PAGE_WRITE_THROUGH = 0x08
+ PAGE_CACHE_DISABLE = 0x010
+ PAGE_ACCESSED = 0x020
+ PAGE_DIRTY = 0x040
+ PAGE_PAT = 0x080
+ PAGE_GLOBAL = 0x0100
+ PAGE_2M_MBO = 0x080
+ PAGE_2M_PAT = 0x01000
+
+ def NopAlign4k(s):
+ c = ((len(s) + 0xfff) & ~0xfff) - len(s)
+ return ('\x90' * c) + s
+
+ def PageDirectoryEntries4GbOf2MbPages(baseAddress):
+
+ s = ''
+ for i in range(0x800):
+ i = (
+ baseAddress + long(i << 21) +
+ PAGE_2M_MBO +
+ PAGE_CACHE_DISABLE +
+ PAGE_ACCESSED +
+ PAGE_DIRTY +
+ PAGE_READ_WRITE +
+ PAGE_PRESENT
+ )
+ s += pack('Q', i)
+ return s
+
+ def PageDirectoryPointerTable4GbOf2MbPages(pdeBase):
+ s = ''
+ for i in range(0x200):
+ i = (
+ pdeBase +
+ (min(i, 3) << 12) +
+ PAGE_CACHE_DISABLE +
+ PAGE_ACCESSED +
+ PAGE_READ_WRITE +
+ PAGE_PRESENT
+ )
+ s += pack('Q', i)
+ return s
+
+ def PageMapLevel4Table4GbOf2MbPages(pdptBase):
+ s = ''
+ for i in range(0x200):
+ i = (
+ pdptBase +
+ (min(i, 0) << 12) +
+ PAGE_CACHE_DISABLE +
+ PAGE_ACCESSED +
+ PAGE_READ_WRITE +
+ PAGE_PRESENT
+ )
+ s += pack('Q', i)
+ return s
+
+ def First4GbPageEntries(topAddress):
+ PDE = PageDirectoryEntries4GbOf2MbPages(0L)
+ pml4tBase = topAddress - 0x1000
+ pdptBase = pml4tBase - 0x1000
+ pdeBase = pdptBase - len(PDE)
+ PDPT = PageDirectoryPointerTable4GbOf2MbPages(pdeBase)
+ PML4T = PageMapLevel4Table4GbOf2MbPages(pdptBase)
+ return PDE + PDPT + PML4T
+
+ def AlignAndAddPageTables():
+ d = open(sys.argv[1], 'rb').read()
+ code = NopAlign4k(d)
+ topAddress = 0x100000000 - len(code)
+ d = ('\x90' * 4) + First4GbPageEntries(topAddress) + code
+ f = open(sys.argv[1], 'wb')
+ f.write(d)
+ f.close()
+
+ AlignAndAddPageTables()
+
diff --git a/IntelFspPkg/Include/Guid/GuidHobFsp.h b/IntelFspPkg/Include/Guid/GuidHobFsp.h new file mode 100644 index 0000000000..4b1c2b175e --- /dev/null +++ b/IntelFspPkg/Include/Guid/GuidHobFsp.h @@ -0,0 +1,22 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __GUID_HOB_FSP_GUID__
+#define __GUID_HOB_FSP_GUID__
+
+#include <Guid/GuidHobFspEas.h>
+#include <GuidHobFspGfx.h>
+#include <GuidHobFspTseg.h>
+#include <GuidHobFspMisc.h>
+
+#endif
diff --git a/IntelFspPkg/Include/Library/CacheAsRamLib.h b/IntelFspPkg/Include/Library/CacheAsRamLib.h new file mode 100644 index 0000000000..6f3d068b67 --- /dev/null +++ b/IntelFspPkg/Include/Library/CacheAsRamLib.h @@ -0,0 +1,30 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CACHE_AS_RAM_LIB_H_
+#define _CACHE_AS_RAM_LIB_H_
+
+/**
+ This function disable CAR.
+
+ @param[in] DisableCar TRUE means use INVD, FALSE means use WBINVD
+
+**/
+VOID
+EFIAPI
+DisableCacheAsRam (
+ IN BOOLEAN DisableCar
+ );
+
+#endif
+
diff --git a/IntelFspPkg/Include/Library/CacheLib.h b/IntelFspPkg/Include/Library/CacheLib.h new file mode 100644 index 0000000000..909ae928f1 --- /dev/null +++ b/IntelFspPkg/Include/Library/CacheLib.h @@ -0,0 +1,62 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CACHE_LIB_H_
+#define _CACHE_LIB_H_
+
+//
+// EFI_MEMORY_CACHE_TYPE
+//
+typedef INT32 EFI_MEMORY_CACHE_TYPE;
+
+#define EFI_CACHE_UNCACHEABLE 0
+#define EFI_CACHE_WRITECOMBINING 1
+#define EFI_CACHE_WRITETHROUGH 4
+#define EFI_CACHE_WRITEPROTECTED 5
+#define EFI_CACHE_WRITEBACK 6
+
+/**
+ Reset all the MTRRs to a known state.
+
+ @retval EFI_SUCCESS All MTRRs have been reset successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ResetCacheAttributes (
+ VOID
+ );
+
+/**
+ Given the memory range and cache type, programs the MTRRs.
+
+ @param[in] MemoryAddress Base Address of Memory to program MTRR.
+ @param[in] MemoryLength Length of Memory to program MTRR.
+ @param[in] MemoryCacheType Cache Type.
+
+ @retval EFI_SUCCESS Mtrr are set successfully.
+ @retval EFI_LOAD_ERROR No empty MTRRs to use.
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+ @retval others An error occurs when setting MTTR.
+
+**/
+EFI_STATUS
+EFIAPI
+SetCacheAttributes (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+#endif
+
diff --git a/IntelFspPkg/Include/Library/DebugDeviceLib.h b/IntelFspPkg/Include/Library/DebugDeviceLib.h new file mode 100644 index 0000000000..5c35eda579 --- /dev/null +++ b/IntelFspPkg/Include/Library/DebugDeviceLib.h @@ -0,0 +1,29 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __DEBUG_DEVICE_LIB_H__
+#define __DEBUG_DEVICE_LIB_H__
+
+/**
+ Returns the debug print device enable state.
+
+ @return Debug print device enable state.
+
+**/
+UINT8
+EFIAPI
+GetDebugPrintDeviceEnable (
+ VOID
+ );
+
+#endif
diff --git a/IntelFspPkg/Include/Library/FspCommonLib.h b/IntelFspPkg/Include/Library/FspCommonLib.h new file mode 100644 index 0000000000..50e9b260bf --- /dev/null +++ b/IntelFspPkg/Include/Library/FspCommonLib.h @@ -0,0 +1,173 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_COMMON_LIB_H_
+#define _FSP_COMMON_LIB_H_
+
+#include <FspGlobalData.h>
+#include <FspMeasurePointId.h>
+
+/**
+ This function sets the FSP global data pointer.
+
+ @param[in] FspData Fsp global data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspGlobalDataPointer (
+ IN FSP_GLOBAL_DATA *FspData
+ );
+
+/**
+ This function gets the FSP global data pointer.
+
+**/
+FSP_GLOBAL_DATA *
+EFIAPI
+GetFspGlobalDataPointer (
+ VOID
+ );
+
+/**
+ This function gets back the FSP API paramter passed by the bootlaoder.
+
+ @retval ApiParameter FSP API paramter passed by the bootlaoder.
+**/
+UINT32
+EFIAPI
+GetFspApiParameter (
+ VOID
+ );
+
+/**
+ This function sets the FSP API paramter in the stack.
+
+ @param[in] Value New parameter value.
+
+**/
+VOID
+EFIAPI
+SetFspApiParameter (
+ IN UINT32 Value
+ );
+
+/**
+ This function sets the FSP continuation function parameters in the stack.
+
+ @param[in] Value New parameter value to set.
+ @param[in] Index Parameter index.
+**/
+VOID
+EFIAPI
+SetFspContinuationFuncParameter (
+ IN UINT32 Value,
+ IN UINT32 Index
+ );
+
+/**
+ This function changes the Bootloader return address in stack.
+
+ @param[in] ReturnAddress Address to return.
+
+**/
+VOID
+EFIAPI
+SetFspApiReturnAddress (
+ IN UINT32 ReturnAddress
+ );
+
+/**
+ This function set the API status code returned to the bootloader.
+
+ @param[in] ReturnStatus Status code to return.
+
+**/
+VOID
+EFIAPI
+SetFspApiReturnStatus (
+ IN UINT32 ReturnStatus
+ );
+
+/**
+ This function sets the context switching stack to a new stack frame.
+
+ @param[in] NewStackTop New core stack to be set.
+
+**/
+VOID
+EFIAPI
+SetFspCoreStackPointer (
+ IN VOID *NewStackTop
+ );
+
+/**
+ This function sets the platform specific data pointer.
+
+ @param[in] PlatformData Fsp platform specific data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspPlatformDataPointer (
+ IN VOID *PlatformData
+ );
+
+/**
+ This function gets the platform specific data pointer.
+
+ @param[in] PlatformData Fsp platform specific data pointer.
+
+**/
+VOID *
+EFIAPI
+GetFspPlatformDataPointer (
+ VOID
+ );
+
+/**
+ This function sets the UPD data pointer.
+
+ @param[in] UpdDataRgnPtr UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspUpdDataPointer (
+ IN VOID *UpdDataRgnPtr
+ );
+
+/**
+ This function gets the UPD data pointer.
+
+ @return UpdDataRgnPtr UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspUpdDataPointer (
+ VOID
+ );
+
+/**
+ Set FSP measurement point timestamp.
+
+ @param[in] Id Measurement point ID.
+
+ @return performance timestamp.
+**/
+UINT64
+EFIAPI
+SetFspMeasurePoint (
+ IN UINT8 Id
+ );
+
+#endif
diff --git a/IntelFspPkg/Include/Library/FspPlatformLib.h b/IntelFspPkg/Include/Library/FspPlatformLib.h new file mode 100644 index 0000000000..855017880b --- /dev/null +++ b/IntelFspPkg/Include/Library/FspPlatformLib.h @@ -0,0 +1,64 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_PLATFORM_LIB_H_
+#define _FSP_PLATFORM_LIB_H_
+
+/**
+ Get system memory from HOB.
+
+ @param[in,out] LowMemoryLength less than 4G memory length
+ @param[in,out] HighMemoryLength greater than 4G memory length
+**/
+VOID
+EFIAPI
+FspGetSystemMemorySize (
+ IN OUT UINT64 *LowMemoryLength,
+ IN OUT UINT64 *HighMemoryLength
+ );
+
+/**
+ Migrate bootloader data before destroying CAR.
+
+**/
+VOID
+EFIAPI
+FspMigrateTemporaryMemory (
+ VOID
+ );
+
+/**
+ This function transfer control to the ContinuationFunc passed in by the
+ bootloader.
+
+**/
+VOID
+EFIAPI
+FspInitDone (
+ VOID
+ );
+
+/**
+ This function handle NotifyPhase API call from the bootloader.
+ It gives control back to the bootloader after it is handled. If the
+ Notification code is a ReadyToBoot event, this function will return
+ and FSP continues the remaining execution until it reaches the DxeIpl.
+
+**/
+VOID
+EFIAPI
+FspWaitForNotify (
+ VOID
+ );
+
+#endif
diff --git a/IntelFspPkg/Include/Library/FspReturnLib.h b/IntelFspPkg/Include/Library/FspReturnLib.h new file mode 100644 index 0000000000..40b69a8e53 --- /dev/null +++ b/IntelFspPkg/Include/Library/FspReturnLib.h @@ -0,0 +1,27 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_RETURN_LIB_H_
+#define _FSP_RETURN_LIB_H_
+
+/**
+ Return the control from FSP to the Caller.
+
+**/
+VOID
+EFIAPI
+AsmFspReturn (
+ VOID
+ );
+
+#endif
diff --git a/IntelFspPkg/Include/Library/FspSwitchStackLib.h b/IntelFspPkg/Include/Library/FspSwitchStackLib.h new file mode 100644 index 0000000000..e90b13e8da --- /dev/null +++ b/IntelFspPkg/Include/Library/FspSwitchStackLib.h @@ -0,0 +1,45 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_SWITCH_STACK_LIB_H_
+#define _FSP_SWITCH_STACK_LIB_H_
+
+/**
+
+ This funciton will switch the current stack to the previous saved stack.
+ Before calling the previous stack has to be set in FSP_GLOBAL_DATA.CoreStack.
+ EIP
+ FLAGS 16 bit FLAGS 16 bit
+ EDI
+ ESI
+ EBP
+ ESP
+ EBX
+ EDX
+ ECX
+ EAX
+ DWORD IDT base1
+ StackPointer: DWORD IDT base2
+
+ @return ReturnKey After switching to the saved stack,
+ this value will be saved in eax before returning.
+
+
+**/
+UINT32
+EFIAPI
+Pei2LoaderSwitchStack (
+ VOID
+ );
+
+#endif
diff --git a/IntelFspPkg/Include/Private/FspGlobalData.h b/IntelFspPkg/Include/Private/FspGlobalData.h new file mode 100644 index 0000000000..7a6ec6db58 --- /dev/null +++ b/IntelFspPkg/Include/Private/FspGlobalData.h @@ -0,0 +1,44 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_GLOBAL_DATA_H_
+#define _FSP_GLOBAL_DATA_H_
+
+#include <FspInfoHeader.h>
+
+#pragma pack(1)
+
+typedef struct {
+ VOID *DataPtr;
+ UINT32 CodeRegionBase;
+ UINT32 CodeRegionSize;
+ UINT32 MicorcodeRegionBase;
+ UINT32 MicorcodeRegionSize;
+} FSP_PLAT_DATA;
+
+#define FSP_GLOBAL_DATA_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'D')
+
+typedef struct {
+ UINT32 Signature;
+ UINT32 CoreStack;
+ FSP_PLAT_DATA PlatformData;
+ FSP_INFO_HEADER *FspInfoHeader;
+ VOID *UpdDataRgnPtr;
+ UINT32 PerfIdx;
+ UINT64 PerfData[32];
+// UINT64 PerfData[FixedPcdGet32(PcdFspMaxPerfEntry)];
+} FSP_GLOBAL_DATA;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFspPkg/Include/Private/FspMeasurePointId.h b/IntelFspPkg/Include/Private/FspMeasurePointId.h new file mode 100644 index 0000000000..765bd0b98b --- /dev/null +++ b/IntelFspPkg/Include/Private/FspMeasurePointId.h @@ -0,0 +1,48 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_MEASURE_POINT_ID_H_
+#define _FSP_MEASURE_POINT_ID_H_
+
+//
+// 0xD0 - 0xEF are reserved for FSP common measure point
+//
+#define FSP_PERF_ID_MRCINIT_ENTRY 0xD0
+#define FSP_PERF_ID_MRCINIT_EXIT (FSP_PERF_ID_MRCINIT_ENTRY + 1)
+
+#define FSP_PERF_ID_SOCINIT_ENTRY 0xD8
+#define FSP_PERF_ID_SOCINIT_EXIT (FSP_PERF_ID_SOCINIT_ENTRY + 1)
+
+#define FSP_PERF_ID_PCHINIT_ENTRY 0xDA
+#define FSP_PERF_ID_PCHINIT_EXIT (FSP_PERF_ID_PCHINIT_ENTRY + 1)
+
+#define FSP_PERF_ID_CPUINIT_ENTRY 0xE0
+#define FSP_PERF_ID_CPUINIT_EXIT (FSP_PERF_ID_CPUINIT_ENTRY + 1)
+
+
+//
+// 0xF0 - 0xFF are reserved for FSP API
+//
+#define FSP_PERF_ID_API_TMPRAMINIT_ENTRY 0xF0
+#define FSP_PERF_ID_API_TMPRAMINIT_EXIT (FSP_PERF_ID_API_TMPRAMINIT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_FSPINIT_ENTRY 0xF2
+#define FSP_PERF_ID_API_FSPINIT_EXIT (FSP_PERF_ID_API_FSPINIT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_NOTIFY_POSTPCI_ENTRY 0xF4
+#define FSP_PERF_ID_API_NOTIFY_POSTPCI_EXIT (FSP_PERF_ID_API_NOTIFY_POSTPCI_ENTRY + 1)
+
+#define FSP_PERF_ID_API_NOTIFY_RDYBOOT_ENTRY 0xF6
+#define FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT (FSP_PERF_ID_API_NOTIFY_RDYBOOT_ENTRY + 1)
+
+#endif
diff --git a/IntelFspPkg/Include/Private/FspPatchTable.h b/IntelFspPkg/Include/Private/FspPatchTable.h new file mode 100644 index 0000000000..ec93994fe7 --- /dev/null +++ b/IntelFspPkg/Include/Private/FspPatchTable.h @@ -0,0 +1,32 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FSP_PATCH_TABLE_H_
+#define _FSP_PATCH_TABLE_H_
+
+#pragma pack(1)
+
+#define FSP_PATCH_TABLE_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'P')
+
+typedef struct {
+ UINT32 Signature;
+ UINT16 HeaderLength;
+ UINT8 HeaderRevision;
+ UINT8 Reserved;
+ UINT32 PatchEntryNum;
+ UINT32 PatchData[FixedPcdGet32(PcdFspMaxPatchEntry)];
+} FSP_PATCH_TABLE;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFspPkg/Include/Private/GuidHobFspGfx.h b/IntelFspPkg/Include/Private/GuidHobFspGfx.h new file mode 100644 index 0000000000..4ac47ba939 --- /dev/null +++ b/IntelFspPkg/Include/Private/GuidHobFspGfx.h @@ -0,0 +1,19 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __GUID_HOB_FSP_GFX_GUID__
+#define __GUID_HOB_FSP_GFX_GUID__
+
+extern EFI_GUID gFspReservedMemoryResourceHobGfxGuid;
+
+#endif
diff --git a/IntelFspPkg/Include/Private/GuidHobFspMisc.h b/IntelFspPkg/Include/Private/GuidHobFspMisc.h new file mode 100644 index 0000000000..97b75af93e --- /dev/null +++ b/IntelFspPkg/Include/Private/GuidHobFspMisc.h @@ -0,0 +1,19 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __GUID_HOB_FSP_MISC_GUID__
+#define __GUID_HOB_FSP_MISC_GUID__
+
+extern EFI_GUID gFspReservedMemoryResourceHobMiscGuid;
+
+#endif
diff --git a/IntelFspPkg/Include/Private/GuidHobFspTseg.h b/IntelFspPkg/Include/Private/GuidHobFspTseg.h new file mode 100644 index 0000000000..a44a8f6e33 --- /dev/null +++ b/IntelFspPkg/Include/Private/GuidHobFspTseg.h @@ -0,0 +1,19 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __GUID_HOB_FSP_TSEG_GUID__
+#define __GUID_HOB_FSP_TSEG_GUID__
+
+extern EFI_GUID gFspReservedMemoryResourceHobTsegGuid;
+
+#endif
diff --git a/IntelFspPkg/IntelFspPkg.dec b/IntelFspPkg/IntelFspPkg.dec index ef942a7ac4..d16eaad346 100644 --- a/IntelFspPkg/IntelFspPkg.dec +++ b/IntelFspPkg/IntelFspPkg.dec @@ -21,11 +21,33 @@ [Includes]
Include
+ Include/Private
[Guids]
+ #
+ # GUID defined in package
+ #
+ gIntelFspPkgTokenSpaceGuid = { 0x834c0c5f, 0xadb3, 0x4372, { 0xae, 0xeb, 0x03, 0xe4, 0xe9, 0xe6, 0xc5, 0x91 } }
+
# Guid define in FSP EAS
gFspHeaderFileGuid = { 0x912740BE, 0x2284, 0x4734, { 0xB9, 0x71, 0x84, 0xB0, 0x27, 0x35, 0x3F, 0x0C } }
gFspBootLoaderTemporaryMemoryGuid = { 0xbbcff46c, 0xc8d3, 0x4113, { 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e } }
gFspReservedMemoryResourceHobGuid = { 0x69a79759, 0x1373, 0x4367, { 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } }
gFspNonVolatileStorageHobGuid = { 0x721acf02, 0x4d77, 0x4c2a, { 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0 } }
+ # Guid defined by platform
+ gFspReservedMemoryResourceHobTsegGuid = { 0xd038747c, 0xd00c, 0x4980, { 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55 } }
+ gFspReservedMemoryResourceHobGfxGuid = { 0x9c7c3aa7, 0x5332, 0x4917, { 0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07 } }
+ gFspReservedMemoryResourceHobMiscGuid = { 0x00d6b14b, 0x7dd0, 0x4062, { 0x88, 0x21, 0xe5, 0xf9, 0x6a, 0x2a, 0x1b, 0x00 } }
+
+[PcdsFixedAtBuild]
+ gIntelFspPkgTokenSpaceGuid.PcdGlobalDataPointerAddress|0xFED00108|UINT32|0x00000001
+ gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamBase |0xFEF00000|UINT32|0x10001001
+ gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamSize | 0x2000|UINT32|0x10001002
+ gIntelFspPkgTokenSpaceGuid.PcdFspTemporaryRamSize | 0x1000|UINT32|0x10001003
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry | 32|UINT32|0x00002001
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry | 5|UINT32|0x00002002
+
+[PcdsFixedAtBuild,PcdsDynamic,PcdsDynamicEx]
+ gIntelFspPkgTokenSpaceGuid.PcdFspReservedMemoryLength |0x00100000|UINT32|0x46530000
+ gIntelFspPkgTokenSpaceGuid.PcdBootLoaderEntry |0xFFFFFFE4|UINT32|0x46530100
diff --git a/IntelFspPkg/IntelFspPkg.dsc b/IntelFspPkg/IntelFspPkg.dsc new file mode 100644 index 0000000000..1f497ffa28 --- /dev/null +++ b/IntelFspPkg/IntelFspPkg.dsc @@ -0,0 +1,75 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ PLATFORM_NAME = IntelFspPkg
+ PLATFORM_GUID = 29C6791F-9EBC-4470-A126-2BB47431AE5E
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/IntelFspPkg
+ SUPPORTED_ARCHITECTURES = IA32
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+[LibraryClasses]
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+
+ # Dummy - test build only
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ DebugDeviceLib|IntelFspPkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf
+
+ # FSP override
+ DebugLib|IntelFspPkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf
+
+ # FSP specific lib
+ CacheAsRamLib|IntelFspPkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ CacheLib|IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf
+ FspCommonLib|IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ FspPlatformLib|IntelFspPkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ FspSwitchStackLib|IntelFspPkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+
+[LibraryClasses.common.PEIM]
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+
+[Components]
+ IntelFspPkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf
+ IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ IntelFspPkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf
+ IntelFspPkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ IntelFspPkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+
+ IntelFspPkg/FspSecCore/FspSecCore.inf {
+ <LibraryClasses>
+ NULL|IntelFspPkg/Library/SecPlatformSecLibNull/SecPlatformSecLibNull.inf
+ }
+ IntelFspPkg/FspDxeIpl/FspDxeIpl.inf
+
+[PcdsFixedAtBuild.common]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80080046
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
diff --git a/IntelFspPkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf b/IntelFspPkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf new file mode 100644 index 0000000000..7c8492cc4d --- /dev/null +++ b/IntelFspPkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf @@ -0,0 +1,30 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCacheAsRamLibNull
+ FILE_GUID = FBB4A01B-947E-4d82-B27D-1E207C070053
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CacheAsRamLib
+
+[sources.common]
+ DisableCacheAsRamNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+
diff --git a/IntelFspPkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c b/IntelFspPkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c new file mode 100644 index 0000000000..9b45163c34 --- /dev/null +++ b/IntelFspPkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c @@ -0,0 +1,41 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CacheAsRamLib.h>
+
+/**
+ This function disable CAR.
+
+ @param[in] DisableCar TRUE means use INVD, FALSE means use WBINVD
+
+**/
+VOID
+EFIAPI
+DisableCacheAsRam (
+ IN BOOLEAN DisableCar
+ )
+{
+ //
+ // Disable CAR
+ //
+
+ if (DisableCar) {
+ AsmInvd ();
+ } else {
+ AsmWbinvd();
+ }
+
+ return ;
+}
diff --git a/IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf b/IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf new file mode 100644 index 0000000000..d76a32bc4f --- /dev/null +++ b/IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf @@ -0,0 +1,32 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCacheLib
+ FILE_GUID = 01359d99-9446-456d-ada4-50a711c03adb
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CacheLib
+
+[sources.IA32]
+ CacheLib.c
+ CacheLibInternal.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+
diff --git a/IntelFspPkg/Library/BaseCacheLib/CacheLib.c b/IntelFspPkg/Library/BaseCacheLib/CacheLib.c new file mode 100644 index 0000000000..aaaeb8b97b --- /dev/null +++ b/IntelFspPkg/Library/BaseCacheLib/CacheLib.c @@ -0,0 +1,749 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CacheLib.h>
+#include <Library/CacheAsRamLib.h>
+#include "CacheLibInternal.h"
+
+/**
+ Calculate the maximum value which is a power of 2, but less the Input.
+
+ @param[in] Input The number to pass in.
+ @return The maximum value which is align to power of 2 and less the Input
+**/
+UINT32
+SetPower2 (
+ IN UINT32 Input
+ );
+
+/**
+ Search the memory cache type for specific memory from MTRR.
+
+ @param[in] MemoryAddress the address of target memory
+ @param[in] MemoryLength the length of target memory
+ @param[in] ValidMtrrAddressMask the MTRR address mask
+ @param[out] UsedMsrNum the used MSR number
+ @param[out] UsedMemoryCacheType the cache type for the target memory
+
+ @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
+ @retval EFI_NOT_FOUND The memory is not found in MTRR
+
+**/
+EFI_STATUS
+SearchForExactMtrr (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN UINT64 ValidMtrrAddressMask,
+ OUT UINT32 *UsedMsrNum,
+ OUT EFI_MEMORY_CACHE_TYPE *MemoryCacheType
+ );
+
+/**
+ Check if CacheType match current default setting.
+
+ @param[in] MemoryCacheType input cache type to be checked.
+
+ @retval TRUE MemoryCacheType is default MTRR setting.
+ @retval TRUE MemoryCacheType is NOT default MTRR setting.
+**/
+BOOLEAN
+IsDefaultType (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+/**
+ Return MTRR alignment requirement for base address and size.
+
+ @param[in] BaseAddress Base address.
+ @param[in] Size Size.
+
+ @retval Zero Alligned.
+ @retval Non-Zero Not alligned.
+
+**/
+UINT32
+CheckMtrrAlignment (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size
+ );
+
+typedef struct {
+ UINT32 Msr;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} EFI_FIXED_MTRR;
+
+EFI_FIXED_MTRR mFixedMtrrTable[] = {
+ { EFI_MSR_IA32_MTRR_FIX64K_00000, 0, 0x10000},
+ { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000},
+ { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000},
+ { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0xC0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0xC8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0xD0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0xD8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0xE0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0xE8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0xF0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0xF8000, 0x1000}
+};
+
+/**
+ Given the input, check if the number of MTRR is lesser.
+ if positive or subtractive.
+
+ @param[in] Input Length of Memory to program MTRR.
+
+ @retval Zero do positive.
+ @retval Non-Zero do subtractive.
+
+**/
+INT8
+CheckDirection (
+ IN UINT64 Input
+ )
+{
+ return 0;
+}
+
+/**
+ Disable cache and its mtrr.
+
+ @param[out] OldMtrr To return the Old MTRR value
+
+**/
+VOID
+EfiDisableCacheMtrr (
+ OUT UINT64 *OldMtrr
+ )
+{
+ UINT64 TempQword;
+
+ //
+ // Disable Cache MTRR
+ //
+ *OldMtrr = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword = (*OldMtrr) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE;
+ AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+ AsmDisableCache ();
+}
+
+/**
+ Recover cache MTRR.
+
+ @param[in] EnableMtrr Whether to enable the MTRR
+ @param[in] OldMtrr The saved old MTRR value to restore when not to enable the MTRR
+
+**/
+VOID
+EfiRecoverCacheMtrr (
+ IN BOOLEAN EnableMtrr,
+ IN UINT64 OldMtrr
+ )
+{
+ UINT64 TempQword;
+
+ //
+ // Enable Cache MTRR
+ //
+ if (EnableMtrr) {
+ TempQword = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword |= (B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE);
+ } else {
+ TempQword = OldMtrr;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+
+ AsmEnableCache ();
+}
+
+/**
+ Programming MTRR according to Memory address, length, and type.
+
+ @param[in] MtrrNumber the variable MTRR index number
+ @param[in] MemoryAddress the address of target memory
+ @param[in] MemoryLength the length of target memory
+ @param[in] MemoryCacheType the cache type of target memory
+ @param[in] ValidMtrrAddressMask the MTRR address mask
+
+**/
+VOID
+EfiProgramMtrr (
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT64 ValidMtrrAddressMask
+ )
+{
+ UINT64 TempQword;
+ UINT64 OldMtrr;
+
+ if (MemoryLength == 0) {
+ return;
+ }
+
+ EfiDisableCacheMtrr (&OldMtrr);
+
+ //
+ // MTRR Physical Base
+ //
+ TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType;
+ AsmWriteMsr64 (MtrrNumber, TempQword);
+
+ //
+ // MTRR Physical Mask
+ //
+ TempQword = ~(MemoryLength - 1);
+ AsmWriteMsr64 (MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID);
+
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+}
+
+/**
+ Calculate the maximum value which is a power of 2, but less the MemoryLength.
+
+ @param[in] MemoryAddress Memory address.
+ @param[in] MemoryLength The number to pass in.
+
+ @return The maximum value which is align to power of 2 and less the MemoryLength
+
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryAddress,
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+
+ if (MemoryLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute inital power of 2 size to return
+ //
+ if (RShiftU64(MemoryLength, 32)) {
+ Result = LShiftU64((UINT64)SetPower2((UINT32) RShiftU64(MemoryLength, 32)), 32);
+ } else {
+ Result = (UINT64)SetPower2((UINT32)MemoryLength);
+ }
+
+ //
+ // Special case base of 0 as all ranges are valid
+ //
+ if (MemoryAddress == 0) {
+ return Result;
+ }
+
+ //
+ // Loop till a value that can be mapped to this base address is found
+ //
+ while (CheckMtrrAlignment (MemoryAddress, Result) != 0) {
+ //
+ // Need to try the next smaller power of 2
+ //
+ Result = RShiftU64 (Result, 1);
+ }
+
+ return Result;
+}
+
+/**
+ Return MTRR alignment requirement for base address and size.
+
+ @param[in] BaseAddress Base address.
+ @param[in] Size Size.
+
+ @retval Zero Alligned.
+ @retval Non-Zero Not alligned.
+
+**/
+UINT32
+CheckMtrrAlignment (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size
+ )
+{
+ UINT32 ShiftedBase;
+ UINT32 ShiftedSize;
+
+ //
+ // Shift base and size right 12 bits to allow for larger memory sizes. The
+ // MTRRs do not use the first 12 bits so this is safe for now. Only supports
+ // up to 52 bits of physical address space.
+ //
+ ShiftedBase = (UINT32) RShiftU64 (BaseAddress, 12);
+ ShiftedSize = (UINT32) RShiftU64 (Size, 12);
+
+ //
+ // Return the results to the caller of the MOD
+ //
+ return ShiftedBase % ShiftedSize;
+}
+
+/**
+ Calculate the maximum value which is a power of 2, but less the Input.
+
+ @param[in] Input The number to pass in.
+
+ @return The maximum value which is align to power of 2 and less the Input.
+**/
+UINT32
+SetPower2 (
+ IN UINT32 Input
+ )
+{
+ UINT32 Result;
+
+ Result = 0;
+#if defined(__GCC__)
+ asm("bsr %1, \
+ %%eax; \
+ bts %%eax, \
+ %0;" :"=r"(Result) :
+ "r"(Input)
+ );
+#elif defined(_MSC_VER)
+ _asm {
+ bsr eax, Input
+ bts Result, eax
+ }
+#endif
+ return Result;
+}
+
+/**
+ Programs fixed MTRRs registers.
+
+ @param[in] MemoryCacheType The memory type to set.
+ @param[in] Base The base address of memory range.
+ @param[in] Length The length of memory range.
+
+ @retval RETURN_SUCCESS The cache type was updated successfully
+ @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
+ for the fixed MTRRs.
+
+**/
+EFI_STATUS
+ProgramFixedMtrr (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT64 *Base,
+ IN UINT64 *Len
+ )
+{
+ UINT32 MsrNum;
+ UINT32 ByteShift;
+ UINT64 TempQword;
+ UINT64 OrMask;
+ UINT64 ClearMask;
+
+ TempQword = 0;
+ OrMask = 0;
+ ClearMask = 0;
+
+ for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) {
+ if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&
+ (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))) {
+ break;
+ }
+ }
+ if (MsrNum == V_EFI_FIXED_MTRR_NUMBER ) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // We found the fixed MTRR to be programmed
+ //
+ for (ByteShift=0; ByteShift < 8; ByteShift++) {
+ if ( *Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {
+ break;
+ }
+ }
+ if (ByteShift == 8 ) {
+ return EFI_DEVICE_ERROR;
+ }
+ for (; ((ByteShift<8) && (*Len >= mFixedMtrrTable[MsrNum].Length));ByteShift++) {
+ OrMask |= LShiftU64((UINT64) MemoryCacheType, (UINT32) (ByteShift* 8));
+ ClearMask |= LShiftU64((UINT64) 0xFF, (UINT32) (ByteShift * 8));
+ *Len -= mFixedMtrrTable[MsrNum].Length;
+ *Base += mFixedMtrrTable[MsrNum].Length;
+ }
+ TempQword = AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & (~ClearMask | OrMask);
+ AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if there is a valid variable MTRR that overlaps the given range.
+
+ @param[in] Start Base Address of the range to check.
+ @param[in] End End address of the range to check.
+
+ @retval TRUE Mtrr overlap.
+ @retval FALSE Mtrr not overlap.
+**/
+BOOLEAN
+CheckMtrrOverlap (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End
+ )
+{
+ return FALSE;
+}
+
+/**
+ Given the memory range and cache type, programs the MTRRs.
+
+ @param[in] MemoryAddress Base Address of Memory to program MTRR.
+ @param[in] MemoryLength Length of Memory to program MTRR.
+ @param[in] MemoryCacheType Cache Type.
+
+ @retval EFI_SUCCESS Mtrr are set successfully.
+ @retval EFI_LOAD_ERROR No empty MTRRs to use.
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+ @retval others An error occurs when setting MTTR.
+
+**/
+EFI_STATUS
+EFIAPI
+SetCacheAttributes (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MsrNum, MsrNumEnd;
+ UINT64 TempQword;
+ UINT32 LastVariableMtrrForBios;
+ UINT64 OldMtrr;
+ UINT32 UsedMsrNum;
+ EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType;
+ UINT64 ValidMtrrAddressMask;
+ UINT32 Cpuid_RegEax;
+
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &Cpuid_RegEax, NULL, NULL, NULL);
+ if (Cpuid_RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Cpuid_RegEax, NULL, NULL, NULL);
+ ValidMtrrAddressMask = (LShiftU64((UINT64) 1, (Cpuid_RegEax & 0xFF)) - 1) & (~(UINT64)0x0FFF);
+ } else {
+ ValidMtrrAddressMask = (LShiftU64((UINT64) 1, 36) - 1) & (~(UINT64)0x0FFF);
+ }
+
+ //
+ // Check for invalid parameter
+ //
+ if ((MemoryAddress & ~ValidMtrrAddressMask) != 0 || (MemoryLength & ~ValidMtrrAddressMask) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MemoryLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (MemoryCacheType) {
+ case EFI_CACHE_UNCACHEABLE:
+ case EFI_CACHE_WRITECOMBINING:
+ case EFI_CACHE_WRITETHROUGH:
+ case EFI_CACHE_WRITEPROTECTED:
+ case EFI_CACHE_WRITEBACK:
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if Fixed MTRR
+ //
+ if ((MemoryAddress + MemoryLength) <= (1 << 20)) {
+ Status = EFI_SUCCESS;
+ EfiDisableCacheMtrr (&OldMtrr);
+ while ((MemoryLength > 0) && (Status == EFI_SUCCESS)) {
+ Status = ProgramFixedMtrr (MemoryCacheType, &MemoryAddress, &MemoryLength);
+ }
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+ return Status;
+ }
+
+ //
+ // Search if the range attribute has been set before
+ //
+ Status = SearchForExactMtrr(
+ MemoryAddress,
+ MemoryLength,
+ ValidMtrrAddressMask,
+ &UsedMsrNum,
+ &UsedMemoryCacheType
+ );
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Compare if it has the same type as current setting
+ //
+ if (UsedMemoryCacheType == MemoryCacheType) {
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Different type
+ //
+
+ //
+ // Check if the set type is the same as Default Type
+ //
+ if (IsDefaultType(MemoryCacheType)) {
+ //
+ // Clear the MTRR
+ //
+ AsmWriteMsr64(UsedMsrNum, 0);
+ AsmWriteMsr64(UsedMsrNum + 1, 0);
+
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Modify the MTRR type
+ //
+ EfiProgramMtrr(UsedMsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+#if 0
+ //
+ // @bug - Need to create memory map so that when checking for overlap we
+ // can determine if an overlap exists based on all caching requests.
+ //
+ // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE
+ //
+ if (MemoryCacheType == (AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE)) {
+ if (!CheckMtrrOverlap (MemoryAddress, MemoryAddress+MemoryLength-1)) {
+ return EFI_SUCCESS;
+ }
+ }
+#endif
+
+ //
+ // Find first unused MTRR
+ //
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
+ if ((AsmReadMsr64(MsrNum+1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0 ) {
+ break;
+ }
+ }
+
+ //
+ // Reserve 1 MTRR pair for OS.
+ //
+ LastVariableMtrrForBios = MsrNumEnd - 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2);
+ if (MsrNum > LastVariableMtrrForBios) {
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Special case for 1 MB base address
+ //
+ if (MemoryAddress == BASE_1MB) {
+ MemoryAddress = 0;
+ }
+
+ //
+ // Program MTRRs
+ //
+ TempQword = MemoryLength;
+
+ if (TempQword == Power2MaxMemory(MemoryAddress, TempQword)) {
+ EfiProgramMtrr(MsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+
+ } else {
+ //
+ // Fill in MTRRs with values. Direction can not be checked for this method
+ // as we are using WB as the default cache type and only setting areas to UC.
+ //
+ do {
+ //
+ // Do boundary check so we don't go past last MTRR register
+ // for BIOS use. Leave one MTRR pair for OS use.
+ //
+ if (MsrNum > LastVariableMtrrForBios) {
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Set next power of 2 region
+ //
+ MemoryLength = Power2MaxMemory(MemoryAddress, TempQword);
+ EfiProgramMtrr(MsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+ MemoryAddress += MemoryLength;
+ TempQword -= MemoryLength;
+ MsrNum += 2;
+ } while (TempQword != 0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset all the MTRRs to a known state.
+
+ @retval EFI_SUCCESS All MTRRs have been reset successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ResetCacheAttributes (
+ VOID
+ )
+{
+ UINT32 MsrNum, MsrNumEnd;
+ UINT16 Index;
+ UINT64 OldMtrr;
+ UINT64 CacheType;
+ BOOLEAN DisableCar;
+ Index = 0;
+ DisableCar = TRUE;
+
+ //
+ // Determine default cache type
+ //
+ CacheType = EFI_CACHE_UNCACHEABLE;
+
+ //
+ // Set default cache type
+ //
+ AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, CacheType);
+
+ //
+ // Disable CAR
+ //
+ DisableCacheAsRam (DisableCar);
+
+ EfiDisableCacheMtrr (&OldMtrr);
+
+ //
+ // Reset Fixed MTRRs
+ //
+ for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) {
+ AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, 0);
+ }
+
+ //
+ // Reset Variable MTRRs
+ //
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum++) {
+ AsmWriteMsr64 (MsrNum, 0);
+ }
+
+ //
+ // Enable Fixed and Variable MTRRs
+ //
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search the memory cache type for specific memory from MTRR.
+
+ @param[in] MemoryAddress the address of target memory
+ @param[in] MemoryLength the length of target memory
+ @param[in] ValidMtrrAddressMask the MTRR address mask
+ @param[out] UsedMsrNum the used MSR number
+ @param[out] UsedMemoryCacheType the cache type for the target memory
+
+ @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
+ @retval EFI_NOT_FOUND The memory is not found in MTRR
+
+**/
+EFI_STATUS
+SearchForExactMtrr (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN UINT64 ValidMtrrAddressMask,
+ OUT UINT32 *UsedMsrNum,
+ OUT EFI_MEMORY_CACHE_TYPE *UsedMemoryCacheType
+ )
+{
+ UINT32 MsrNum, MsrNumEnd;
+ UINT64 TempQword;
+
+ if (MemoryLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
+ TempQword = AsmReadMsr64(MsrNum+1);
+ if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
+ continue;
+ }
+
+ if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) {
+ continue;
+ }
+
+ TempQword = AsmReadMsr64 (MsrNum);
+ if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) {
+ continue;
+ }
+
+ *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE)(TempQword & B_EFI_MSR_CACHE_MEMORY_TYPE);
+ *UsedMsrNum = MsrNum;
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Check if CacheType match current default setting.
+
+ @param[in] MemoryCacheType input cache type to be checked.
+
+ @retval TRUE MemoryCacheType is default MTRR setting.
+ @retval TRUE MemoryCacheType is NOT default MTRR setting.
+**/
+BOOLEAN
+IsDefaultType (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ )
+{
+ if ((AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE) != MemoryCacheType) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/IntelFspPkg/Library/BaseCacheLib/CacheLibInternal.h b/IntelFspPkg/Library/BaseCacheLib/CacheLibInternal.h new file mode 100644 index 0000000000..fbbf551dde --- /dev/null +++ b/IntelFspPkg/Library/BaseCacheLib/CacheLibInternal.h @@ -0,0 +1,59 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CACHE_LIB_INTERNAL_H_
+#define _CACHE_LIB_INTERNAL_H_
+
+#define EFI_MSR_CACHE_VARIABLE_MTRR_BASE 0x00000200
+#define EFI_MSR_CACHE_VARIABLE_MTRR_END 0x0000020F
+#define V_EFI_FIXED_MTRR_NUMBER 11
+
+#define EFI_MSR_IA32_MTRR_FIX64K_00000 0x00000250
+#define EFI_MSR_IA32_MTRR_FIX16K_80000 0x00000258
+#define EFI_MSR_IA32_MTRR_FIX16K_A0000 0x00000259
+#define EFI_MSR_IA32_MTRR_FIX4K_C0000 0x00000268
+#define EFI_MSR_IA32_MTRR_FIX4K_C8000 0x00000269
+#define EFI_MSR_IA32_MTRR_FIX4K_D0000 0x0000026A
+#define EFI_MSR_IA32_MTRR_FIX4K_D8000 0x0000026B
+#define EFI_MSR_IA32_MTRR_FIX4K_E0000 0x0000026C
+#define EFI_MSR_IA32_MTRR_FIX4K_E8000 0x0000026D
+#define EFI_MSR_IA32_MTRR_FIX4K_F0000 0x0000026E
+#define EFI_MSR_IA32_MTRR_FIX4K_F8000 0x0000026F
+#define EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE 0x000002FF
+#define B_EFI_MSR_CACHE_MTRR_VALID BIT11
+#define B_EFI_MSR_GLOBAL_MTRR_ENABLE BIT11
+#define B_EFI_MSR_FIXED_MTRR_ENABLE BIT10
+#define B_EFI_MSR_CACHE_MEMORY_TYPE (BIT2 | BIT1 | BIT0)
+
+#define EFI_MSR_VALID_MASK 0xFFFFFFFFF
+#define EFI_CACHE_VALID_ADDRESS 0xFFFFFF000
+#define EFI_SMRR_CACHE_VALID_ADDRESS 0xFFFFF000
+#define EFI_CACHE_VALID_EXTENDED_ADDRESS 0xFFFFFFFFFF000
+
+// Leave one MTRR pairs for OS use
+#define EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS 1
+#define EFI_CACHE_LAST_VARIABLE_MTRR_FOR_BIOS (EFI_MSR_CACHE_VARIABLE_MTRR_END) - \
+ (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2)
+
+#define EFI_MSR_IA32_MTRR_CAP 0x000000FE
+#define B_EFI_MSR_IA32_MTRR_CAP_EMRR_SUPPORT BIT12
+#define B_EFI_MSR_IA32_MTRR_CAP_SMRR_SUPPORT BIT11
+#define B_EFI_MSR_IA32_MTRR_CAP_WC_SUPPORT BIT10
+#define B_EFI_MSR_IA32_MTRR_CAP_FIXED_SUPPORT BIT8
+#define B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008
+#define CPUID_EXTENDED_FUNCTION 0x80000000
+
+#endif
+
diff --git a/IntelFspPkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf b/IntelFspPkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf new file mode 100644 index 0000000000..58930bd82a --- /dev/null +++ b/IntelFspPkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf @@ -0,0 +1,34 @@ +## @file
+# Debug device library instance that retrieves the current enabling state for
+# the platform debug output device.
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseDebugDeviceLibNull
+ FILE_GUID = 455D16DC-E3AF-4b5f-A9AD-A4BC198085BD
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugDeviceLib
+
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ DebugDeviceLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
diff --git a/IntelFspPkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c b/IntelFspPkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c new file mode 100644 index 0000000000..95c100472c --- /dev/null +++ b/IntelFspPkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c @@ -0,0 +1,31 @@ +/** @file
+ Debug device library instance that retrieves the current enabling state for
+ the platform debug output device.
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+
+/**
+ Returns the debug print device enable state.
+
+ @return Debug print device enable state.
+
+**/
+UINT8
+EFIAPI
+GetDebugPrintDeviceEnable (
+ VOID
+ )
+{
+ return 1;
+}
diff --git a/IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf b/IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf new file mode 100644 index 0000000000..0fa8c6a2dc --- /dev/null +++ b/IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf @@ -0,0 +1,37 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspCommonLib
+ FILE_GUID = 54607F66-D728-448e-A282-49E0404A557F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspCommonLib
+
+[Sources]
+ FspCommonLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+
+[Pcd]
+ gIntelFspPkgTokenSpaceGuid.PcdGlobalDataPointerAddress
+
+[FixedPcd]
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry
diff --git a/IntelFspPkg/Library/BaseFspCommonLib/FspCommonLib.c b/IntelFspPkg/Library/BaseFspCommonLib/FspCommonLib.c new file mode 100644 index 0000000000..958a7322a0 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspCommonLib/FspCommonLib.c @@ -0,0 +1,318 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <FspGlobalData.h>
+#include <FspApi.h>
+
+#pragma pack(1)
+
+//
+// Cont Func Parameter 2 +0x3C
+// Cont Func Parameter 1 +0x38
+//
+// API Parameter +0x34
+// API return address +0x30
+//
+// push offset exit +0x2C
+// pushfd +0x28
+// cli
+// pushad +0x24
+// sub esp, 8 +0x00
+// sidt fword ptr [esp]
+//
+typedef struct {
+ UINT16 IdtrLimit;
+ UINT32 IdtrBase;
+ UINT16 Reserved;
+ UINT32 Edi;
+ UINT32 Esi;
+ UINT32 Ebp;
+ UINT32 Esp;
+ UINT32 Ebx;
+ UINT32 Edx;
+ UINT32 Ecx;
+ UINT32 Eax;
+ UINT16 Flags[2];
+ UINT32 ExitOff;
+ UINT32 ApiRet;
+ UINT32 ApiParam;
+} CONTEXT_STACK;
+
+#define CONTEXT_STACK_OFFSET(x) (UINT32)&((CONTEXT_STACK *)(UINTN)0)->x
+
+#pragma pack()
+
+/**
+ This function sets the FSP global data pointer.
+
+ @param[in] FspData Fsp global data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspGlobalDataPointer (
+ IN FSP_GLOBAL_DATA *FspData
+ )
+{
+ ASSERT (FspData != NULL);
+ *((volatile UINT32 *)(UINTN)PcdGet32(PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;
+}
+
+/**
+ This function gets the FSP global data pointer.
+
+**/
+FSP_GLOBAL_DATA *
+EFIAPI
+GetFspGlobalDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = *(FSP_GLOBAL_DATA **)(UINTN)PcdGet32(PcdGlobalDataPointerAddress);
+ return FspData;
+}
+
+/**
+ This function gets back the FSP API paramter passed by the bootlaoder.
+
+ @retval ApiParameter FSP API paramter passed by the bootlaoder.
+**/
+UINT32
+EFIAPI
+GetFspApiParameter (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam));
+}
+
+/**
+ This function sets the FSP API paramter in the stack.
+
+ @param[in] Value New parameter value.
+
+**/
+VOID
+EFIAPI
+SetFspApiParameter (
+ IN UINT32 Value
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam)) = Value;
+}
+
+/**
+ This function sets the FSP continuation function parameters in the stack.
+
+ @param[in] Value New parameter value to set.
+ @param[in] Index Parameter index.
+**/
+VOID
+EFIAPI
+SetFspContinuationFuncParameter (
+ IN UINT32 Value,
+ IN UINT32 Index
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam) + (Index + 1) * sizeof(UINT32)) = Value;
+}
+
+
+/**
+ This function changes the Bootloader return address in stack.
+
+ @param[in] ReturnAddress Address to return.
+
+**/
+VOID
+EFIAPI
+SetFspApiReturnAddress (
+ IN UINT32 ReturnAddress
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiRet)) = ReturnAddress;
+}
+
+/**
+ This function set the API status code returned to the bootloader.
+
+ @param[in] ReturnStatus Status code to return.
+
+**/
+VOID
+EFIAPI
+SetFspApiReturnStatus (
+ IN UINT32 ReturnStatus
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(Eax)) = ReturnStatus;
+}
+
+/**
+ This function sets the context switching stack to a new stack frame.
+
+ @param[in] NewStackTop New core stack to be set.
+
+**/
+VOID
+EFIAPI
+SetFspCoreStackPointer (
+ IN VOID *NewStackTop
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+ UINT32 *OldStack;
+ UINT32 *NewStack;
+ UINT32 StackContextLen;
+
+ FspData = GetFspGlobalDataPointer ();
+ StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINT32);
+
+ //
+ // Reserve space for the ContinuationFunc two parameters
+ //
+ OldStack = (UINT32 *)FspData->CoreStack;
+ NewStack = (UINT32 *)NewStackTop - StackContextLen - 2;
+ FspData->CoreStack = (UINT32)NewStack;
+ while (StackContextLen-- != 0) {
+ *NewStack++ = *OldStack++;
+ }
+}
+
+/**
+ This function sets the platform specific data pointer.
+
+ @param[in] PlatformData Fsp platform specific data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspPlatformDataPointer (
+ IN VOID *PlatformData
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ FspData->PlatformData.DataPtr = PlatformData;
+}
+
+
+/**
+ This function gets the platform specific data pointer.
+
+ @param[in] PlatformData Fsp platform specific data pointer.
+
+**/
+VOID *
+EFIAPI
+GetFspPlatformDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return FspData->PlatformData.DataPtr;
+}
+
+
+/**
+ This function sets the UPD data pointer.
+
+ @param[in] UpdDataRgnPtr UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspUpdDataPointer (
+ IN VOID *UpdDataRgnPtr
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ //
+ // Get the Fsp Global Data Pointer
+ //
+ FspData = GetFspGlobalDataPointer ();
+
+ //
+ // Set the UPD pointer.
+ //
+ FspData->UpdDataRgnPtr = UpdDataRgnPtr;
+}
+
+/**
+ This function gets the UPD data pointer.
+
+ @return UpdDataRgnPtr UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspUpdDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return FspData->UpdDataRgnPtr;
+}
+
+/**
+ Set FSP measurement point timestamp.
+
+ @param[in] Id Measurement point ID.
+
+ @return performance timestamp.
+**/
+UINT64
+EFIAPI
+SetFspMeasurePoint (
+ IN UINT8 Id
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ //
+ // Bit [55: 0] will be the timestamp
+ // Bit [63:56] will be the ID
+ //
+ FspData = GetFspGlobalDataPointer ();
+ if (FspData->PerfIdx < sizeof(FspData->PerfData) / sizeof(FspData->PerfData[0])) {
+ FspData->PerfData[FspData->PerfIdx] = AsmReadTsc ();
+ ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;
+ }
+
+ return FspData->PerfData[(FspData->PerfIdx)++];
+}
diff --git a/IntelFspPkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf new file mode 100644 index 0000000000..d3df6c3de3 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf @@ -0,0 +1,49 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspDebugLibSerialPort
+ FILE_GUID = BB83F95F-EDBC-4884-A520-CD42AF388FAE
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugLib
+
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ DebugLib.c
+
+[Sources.Ia32]
+ Ia32/FspDebug.asm | MSFT
+ Ia32/FspDebug.s | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ SerialPortLib
+ BaseMemoryLib
+ PcdLib
+ PrintLib
+ BaseLib
+ DebugDeviceLib
+ DebugPrintErrorLevelLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
+
diff --git a/IntelFspPkg/Library/BaseFspDebugLibSerialPort/DebugLib.c b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/DebugLib.c new file mode 100644 index 0000000000..467d59db0e --- /dev/null +++ b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/DebugLib.c @@ -0,0 +1,305 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/DebugDeviceLib.h>
+#include <Library/DebugPrintErrorLevelLib.h>
+
+//
+// Define the maximum debug and assert message length that this library supports
+//
+#define MAX_DEBUG_MESSAGE_LENGTH 0x100
+
+CONST CHAR8 *mHexTable = "0123456789ABCDEF";
+
+/**
+ Get stack frame pointer of function call.
+
+ @return StackFramePointer stack frame pointer of function call.
+**/
+UINT32 *
+EFIAPI
+GetStackFramePointer (
+ VOID
+ );
+
+
+/**
+ Prints a debug message to the debug output device if the specified error level is enabled.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and the
+ associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format Format string for the debug message to print.
+ @param ... Variable argument list whose contents are accessed
+ based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+DebugPrint (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ ...
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ VA_LIST Marker;
+
+ //
+ // If Format is NULL, then ASSERT().
+ //
+ if (!GetDebugPrintDeviceEnable ()) {
+ return;
+ }
+
+ //
+ // Check driver debug mask value and global mask
+ //
+ if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
+ return;
+ }
+
+ //
+ // If Format is NULL, then ASSERT().
+ //
+ ASSERT (Format != NULL);
+
+ //
+ // Convert the DEBUG() message to an ASCII String
+ //
+ VA_START (Marker, Format);
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
+ VA_END (Marker);
+
+ //
+ // Send the print string to a Serial Port
+ //
+ SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
+}
+
+/**
+ Convert an UINT32 value into HEX string sepcified by Buffer.
+
+ @param Value The HEX value to convert to string
+ @param Buffer The pointer to the target buffer to be filled with HEX string
+
+**/
+VOID
+FillHex (
+ UINT32 Value,
+ CHAR8 *Buffer
+ )
+{
+ INTN Idx;
+ for (Idx = 7; Idx >= 0; Idx--) {
+ Buffer[Idx] = mHexTable[Value & 0x0F];
+ Value >>= 4;
+ }
+}
+
+/**
+ Prints an assert message containing a filename, line number, and description.
+ This may be followed by a breakpoint or a dead loop.
+
+ Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
+ to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
+ PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
+ DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
+ CpuDeadLoop() is called. If neither of these bits are set, then this function
+ returns immediately after the message is printed to the debug output device.
+ DebugAssert() must actively prevent recursion. If DebugAssert() is called while
+ processing another DebugAssert(), then DebugAssert() must return immediately.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+**/
+VOID
+DebugAssertInternal (
+ VOID
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ UINT32 *Frame;
+
+ Frame = (UINT32 *)GetStackFramePointer ();
+
+ //
+ // Generate the ASSERT() message in Ascii format
+ //
+ AsciiStrCpy (Buffer, "-> EBP:0x00000000 EIP:0x00000000\n");
+ SerialPortWrite ((UINT8 *)"ASSERT DUMP:\n", 13);
+ while (Frame != NULL) {
+ FillHex ((UINT32)Frame, Buffer + 9);
+ FillHex (Frame[1], Buffer + 9 + 8 + 8);
+ SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
+ if ((Frame[0] > (UINT32)Frame) && (Frame[0] < (UINT32)Frame + 0x00100000)) {
+ Frame = (UINT32 *)Frame[0];
+ } else {
+ Frame = NULL;
+ }
+ }
+
+ //
+ // Dead loop
+ //
+ CpuDeadLoop ();
+}
+
+/**
+ Prints an assert message containing a filename, line number, and description.
+ This may be followed by a breakpoint or a dead loop.
+
+ Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
+ to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
+ PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
+ DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
+ CpuDeadLoop() is called. If neither of these bits are set, then this function
+ returns immediately after the message is printed to the debug output device.
+ DebugAssert() must actively prevent recursion. If DebugAssert() is called while
+ processing another DebugAssert(), then DebugAssert() must return immediately.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+ @param FileName The pointer to the name of the source file that generated the assert condition.
+ @param LineNumber The line number in the source file that generated the assert condition
+ @param Description The pointer to the description of the assert condition.
+
+**/
+VOID
+EFIAPI
+DebugAssert (
+ IN CONST CHAR8 *FileName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *Description
+ )
+{
+ DebugAssertInternal ();
+}
+
+
+/**
+ Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
+
+ This function fills Length bytes of Buffer with the value specified by
+ PcdDebugClearMemoryValue, and returns Buffer.
+
+ If Buffer is NULL, then ASSERT().
+ If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+ @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
+ @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
+
+ @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.
+
+**/
+VOID *
+EFIAPI
+DebugClearMemory (
+ OUT VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ return Buffer;
+}
+
+
+/**
+ Returns TRUE if ASSERT() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugAssertEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPrintEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
+}
+
+/**
+ Returns TRUE if DEBUG_CODE() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugCodeEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugClearMemoryEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
+}
diff --git a/IntelFspPkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.asm b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.asm new file mode 100644 index 0000000000..8ac18ec4ec --- /dev/null +++ b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.asm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+; FSP Debug functions
+;
+;------------------------------------------------------------------------------
+
+ .386
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; UINT32 *
+; EFIAPI
+; GetStackFramePointer (
+; VOID
+; );
+;------------------------------------------------------------------------------
+GetStackFramePointer PROC PUBLIC
+ mov eax, ebp
+ ret
+GetStackFramePointer ENDP
+
+ END
diff --git a/IntelFspPkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.s b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.s new file mode 100644 index 0000000000..0f8475fa62 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.s @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Abstract:
+#
+# FSP Debug functions
+#
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# UINT32 *
+# EFIAPI
+# GetStackFramePointer (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(GetStackFramePointer)
+ASM_PFX(GetStackFramePointer):
+ mov %ebp, %eax
+ ret
+
+
diff --git a/IntelFspPkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf b/IntelFspPkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf new file mode 100644 index 0000000000..debce76c30 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf @@ -0,0 +1,41 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspPlatformLib
+ FILE_GUID = 7DECCDAF-361F-4ec1-9714-260BAAF6F384
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspPlatformLib
+
+[Sources]
+ FspPlatformMemory.c
+ FspPlatformNotify.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+
+[Pcd]
+ gIntelFspPkgTokenSpaceGuid.PcdGlobalDataPointerAddress
+ gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamBase
+ gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamSize
+ gIntelFspPkgTokenSpaceGuid.PcdFspTemporaryRamSize
+
+[FixedPcd]
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry
diff --git a/IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformMemory.c b/IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformMemory.c new file mode 100644 index 0000000000..2f1c0b14e5 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformMemory.c @@ -0,0 +1,155 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/FspCommonLib.h>
+#include <Guid/GuidHobFsp.h>
+#include <FspGlobalData.h>
+#include <FspApi.h>
+
+/**
+ Get system memory from HOB.
+
+ @param[in,out] LowMemoryLength less than 4G memory length
+ @param[in,out] HighMemoryLength greater than 4G memory length
+**/
+VOID
+EFIAPI
+FspGetSystemMemorySize (
+ IN OUT UINT64 *LowMemoryLength,
+ IN OUT UINT64 *HighMemoryLength
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ *HighMemoryLength = 0;
+ *LowMemoryLength = SIZE_1MB;
+ //
+ // Get the HOB list for processing
+ //
+ Hob.Raw = GetHobList ();
+
+ //
+ // Collect memory ranges
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ //
+ // Need memory above 1MB to be collected here
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB &&
+ Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) BASE_4GB) {
+ *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
+ } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) BASE_4GB) {
+ *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+}
+
+/**
+ Migrate bootloader data before destroying CAR.
+
+**/
+VOID
+EFIAPI
+FspMigrateTemporaryMemory (
+ VOID
+ )
+{
+ FSP_INIT_RT_COMMON_BUFFER *FspInitRtBuffer;
+ UINT32 BootLoaderTempRamStart;
+ UINT32 BootLoaderTempRamEnd;
+ UINT32 BootLoaderTempRamSize;
+ UINT32 OffsetGap;
+ UINT32 FspParamPtr;
+ FSP_INIT_PARAMS *FspInitParams;
+ UINT32 *NewStackTop;
+ VOID *BootLoaderTempRamHob;
+ VOID *UpdDataRgnPtr;
+ VOID *PlatformDataPtr;
+
+ //
+ // Get the temporary memory range used by the bootloader
+ //
+ BootLoaderTempRamStart = PcdGet32(PcdTemporaryRamBase);
+ BootLoaderTempRamSize = PcdGet32(PcdTemporaryRamSize) - PcdGet32(PcdFspTemporaryRamSize);
+ BootLoaderTempRamEnd = BootLoaderTempRamStart + BootLoaderTempRamSize;
+
+ //
+ // Build a Boot Loader Temporary Memory GUID HOB
+ //
+ BootLoaderTempRamHob = BuildGuidHob (&gFspBootLoaderTemporaryMemoryGuid, BootLoaderTempRamSize);
+ CopyMem (BootLoaderTempRamHob, (VOID *)BootLoaderTempRamStart, BootLoaderTempRamSize);
+ OffsetGap = (UINT32)BootLoaderTempRamHob - BootLoaderTempRamStart;
+
+ //
+ // Set a new stack frame for the continuation function
+ //
+ FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
+ FspInitRtBuffer = (FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr;
+ NewStackTop = (UINT32 *)FspInitRtBuffer->StackTop - 1;
+ SetFspCoreStackPointer (NewStackTop);
+
+ //
+ // Fix the FspInit Parameter Pointers to the new location.
+ //
+ FspParamPtr = GetFspApiParameter ();
+ if (FspParamPtr >= BootLoaderTempRamStart && FspParamPtr < BootLoaderTempRamEnd) {
+ SetFspApiParameter(FspParamPtr + OffsetGap);
+ }
+
+ FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
+ if ((UINT32)(FspInitParams->RtBufferPtr) >= BootLoaderTempRamStart &&
+ (UINT32)(FspInitParams->RtBufferPtr) < BootLoaderTempRamEnd) {
+ FspInitParams->RtBufferPtr = (VOID *)((UINT32)(FspInitParams->RtBufferPtr) + OffsetGap);
+ }
+
+ if ((UINT32)(FspInitParams->NvsBufferPtr) >= BootLoaderTempRamStart &&
+ (UINT32)(FspInitParams->NvsBufferPtr) < BootLoaderTempRamEnd) {
+ FspInitParams->NvsBufferPtr = (VOID *)((UINT32)(FspInitParams->NvsBufferPtr) + OffsetGap);
+ }
+
+ if ((UINT32)(((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr) >= BootLoaderTempRamStart &&
+ (UINT32)(((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr) < BootLoaderTempRamEnd) {
+ ((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr = \
+ (VOID *)((UINT32)(((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr) + OffsetGap);
+ }
+
+ //
+ // Update UPD pointer in FSP Global Data
+ //
+ UpdDataRgnPtr = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr)->UpdDataRgnPtr;
+ if (UpdDataRgnPtr != NULL) {
+ SetFspUpdDataPointer (UpdDataRgnPtr);
+ }
+
+ //
+ // Update Platform data pointer in FSP Global Data
+ //
+ PlatformDataPtr = GetFspPlatformDataPointer ();
+ if (((UINT32)PlatformDataPtr >= BootLoaderTempRamStart) &&
+ ((UINT32)PlatformDataPtr < BootLoaderTempRamEnd)) {
+ SetFspPlatformDataPointer ((UINT8 *)PlatformDataPtr + OffsetGap);
+ }
+
+}
diff --git a/IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformNotify.c b/IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformNotify.c new file mode 100644 index 0000000000..3488fbc61c --- /dev/null +++ b/IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformNotify.c @@ -0,0 +1,178 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/FspSwitchStackLib.h>
+#include <Library/FspCommonLib.h>
+#include <Guid/EventGroup.h>
+#include <FspApi.h>
+#include <Protocol/PciEnumerationComplete.h>
+
+EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEventReadyToBootGuid,
+ NULL
+};
+
+
+UINT32 mFspNotfifySequence[] = {
+ EnumInitPhaseAfterPciEnumeration,
+ EnumInitPhaseReadyToBoot
+};
+
+/**
+ Install FSP notification.
+
+ @param[in] NotificatonCode FSP notification code
+
+ @retval EFI_SUCCESS Notify FSP successfully
+ @retval EFI_INVALID_PARAMETER NotificatonCode is invalid
+
+**/
+EFI_STATUS
+EFIAPI
+FspNotificationHandler (
+ IN UINT32 NotificatonCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (NotificatonCode) {
+ case EnumInitPhaseAfterPciEnumeration:
+ //
+ // Do POST PCI initialization if needed
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));
+ PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);
+ break;
+
+ case EnumInitPhaseReadyToBoot:
+ //
+ // Ready To Boot
+ //
+ DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));
+ PeiServicesInstallPpi (&mPeiReadyToBootPpi);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ This function transfer control to the ContinuationFunc passed in by the
+ bootloader.
+
+**/
+VOID
+EFIAPI
+FspInitDone (
+ VOID
+ )
+{
+ FSP_INIT_PARAMS *FspInitParams;
+
+ FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
+
+ //
+ // Modify the parameters for ContinuationFunc
+ //
+ SetFspContinuationFuncParameter(EFI_SUCCESS, 0);
+ SetFspContinuationFuncParameter((UINT32)GetHobList(), 1);
+
+ //
+ // Modify the return address to ContinuationFunc
+ //
+ SetFspApiReturnAddress((UINT32)FspInitParams->ContinuationFunc);
+
+ //
+ // Give control back to the boot loader framework caller after FspInit is done
+ // It is done throught the continuation function
+ //
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_EXIT);
+ Pei2LoaderSwitchStack();
+}
+
+/**
+ This function handle NotifyPhase API call from the bootloader.
+ It gives control back to the bootloader after it is handled. If the
+ Notification code is a ReadyToBoot event, this function will return
+ and FSP continues the remaining execution until it reaches the DxeIpl.
+
+**/
+VOID
+FspWaitForNotify (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NotificatonValue;
+ UINT32 NotificatonCount;
+ UINT8 Count;
+
+ NotificatonCount = 0;
+ while (NotificatonCount < sizeof(mFspNotfifySequence) / sizeof(UINT32)) {
+
+ Count = (NotificatonCount << 1) & 0x07;
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_ENTRY + Count);
+
+ NotificatonValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;
+ DEBUG ((DEBUG_INFO, "FSP Got Notification. Notification Value : 0x%08X\n", NotificatonValue));
+
+ if (mFspNotfifySequence[NotificatonCount] != NotificatonValue) {
+ //
+ // Notify code does not follow the predefined order
+ //
+ SetFspApiReturnStatus(EFI_UNSUPPORTED);
+ } else {
+ //
+ // Process Notification and Give control back to the boot loader framework caller
+ //
+ Status = FspNotificationHandler (NotificatonValue);
+ SetFspApiReturnStatus(Status);
+ if (!EFI_ERROR(Status)) {
+ NotificatonCount++;
+ SetFspApiReturnStatus(EFI_SUCCESS);
+ if (NotificatonValue == EnumInitPhaseReadyToBoot) {
+ break;
+ }
+ }
+ }
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_EXIT + Count);
+ Pei2LoaderSwitchStack();
+ }
+
+ //
+ // Control goes back to the PEI Core and it dispatches further PEIMs.
+ // DXEIPL is the final one to transfer control back to the boot loader.
+ //
+}
+
diff --git a/IntelFspPkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf b/IntelFspPkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf new file mode 100644 index 0000000000..c3b47b5dbf --- /dev/null +++ b/IntelFspPkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf @@ -0,0 +1,42 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspSwitchStackLib
+ FILE_GUID = 8A5EA987-27F9-4ad0-B07C-D61882BFF4FF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspSwitchStackLib
+
+[Sources.IA32]
+ FspSwitchStackLib.c
+
+[Sources.IA32]
+ Ia32/Stack.asm | MSFT
+ Ia32/Stack.s | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFspPkg/IntelFspPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+
+[FixedPcd]
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry
+ gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry
+
+
+
diff --git a/IntelFspPkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c b/IntelFspPkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c new file mode 100644 index 0000000000..42a57a27c0 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c @@ -0,0 +1,42 @@ +/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/FspCommonLib.h>
+
+/**
+
+ Switch the current stack to the previous saved stack.
+
+ @param[in] NewStack The new stack to be switched.
+
+ @return OldStack After switching to the saved stack,
+ this value will be saved in eax before returning.
+
+
+**/
+UINT32
+SwapStack (
+ IN UINT32 NewStack
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+ UINT32 OldStack;
+
+ FspData = GetFspGlobalDataPointer ();
+ OldStack = FspData->CoreStack;
+ FspData->CoreStack = NewStack;
+ return OldStack;
+}
+
diff --git a/IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.asm b/IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.asm new file mode 100644 index 0000000000..d04f229a6b --- /dev/null +++ b/IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.asm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+; Switch the stack from temporary memory to permenent memory.
+;
+;------------------------------------------------------------------------------
+
+ .586p
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; Pei2LoaderSwitchStack (
+; VOID
+; )
+;------------------------------------------------------------------------------
+EXTERNDEF C MeasurePoint:PROC
+Pei2LoaderSwitchStack PROC C PUBLIC
+ jmp Loader2PeiSwitchStack
+Pei2LoaderSwitchStack ENDP
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; Loader2PeiSwitchStack (
+; VOID
+; )
+;------------------------------------------------------------------------------
+EXTERNDEF C SwapStack:PROC
+Loader2PeiSwitchStack PROC C PUBLIC
+ ; Save current contexts
+ push offset exit
+ pushfd
+ cli
+ pushad
+ sub esp, 8
+ sidt fword ptr [esp]
+
+ ; Load new stack
+ push esp
+ call SwapStack
+ mov esp, eax
+
+ ; Restore previous contexts
+ lidt fword ptr [esp]
+ add esp, 8
+ popad
+ popfd
+exit:
+ ret
+Loader2PeiSwitchStack ENDP
+
+ END
diff --git a/IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.s b/IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.s new file mode 100644 index 0000000000..6932cd8448 --- /dev/null +++ b/IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.s @@ -0,0 +1,64 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Abstract:
+#
+# Switch the stack from temporary memory to permenent memory.
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)
+ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)
+
+#------------------------------------------------------------------------------
+# UINT32
+# EFIAPI
+# Pei2LoaderSwitchStack (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)
+ASM_PFX(Pei2LoaderSwitchStack):
+ jmp ASM_PFX(Loader2PeiSwitchStack)
+
+#------------------------------------------------------------------------------
+# UINT32
+# EFIAPI
+# Loader2PeiSwitchStack (
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)
+ASM_PFX(Loader2PeiSwitchStack):
+#Save current contexts
+ push $exit
+ pushf
+ pushf
+ cli
+ pusha
+ push $0x0
+ push $0x0
+ sidt (%esp)
+
+ # Load new stack
+ push %esp
+ call ASM_PFX(SwapStack)
+ mov %eax,%esp
+
+ # Restore previous contexts
+ lidt (%esp)
+ add $8,%esp
+ popa
+ popf
+ popf
+exit:
+ ret
+
+
diff --git a/IntelFspPkg/Library/SecPlatformSecLibNull/PlatformSecLibNull.c b/IntelFspPkg/Library/SecPlatformSecLibNull/PlatformSecLibNull.c new file mode 100644 index 0000000000..af41a61813 --- /dev/null +++ b/IntelFspPkg/Library/SecPlatformSecLibNull/PlatformSecLibNull.c @@ -0,0 +1,29 @@ +/** @file
+ Null instance of Platform Sec Lib.
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+
+/**
+ This function provides dummy function so that SecCore can pass pass build
+ Validation in Ia32FamilyCpuPkg. All real platform library instances needs
+ to implement the real entry point in assembly.
+**/
+VOID
+EFIAPI
+_ModuleEntryPoint (
+ VOID
+ )
+{
+ return;
+}
diff --git a/IntelFspPkg/Library/SecPlatformSecLibNull/SecPlatformSecLibNull.inf b/IntelFspPkg/Library/SecPlatformSecLibNull/SecPlatformSecLibNull.inf new file mode 100644 index 0000000000..72006c585c --- /dev/null +++ b/IntelFspPkg/Library/SecPlatformSecLibNull/SecPlatformSecLibNull.inf @@ -0,0 +1,53 @@ +## @file
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecPlatformSecLibNull
+ FILE_GUID = 6695974D-968C-420b-80B9-7870CD20118F
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ PlatformSecLibNull.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+
diff --git a/IntelFspPkg/Tools/GenCfgOpt.py b/IntelFspPkg/Tools/GenCfgOpt.py new file mode 100644 index 0000000000..4417bc33fe --- /dev/null +++ b/IntelFspPkg/Tools/GenCfgOpt.py @@ -0,0 +1,894 @@ +## @ GenCfgOpt.py
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+import os
+import re
+import sys
+import struct
+from datetime import date
+
+# Generated file copyright header
+
+__copyright_txt__ = """## @file
+#
+# THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
+#
+# This file lists all VPD informations for a platform collected by build.exe.
+#
+# Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+"""
+
+__copyright_bsf__ = """/** @file
+
+ Boot Setting File for Platform Configuration.
+
+ Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ This file is automatically generated. Please do NOT modify !!!
+
+**/
+
+"""
+
+__copyright_h__ = """/** @file
+
+Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is automatically generated. Please do NOT modify !!!
+
+**/
+"""
+
+class CGenCfgOpt:
+ def __init__(self):
+ self.Error = ''
+
+ self._GlobalDataDef = """
+GlobalDataDef
+ SKUID = 0, "DEFAULT"
+EndGlobalData
+
+"""
+ self._BuidinOptionTxt = """
+List &EN_DIS
+ Selection 0x1 , "Enabled"
+ Selection 0x0 , "Disabled"
+EndList
+
+"""
+
+ self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']
+ self._HdrKeyList = ['HEADER','STRUCT']
+ self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}
+
+ self._MacroDict = {}
+ self._CfgBlkDict = {}
+ self._CfgPageDict = {}
+ self._CfgItemList = []
+ self._DscFile = ''
+ self._FvDir = ''
+ self._MapVer = 0
+
+ def ParseMacros (self, MacroDefStr):
+ # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
+ self._MacroDict = {}
+ IsExpression = False
+ for Macro in MacroDefStr:
+ if Macro.startswith('-D'):
+ IsExpression = True
+ if len(Macro) > 2:
+ Macro = Macro[2:]
+ else :
+ continue
+ if IsExpression:
+ IsExpression = False
+ Match = re.match("(\w+)=(.+)", Macro)
+ if Match:
+ self._MacroDict[Match.group(1)] = Match.group(2)
+ else:
+ Match = re.match("(\w+)", Macro)
+ if Match:
+ self._MacroDict[Match.group(1)] = ''
+ if len(self._MacroDict) == 0:
+ self.Error = "Invalid MACRO arguments"
+ Error = 1
+ else:
+ Error = 0
+ return Error
+
+
+ def ParseDscFile (self, DscFile, FvDir):
+ self._CfgItemList = []
+ self._CfgPageDict = {}
+ self._CfgBlkDict = {}
+ self._DscFile = DscFile
+ self._FvDir = FvDir
+
+ IsDefSect = False
+ IsUpdSect = False
+ IsVpdSect = False
+ Found = False
+
+ IfStack = [True]
+ ElifStack = []
+ Error = 0
+
+ DscFd = open(DscFile, "r")
+ DscLines = DscFd.readlines()
+ DscFd.close()
+
+ ConfigDict = {}
+
+ for DscLine in DscLines:
+ Handle = False
+ DscLine = DscLine.strip()
+ Match = re.match("^\[(.+)\]", DscLine)
+ if Match is not None:
+ if Match.group(1).lower() == "Defines".lower():
+ IsDefSect = True
+ IsVpdSect = False
+ IsUpdSect = False
+ elif Match.group(1).lower() == "PcdsDynamicVpd".lower():
+ ConfigDict = {}
+ ConfigDict['header'] = 'ON'
+ ConfigDict['region'] = 'VPD'
+ ConfigDict['order'] = -1
+ ConfigDict['page'] = ''
+ ConfigDict['name'] = ''
+ ConfigDict['find'] = ''
+ ConfigDict['struct'] = ''
+ ConfigDict['subreg'] = []
+ IsDefSect = False
+ IsVpdSect = True
+ IsUpdSect = False
+ elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
+ ConfigDict = {}
+ ConfigDict['header'] = 'ON'
+ ConfigDict['region'] = 'UPD'
+ ConfigDict['order'] = -1
+ ConfigDict['page'] = ''
+ ConfigDict['name'] = ''
+ ConfigDict['find'] = ''
+ ConfigDict['struct'] = ''
+ ConfigDict['subreg'] = []
+ IsDefSect = False
+ IsUpdSect = True
+ IsVpdSect = False
+ Found = True
+ else:
+ IsDefSect = False
+ IsUpdSect = False
+ IsVpdSect = False
+ else:
+ if IsDefSect or IsUpdSect or IsVpdSect:
+ if DscLine == "!else":
+ IfStack[-1] = not IfStack[-1]
+ elif DscLine == "!endif":
+ IfStack.pop()
+ Level = ElifStack.pop()
+ while Level > 0:
+ IfStack.pop()
+ Level = Level - 1
+ else:
+ Result = False
+ Match = re.match("!(ifdef|ifndef)\s+\$\((\w+)\)", DscLine)
+ if Match is not None:
+ if Match.group(2) in self._MacroDict:
+ if Match.group(1) == 'ifdef':
+ Result = True
+ else:
+ if Match.group(1) == 'ifndef':
+ Result = True
+ ElifStack.append(0)
+ IfStack.append(Result)
+ else:
+ Match = re.match("!(if|elseif)\s+\$\\((\w+)\)\s*==\s*(\w+|\$\(\w+\))", DscLine)
+ if Match is not None:
+ if Match.group(2) in self._MacroDict:
+ MacroName = self._MacroDict[Match.group(2)]
+ else:
+ MacroName = ''
+ Value = Match.group(3)
+ if Value.startswith('$'):
+ if Value[2:-1] in self._MacroDict:
+ Value = self._MacroDict[Value[2:-1]]
+ else:
+ Value = ''
+ if MacroName == Value:
+ Result = True
+ if Match.group(1) == "if":
+ ElifStack.append(0)
+ IfStack.append(Result)
+ else: #elseif
+ IfStack[-1] = not IfStack[-1]
+ IfStack.append(Result)
+ ElifStack[-1] = ElifStack[-1] + 1
+ else:
+ if len(DscLine) > 0 and DscLine[0] == '!':
+ self.Error = "Invalid DscLine '%s'" % DscLine
+ Error = 3
+ break;
+ else:
+ if reduce(lambda x,y: x and y, IfStack):
+ Handle = True
+
+ if not Handle:
+ continue
+
+ if IsDefSect:
+ #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
+ Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", DscLine)
+ if Match:
+ self._MacroDict[Match.group(1)] = Match.group(2)
+ else:
+ Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)
+ if Match:
+ Remaining = Match.group(2)
+ if Match.group(1) == 'BSF':
+ Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)
+ if Match:
+ # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
+ PageList = Match.group(1).split(',')
+ for Page in PageList:
+ Page = Page.strip()
+ Match = re.match("(\w+):\"(.+)\"", Page)
+ self._CfgPageDict[Match.group(1)] = Match.group(2)
+
+ Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)
+ if Match:
+ self._CfgBlkDict['name'] = Match.group(1)
+ self._CfgBlkDict['ver'] = Match.group(2)
+
+ for Key in self._BsfKeyList:
+ Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
+ if Match:
+ if Key in ['HELP', 'OPTION'] and Match.group(1).startswith('+'):
+ ConfigDict[Key.lower()] += Match.group(1)[1:]
+ else:
+ ConfigDict[Key.lower()] = Match.group(1)
+ else:
+ for Key in self._HdrKeyList:
+ Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
+ if Match:
+ ConfigDict[Key.lower()] = Match.group(1)
+
+ # Check VPD/UPD
+ if IsUpdSect:
+ Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]{4})\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
+ else:
+ Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)
+ if Match:
+ ConfigDict['space'] = Match.group(1)
+ ConfigDict['cname'] = Match.group(2)
+ ConfigDict['offset'] = int (Match.group(3), 16)
+ if ConfigDict['order'] == -1:
+ ConfigDict['order'] = ConfigDict['offset'] << 8
+ else:
+ (Major, Minor) = ConfigDict['order'].split('.')
+ ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)
+ if IsUpdSect:
+ Value = Match.group(5).strip()
+ if Match.group(4).startswith("0x"):
+ Length = int (Match.group(4), 16)
+ else :
+ Length = int (Match.group(4))
+ else:
+ Value = Match.group(4)
+ if Value is None:
+ Value = ''
+ Value = Value.strip()
+ if '|' in Value:
+ Match = re.match("^.+\s*\|\s*(.+)", Value)
+ if Match:
+ Value = Match.group(1)
+ Length = -1
+
+ ConfigDict['length'] = Length
+ Match = re.match("\$\((\w+)\)", Value)
+ if Match:
+ if Match.group(1) in self._MacroDict:
+ Value = self._MacroDict[Match.group(1)]
+ ConfigDict['value'] = Value
+ if ConfigDict['name'] == '':
+ # Clear BSF specific items
+ ConfigDict['help'] = ''
+ ConfigDict['type'] = ''
+ ConfigDict['option'] = ''
+
+ self._CfgItemList.append(ConfigDict.copy())
+ ConfigDict['name'] = ''
+ ConfigDict['find'] = ''
+ ConfigDict['struct'] = ''
+ ConfigDict['order'] = -1
+ ConfigDict['subreg'] = []
+ else:
+ # It could be a virtual item as below
+ # !BSF FIELD:{1:SerialDebugPortAddress0}
+ Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine)
+ if Match:
+ SubCfgDict = ConfigDict
+ SubCfgDict['cname'] = Match.group(1)
+ SubCfgDict['length'] = int (Match.group(2))
+ if SubCfgDict['length'] > 0:
+ LastItem = self._CfgItemList[-1]
+ if len(LastItem['subreg']) == 0:
+ SubOffset = 0
+ else:
+ SubOffset += LastItem['subreg'][-1]['length']
+ SubCfgDict['offset'] = SubOffset
+ LastItem['subreg'].append (SubCfgDict.copy())
+ ConfigDict['name'] = ''
+ return Error
+
+ def UpdateSubRegionDefaultValue (self):
+ Error = 0
+ for Item in self._CfgItemList:
+ if len(Item['subreg']) == 0:
+ continue
+ bytearray = []
+ if Item['value'][0] == '{':
+ binlist = Item['value'][1:-1].split(',')
+ for each in binlist:
+ each = each.strip()
+ if each.startswith('0x'):
+ value = int(each, 16)
+ else:
+ value = int(each)
+ bytearray.append(value)
+ else:
+ if Item['value'].startswith('0x'):
+ value = int(Item['value'], 16)
+ else:
+ value = int(Item['value'])
+ idx = 0;
+ while idx < Item['length']:
+ bytearray.append(value & 0xFF)
+ value = value >> 8
+ idx = idx + 1
+ for SubItem in Item['subreg']:
+ if SubItem['length'] in (1,2,4,8):
+ valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]
+ valuelist.reverse()
+ valuestr = "".join('%02X' % b for b in valuelist)
+ SubItem['value'] = '0x%s' % valuestr
+ else:
+ valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])
+ SubItem['value'] = '{%s}' % valuestr
+ return Error
+
+ def UpdateVpdSizeField (self):
+ FvDir = self._FvDir;
+
+ if 'VPD_TOOL_GUID' not in self._MacroDict:
+ self.Error = "VPD_TOOL_GUID definition is missing in DSC file"
+ return 1
+
+ VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map')
+ if not os.path.exists(VpdMapFile):
+ self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile
+ return 2
+
+ MapFd = open(VpdMapFile, "r")
+ MapLines = MapFd.readlines()
+ MapFd.close()
+
+ VpdDict = {}
+ PcdDict = {}
+ for MapLine in MapLines:
+ #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346
+ #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346
+ #gPlatformFspPkgTokenSpaceGuid.PcdTest | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05}
+ Match = re.match("([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)(\s\|\sDEFAULT)?\s\|\s(0x[0-9A-F]{4})\s\|\s(\d+|0x[0-9a-fA-F]+)\s\|\s(\{?[x0-9a-fA-F,\s]+\}?)", MapLine)
+ if Match:
+ Space = Match.group(1)
+ Name = Match.group(2)
+ if (self._MapVer == 0) and (Match.group(3) != None):
+ self._MapVer = 1
+ Offset = int (Match.group(4), 16)
+ if Match.group(5).startswith("0x"):
+ Length = int (Match.group(5), 16)
+ else :
+ Length = int (Match.group(5))
+ PcdDict["len"] = Length
+ PcdDict["value"] = Match.group(6)
+ VpdDict[Space+'.'+Name] = dict(PcdDict)
+
+ for Item in self._CfgItemList:
+ if Item['value'] == '':
+ Item['value'] = VpdDict[Item['space']+'.'+Item['cname']]['value']
+ if Item['length'] == -1:
+ Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len']
+ if Item['struct'] != '':
+ Type = Item['struct'].strip()
+ if Type.endswith('*') and (Item['length'] != 4):
+ self.Error = "Struct pointer '%s' has invalid size" % Type
+ return 3
+
+ return 0
+
+ def CreateUpdTxtFile (self, UpdTxtFile):
+ FvDir = self._FvDir
+ if 'UPD_TOOL_GUID' not in self._MacroDict:
+ self.Error = "UPD_TOOL_GUID definition is missing in DSC file"
+ return 1
+
+ if UpdTxtFile == '':
+ UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.txt')
+
+ ReCreate = False
+ if not os.path.exists(UpdTxtFile):
+ ReCreate = True
+ else:
+ DscTime = os.path.getmtime(self._DscFile)
+ TxtTime = os.path.getmtime(UpdTxtFile)
+ if DscTime > TxtTime:
+ ReCreate = True
+
+ if not ReCreate:
+ # DSC has not been modified yet
+ # So don't have to re-generate other files
+ self.Error = 'No DSC file change, skip to create UPD TXT file'
+ return 256
+
+ TxtFd = open(UpdTxtFile, "w")
+ TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))
+
+ NextOffset = 0
+ SpaceIdx = 0
+ if self._MapVer == 1:
+ Default = 'DEFAULT|'
+ else:
+ Default = ''
+ for Item in self._CfgItemList:
+ if Item['region'] != 'UPD':
+ continue
+ Offset = Item['offset']
+ if NextOffset < Offset:
+ # insert one line
+ TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset))
+ SpaceIdx = SpaceIdx + 1
+ NextOffset = Offset + Item['length']
+ TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value']))
+ TxtFd.close()
+ return 0
+
+ def CreateField (self, Name, Length, Offset, Struct):
+ PosName = 28
+ PosComment = 30
+
+ IsArray = False
+ if Length == 1:
+ Type = "UINT8"
+ elif Length == 2:
+ Type = "UINT16"
+ elif Length == 4:
+ Type = "UINT32"
+ elif Length == 8:
+ Type = "UINT64"
+ else:
+ Type = "UINT8"
+ IsArray = True
+
+ if Struct != '':
+ IsArray = False
+ Type = Struct
+
+ if IsArray:
+ Name = Name + '[%d]' % Length
+
+ if len(Type) < PosName:
+ Space1 = PosName - len(Type)
+ else:
+ Space1 = 1
+
+ if len(Name) < PosComment:
+ Space2 = PosComment - len(Name)
+ else:
+ Space2 = 1
+
+ return " %s%s%s;%s/* Offset 0x%04X */\n" % (Type, ' ' * Space1, Name, ' ' * Space2, Offset)
+
+
+ def CreateHeaderFile (self, InputHeaderFile, IsInternal):
+ Error = 0
+ FvDir = self._FvDir
+
+ if IsInternal:
+ HeaderFile = os.path.join(FvDir, 'VpdHeader.h')
+ else:
+ HeaderFile = os.path.join(FvDir, 'fsp_vpd.h')
+
+ # Check if header needs to be recreated
+ ReCreate = False
+ if IsInternal:
+ if not os.path.exists(HeaderFile):
+ ReCreate = True
+ else:
+ DscTime = os.path.getmtime(self._DscFile)
+ HeadTime = os.path.getmtime(HeaderFile)
+ if not os.path.exists(InputHeaderFile):
+ InpTime = HeadTime
+ else:
+ InpTime = os.path.getmtime(InputHeaderFile)
+ if DscTime > HeadTime or InpTime > HeadTime:
+ ReCreate = True
+
+ if not ReCreate:
+ self.Error = "No DSC or input header file is changed, skip the header file generating"
+ return 256
+
+ HeaderFd = open(HeaderFile, "w")
+ FileBase = os.path.basename(HeaderFile)
+ FileName = FileBase.replace(".", "_").upper()
+ HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
+ HeaderFd.write("#ifndef __%s__\n" % FileName)
+ HeaderFd.write("#define __%s__\n\n" % FileName)
+ HeaderFd.write("#pragma pack(1)\n\n")
+
+ if InputHeaderFile != '':
+ if not os.path.exists(InputHeaderFile):
+ self.Error = "Input header file '%s' does not exist" % InputHeaderFile
+ return 2
+
+ InFd = open(InputHeaderFile, "r")
+ IncLines = InFd.readlines()
+ InFd.close()
+
+ Export = False
+ for Line in IncLines:
+ Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)
+ if Match:
+ if Match.group(1) == "BEGIN":
+ Export = True
+ continue
+ else:
+ Export = False
+ continue
+ if Export:
+ HeaderFd.write(Line)
+ HeaderFd.write("\n\n")
+
+ for Region in ['UPD', 'VPD']:
+
+ # Write PcdVpdRegionSign and PcdImageRevision
+ if Region[0] == 'V':
+ if 'VPD_TOOL_GUID' not in self._MacroDict:
+ self.Error = "VPD_TOOL_GUID definition is missing in DSC file"
+ Error = 1
+ break
+
+ BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin")
+ if not os.path.exists(BinFile):
+ self.Error = "VPD binary file '%s' does not exist" % BinFile
+ Error = 2
+ break
+
+ BinFd = open(BinFile, "rb")
+ IdStr = BinFd.read(0x08)
+ ImageId = struct.unpack('Q', IdStr)
+ ImageRev = struct.unpack('L', BinFd.read(0x04))
+ BinFd.close()
+
+ HeaderFd.write("#define VPD_IMAGE_ID 0x%016X /* '%s' */\n" % (ImageId[0], IdStr))
+ HeaderFd.write("#define VPD_IMAGE_REV 0x%08X \n\n" % ImageRev[0])
+
+ HeaderFd.write("typedef struct _" + Region[0] + "PD_DATA_REGION {\n")
+ NextOffset = 0
+ SpaceIdx = 0
+ Offset = 0
+
+ LastVisible = True
+ ResvOffset = 0
+ ResvIdx = 0
+ LineBuffer = []
+ for Item in self._CfgItemList:
+ if Item['region'] != Region:
+ continue
+
+ NextVisible = LastVisible
+ if not IsInternal:
+ if LastVisible and (Item['header'] == 'OFF'):
+ NextVisible = False
+ ResvOffset = Item['offset']
+ elif (not LastVisible) and Item['header'] == 'ON':
+ NextVisible = True
+ Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
+ ResvIdx = ResvIdx + 1
+ HeaderFd.write(self.CreateField (Name, Item["offset"] - ResvOffset, ResvOffset, ''))
+
+ if Offset < Item["offset"]:
+ if IsInternal or LastVisible:
+ Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
+ LineBuffer.append(self.CreateField (Name, Item["offset"] - Offset, Offset, ''))
+ SpaceIdx = SpaceIdx + 1
+ Offset = Item["offset"]
+
+ if Offset != Item["offset"]:
+ print "Unsorted offset 0x%04X\n" % Item["offset"]
+ error = 2
+ break;
+
+ LastVisible = NextVisible
+
+ Offset = Offset + Item["length"]
+ if IsInternal or LastVisible:
+ for Each in LineBuffer:
+ HeaderFd.write (Each)
+ LineBuffer = []
+ HeaderFd.write(self.CreateField (Item["cname"], Item["length"], Item["offset"], Item['struct']))
+
+ HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")
+ HeaderFd.write("#pragma pack()\n\n")
+ HeaderFd.write("#endif\n")
+ HeaderFd.close()
+
+ return Error
+
+ def WriteBsfStruct (self, BsfFd, Item):
+ if Item['type'] == "None":
+ Space = "gPlatformFspPkgTokenSpaceGuid"
+ else:
+ Space = Item['space']
+ Line = " $%s_%s" % (Space, Item['cname'])
+ Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])
+ if Match:
+ DefaultValue = Match.group(1).strip()
+ else:
+ DefaultValue = Item['value'].strip()
+ BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))
+ TmpList = []
+ if Item['type'] == "Combo":
+ if not Item['option'] in self._BuidinOption:
+ OptList = Item['option'].split(',')
+ for Option in OptList:
+ Option = Option.strip()
+ (OpVal, OpStr) = Option.split(':')
+ TmpList.append((OpVal, OpStr))
+ return TmpList
+
+ def WriteBsfOption (self, BsfFd, Item):
+ PcdName = Item['space'] + '_' + Item['cname']
+ WriteHelp = 0
+ if Item['type'] == "Combo":
+ if Item['option'] in self._BuidinOption:
+ Options = self._BuidinOption[Item['option']]
+ else:
+ Options = PcdName
+ BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options));
+ WriteHelp = 1
+ elif Item['type'].startswith("EditNum"):
+ Match = re.match("EditNum\s*,\s*(HEX|DEC)\s*,\s*\((\d+|0x[0-9A-Fa-f]+)\s*,\s*(\d+|0x[0-9A-Fa-f]+)\)", Item['type'])
+ if Match:
+ BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)));
+ WriteHelp = 2
+ elif Item['type'].startswith("EditText"):
+ BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));
+ WriteHelp = 1
+
+ if WriteHelp > 0:
+ HelpLines = Item['help'].split('\\n\\r')
+ FirstLine = True
+ for HelpLine in HelpLines:
+ if FirstLine:
+ FirstLine = False
+ BsfFd.write(' Help "%s"\n' % (HelpLine));
+ else:
+ BsfFd.write(' "%s"\n' % (HelpLine));
+ if WriteHelp == 2:
+ BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)));
+
+ def GenerateBsfFile (self, BsfFile):
+
+ if BsfFile == '':
+ self.Error = "BSF output file '%s' is invalid" % BsfFile
+ return 1
+
+ Error = 0
+ OptionDict = {}
+ BsfFd = open(BsfFile, "w")
+ BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))
+ BsfFd.write("%s\n" % self._GlobalDataDef);
+ BsfFd.write("StructDef\n")
+ NextOffset = -1
+ for Item in self._CfgItemList:
+ if Item['find'] != '':
+ BsfFd.write('\n Find "%s"\n' % Item['find'])
+ NextOffset = Item['offset'] + Item['length']
+ if Item['name'] != '':
+ if NextOffset != Item['offset']:
+ BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))
+ if len(Item['subreg']) > 0:
+ NextOffset = Item['offset']
+ for SubItem in Item['subreg']:
+ NextOffset += SubItem['length']
+ if SubItem['name'] == '':
+ BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))
+ else:
+ Options = self.WriteBsfStruct(BsfFd, SubItem)
+ if len(Options) > 0:
+ OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options
+ if (Item['offset'] + Item['length']) < NextOffset:
+ self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])
+ return 2
+ else:
+ NextOffset = Item['offset'] + Item['length']
+ Options = self.WriteBsfStruct(BsfFd, Item)
+ if len(Options) > 0:
+ OptionDict[Item['space']+'_'+Item['cname']] = Options
+ BsfFd.write("\nEndStruct\n\n")
+
+ BsfFd.write("%s" % self._BuidinOptionTxt);
+
+ for Each in OptionDict:
+ BsfFd.write("List &%s\n" % Each);
+ for Item in OptionDict[Each]:
+ BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]));
+ BsfFd.write("EndList\n\n");
+
+ BsfFd.write("BeginInfoBlock\n");
+ BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']));
+ BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']));
+ BsfFd.write("EndInfoBlock\n\n");
+
+ for Each in self._CfgPageDict:
+ BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);
+ BsfItems = []
+ for Item in self._CfgItemList:
+ if Item['name'] != '':
+ if Item['page'] != Each:
+ continue
+ if len(Item['subreg']) > 0:
+ for SubItem in Item['subreg']:
+ if SubItem['name'] != '':
+ BsfItems.append(SubItem)
+ else:
+ BsfItems.append(Item)
+
+ BsfItems.sort(key=lambda x: x['order'])
+
+ for Item in BsfItems:
+ self.WriteBsfOption (BsfFd, Item)
+ BsfFd.write("EndPage\n\n");
+
+ BsfFd.close()
+ return Error
+
+
+def Usage():
+ print "GenCfgOpt Version 0.50"
+ print "Usage:"
+ print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-D Macros]"
+ print " GenCfgOpt HEADER PlatformDscFile BuildFvDir [InputHFile] [-D Macros]"
+ print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"
+
+def Main():
+ #
+ # Parse the options and args
+ #
+ GenCfgOpt = CGenCfgOpt()
+ argc = len(sys.argv)
+ if argc < 4:
+ Usage()
+ return 1
+ else:
+ DscFile = sys.argv[2]
+ if not os.path.exists(DscFile):
+ print "ERROR: Cannot open DSC file '%s' !" % DscFile
+ return 2
+
+ OutFile = ''
+ if argc > 4:
+ if sys.argv[4][0] == '-':
+ Start = 4
+ else:
+ OutFile = sys.argv[4]
+ Start = 5
+ if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:
+ print "ERROR: %s !" % GenCfgOpt.Error
+ return 3
+
+ FvDir = sys.argv[3]
+ if not os.path.isdir(FvDir):
+ print "ERROR: FV folder '%s' is invalid !" % FvDir
+ return 4
+
+ if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:
+ print "ERROR: %s !" % GenCfgOpt.Error
+ return 5
+
+
+ if GenCfgOpt.UpdateVpdSizeField() != 0:
+ print "ERROR: %s !" % GenCfgOpt.Error
+ return 6
+
+ if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:
+ print "ERROR: %s !" % GenCfgOpt.Error
+ return 7
+
+ if sys.argv[1] == "UPDTXT":
+ Ret = GenCfgOpt.CreateUpdTxtFile(OutFile)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print "INFO: %s !" % (GenCfgOpt.Error)
+ else :
+ print "ERROR: %s !" % (GenCfgOpt.Error)
+ return Ret
+ elif sys.argv[1] == "HEADER":
+ Ret = GenCfgOpt.CreateHeaderFile(OutFile, True)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print "INFO: %s !" % (GenCfgOpt.Error)
+ else :
+ print "ERROR: %s !" % (GenCfgOpt.Error)
+ return Ret
+ if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0:
+ print "ERROR: %s !" % GenCfgOpt.Error
+ return 8
+ elif sys.argv[1] == "GENBSF":
+ if GenCfgOpt.GenerateBsfFile(OutFile) != 0:
+ print "ERROR: %s !" % GenCfgOpt.Error
+ return 9
+ else:
+ if argc < 5:
+ Usage()
+ return 1
+ print "ERROR: Unknown command '%s' !" % sys.argv[1]
+ Usage()
+ return 1
+ return 0
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/IntelFspPkg/Tools/PatchFv.py b/IntelFspPkg/Tools/PatchFv.py new file mode 100644 index 0000000000..cc22cc201e --- /dev/null +++ b/IntelFspPkg/Tools/PatchFv.py @@ -0,0 +1,567 @@ +## @ PatchFv.py
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License that accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+import os
+import re
+import sys
+
+def readDataFromFile (binfile, offset, len=1):
+ fd = open(binfile, "r+b")
+ fsize = os.path.getsize(binfile)
+ offval = offset & 0xFFFFFFFF
+ if (offval & 0x80000000):
+ offval = fsize - (0xFFFFFFFF - offval + 1)
+ fd.seek(offval)
+ bytearray = [ord(b) for b in fd.read(len)]
+ value = 0;
+ idx = len - 1;
+ while idx >= 0:
+ value = value << 8 | bytearray[idx]
+ idx = idx - 1
+ fd.close()
+ return value
+
+def patchDataInFile (binfile, offset, value, len=1):
+ fd = open(binfile, "r+b")
+ fsize = os.path.getsize(binfile)
+ offval = offset & 0xFFFFFFFF
+ if (offval & 0x80000000):
+ offval = fsize - (0xFFFFFFFF - offval + 1)
+ bytearray = []
+ idx = 0;
+ while idx < len:
+ bytearray.append(value & 0xFF)
+ value = value >> 8
+ idx = idx + 1
+ fd.seek(offval)
+ fd.write("".join(chr(b) for b in bytearray))
+ fd.close()
+ return len;
+
+
+class Symbols:
+ def __init__(self):
+ self.dictSymbolAddress = {}
+ self.dictGuidNameXref = {}
+ self.dictFfsOffset = {}
+ self.dictVariable = {}
+ self.dictModBase = {}
+ self.fdFile = None
+ self.string = ""
+ self.fdBase = 0xFFFFFFFF
+ self.fdSize = 0
+ self.index = 0
+ self.parenthesisOpenSet = '([{<'
+ self.parenthesisCloseSet = ')]}>'
+
+ def getFdFile (self):
+ return self.fdFile
+
+ def getFdSize (self):
+ return self.fdSize
+
+ def createDicts (self, fvDir, fvNames):
+ if not os.path.isdir(fvDir):
+ raise Exception ("'%s' is not a valid directory!" % FvDir)
+
+ xrefFile = os.path.join(fvDir, "Guid.xref")
+ if not os.path.exists(xrefFile):
+ raise Exception("Cannot open GUID Xref file '%s'!" % xrefFile)
+
+ self.dictGuidNameXref = {}
+ self.parseGuidXrefFile(xrefFile)
+
+ fvList = fvNames.split(":")
+ fdBase = fvList.pop()
+ if len(fvList) == 0:
+ fvList.append(fdBase)
+
+ fdFile = os.path.join(fvDir, fdBase.strip() + ".fd")
+ if not os.path.exists(fdFile):
+ raise Exception("Cannot open FD file '%s'!" % fdFile)
+
+ self.fdFile = fdFile
+ self.fdSize = os.path.getsize(fdFile)
+
+ infFile = os.path.join(fvDir, fvList[0].strip()) + ".inf"
+ if not os.path.exists(infFile):
+ raise Exception("Cannot open INF file '%s'!" % infFile)
+
+ self.parseInfFile(infFile)
+
+ self.dictVariable = {}
+ self.dictVariable["FDSIZE"] = self.fdSize
+ self.dictVariable["FDBASE"] = self.fdBase
+
+ self.dictSymbolAddress = {}
+ self.dictFfsOffset = {}
+ for file in fvList:
+
+ fvFile = os.path.join(fvDir, file.strip()) + ".Fv"
+ mapFile = fvFile + ".map"
+ if not os.path.exists(mapFile):
+ raise Exception("Cannot open MAP file '%s'!" % mapFile)
+
+ self.parseFvMapFile(mapFile)
+
+ fvTxtFile = fvFile + ".txt"
+ if not os.path.exists(fvTxtFile):
+ raise Exception("Cannot open FV TXT file '%s'!" % fvTxtFile)
+
+ self.parseFvTxtFile(fvTxtFile)
+
+ ffsDir = os.path.join(fvDir, "Ffs")
+ if (os.path.isdir(ffsDir)):
+ for item in os.listdir(ffsDir):
+ if len(item) <= 0x24:
+ continue
+ mapFile =os.path.join(ffsDir, item, "%s.map" % item[0:0x24])
+ if not os.path.exists(mapFile):
+ continue
+ self.parseModMapFile(item[0x24:], mapFile)
+
+ return 0
+
+ def getFvOffsetInFd(self, fvFile):
+ fvHandle = open(fvFile, "r+b")
+ fdHandle = open(self.fdFile, "r+b")
+ offset = fdHandle.read().find(fvHandle.read(0x70))
+ fvHandle.close()
+ fdHandle.close()
+ if offset == -1:
+ raise Exception("Could not locate FV file %s in FD!" % fvFile)
+ return offset
+
+ def parseInfFile(self, infFile):
+ fvOffset = self.getFvOffsetInFd(infFile[0:-4] + ".Fv")
+ fdIn = open(infFile, "r")
+ rptLine = fdIn.readline()
+ self.fdBase = 0xFFFFFFFF
+ while (rptLine != "" ):
+ #EFI_BASE_ADDRESS = 0xFFFDF400
+ match = re.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine)
+ if match is not None:
+ self.fdBase = int(match.group(1), 16) - fvOffset
+ rptLine = fdIn.readline()
+ fdIn.close()
+ if self.fdBase == 0xFFFFFFFF:
+ raise Exception("Could not find EFI_BASE_ADDRESS in INF file!" % fvFile)
+ return 0
+
+ def parseFvTxtFile(self, fvTxtFile):
+ fvOffset = self.getFvOffsetInFd(fvTxtFile[0:-4])
+ fdIn = open(fvTxtFile, "r")
+ rptLine = fdIn.readline()
+ while (rptLine != "" ):
+ match = re.match("(0x[a-fA-F0-9]+)\s([0-9a-fA-F\-]+)", rptLine)
+ if match is not None:
+ self.dictFfsOffset[match.group(2)] = "0x%08X" % (int(match.group(1), 16) + fvOffset)
+ rptLine = fdIn.readline()
+ fdIn.close()
+ return 0
+
+ def parseFvMapFile(self, mapFile):
+ fdIn = open(mapFile, "r")
+ rptLine = fdIn.readline()
+ modName = ""
+ while (rptLine != "" ):
+ if rptLine[0] != ' ':
+ #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958)
+ #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178)
+ match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine)
+ if match is not None:
+ modName = match.group(1)
+ if len(modName) == 36:
+ modName = self.dictGuidNameXref[modName.upper()]
+ self.dictModBase['%s:BASE' % modName] = int (match.group(2), 16)
+ self.dictModBase['%s:ENTRY' % modName] = int (match.group(3), 16)
+ match = re.match("\(GUID=([A-Z0-9\-]+)\s+\.textbaseaddress=(0x[0-9a-fA-F]+)\s+\.databaseaddress=(0x[0-9a-fA-F]+)\)", rptLine)
+ if match is not None:
+ modName = match.group(1)
+ if len(modName) == 36:
+ modName = self.dictGuidNameXref[modName.upper()]
+ self.dictModBase['%s:TEXT' % modName] = int (match.group(2), 16)
+ self.dictModBase['%s:DATA' % modName] = int (match.group(3), 16)
+ else:
+ # 0x00fff8016c __ModuleEntryPoint
+ match = re.match("^\s+(0x[a-z0-9]+)\s+([_a-zA-Z0-9]+)", rptLine)
+ if match is not None:
+ self.dictSymbolAddress["%s:%s"%(modName, match.group(2))] = match.group(1)
+ rptLine = fdIn.readline()
+ fdIn.close()
+ return 0
+
+ def parseModMapFile(self, moduleName, mapFile):
+ modSymbols = {}
+ fdIn = open(mapFile, "r")
+ reportLine = fdIn.readline()
+ if reportLine.strip().find("Archive member included because of file (symbol)") != -1:
+ #GCC
+ # 0x0000000000001d55 IoRead8
+ patchMapFileMatchString = "\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
+ matchKeyGroupIndex = 2
+ matchSymbolGroupIndex = 1
+ moduleEntryPoint = "_ModuleEntryPoint"
+ else:
+ #MSFT
+ #0003:00000190 _gComBase 00007a50 SerialPo
+ patchMapFileMatchString = "^\s[0-9a-fA-F]{4}:[0-9a-fA-F]{8}\s+(\w+)\s+([0-9a-fA-F]{8}\s+)"
+ matchKeyGroupIndex = 1
+ matchSymbolGroupIndex = 2
+ moduleEntryPoint = "__ModuleEntryPoint"
+ while (reportLine != "" ):
+ match = re.match(patchMapFileMatchString, reportLine)
+ if match is not None:
+ modSymbols[match.group(matchKeyGroupIndex)] = match.group(matchSymbolGroupIndex)
+ reportLine = fdIn.readline()
+ fdIn.close()
+
+ if not moduleEntryPoint in modSymbols:
+ return 1
+
+ modEntry = '%s:%s' % (moduleName,moduleEntryPoint)
+ if not modEntry in self.dictSymbolAddress:
+ modKey = '%s:ENTRY' % moduleName
+ if modKey in self.dictModBase:
+ baseOffset = self.dictModBase['%s:ENTRY' % moduleName] - int(modSymbols[moduleEntryPoint], 16)
+ else:
+ return 2
+ else:
+ baseOffset = int(self.dictSymbolAddress[modEntry], 16) - int(modSymbols[moduleEntryPoint], 16)
+ for symbol in modSymbols:
+ fullSym = "%s:%s" % (moduleName, symbol)
+ if not fullSym in self.dictSymbolAddress:
+ self.dictSymbolAddress[fullSym] = "0x00%08x" % (baseOffset+ int(modSymbols[symbol], 16))
+ return 0
+
+ def parseGuidXrefFile(self, xrefFile):
+ fdIn = open(xrefFile, "r")
+ rptLine = fdIn.readline()
+ while (rptLine != "" ):
+ match = re.match("([0-9a-fA-F\-]+)\s([_a-zA-Z0-9]+)", rptLine)
+ if match is not None:
+ self.dictGuidNameXref[match.group(1).upper()] = match.group(2)
+ rptLine = fdIn.readline()
+ fdIn.close()
+ return 0
+
+ def getCurr(self):
+ try:
+ return self.string[self.index]
+ except Exception:
+ return ''
+
+ def isLast(self):
+ return self.index == len(self.string)
+
+ def moveNext(self):
+ self.index += 1
+
+ def skipSpace(self):
+ while not self.isLast():
+ if self.getCurr() in ' \t':
+ self.moveNext()
+ else:
+ return
+
+ def parseValue(self):
+ self.skipSpace()
+ var = ''
+ while not self.isLast():
+ char = self.getCurr()
+ if char.lower() in '_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-':
+ var += char
+ self.moveNext()
+ else:
+ break
+
+ if ':' in var:
+ partList = var.split(':')
+ if len(partList) != 2:
+ raise Exception("Unrecognized expression %s" % var)
+ modName = partList[0]
+ modOff = partList[1]
+ if ('-' not in modName) and (modOff[0] in '0123456789'):
+ # MOD: OFFSET
+ var = self.getModGuid(modName) + ":" + modOff
+ if '-' in var: # GUID:OFFSET
+ value = self.getGuidOff(var)
+ else:
+ value = self.getSymbols(var)
+ self.synUsed = True
+ else:
+ if var[0] in '0123456789':
+ value = self.getNumber(var)
+ else:
+ value = self.getVariable(var)
+ return int(value)
+
+ def parseSingleOp(self):
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '~':
+ self.moveNext()
+ return ~self.parseBrace()
+ else:
+ return self.parseValue()
+
+ def parseBrace(self):
+ self.skipSpace()
+ char = self.getCurr()
+ parenthesisType = self.parenthesisOpenSet.find(char)
+ if parenthesisType >= 0:
+ self.moveNext()
+ value = self.parseExpr()
+ self.skipSpace()
+ if self.getCurr() != self.parenthesisCloseSet[parenthesisType]:
+ raise Exception("No closing brace")
+ self.moveNext()
+ if parenthesisType == 1: # [ : Get content
+ value = self.getContent(value)
+ elif parenthesisType == 2: # { : To address
+ value = self.toAddress(value)
+ elif parenthesisType == 3: # < : To offset
+ value = self.toOffset(value)
+ return value
+ else:
+ return self.parseSingleOp()
+
+ def parseMul(self):
+ values = [self.parseBrace()]
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '*':
+ self.moveNext()
+ values.append(self.parseBrace())
+ else:
+ break
+ value = 1;
+ for each in values:
+ value *= each
+ return value
+
+ def parseAndOr(self):
+ values = [self.parseMul()]
+ op = None
+ value = 0xFFFFFFFF;
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '&':
+ self.moveNext()
+ values.append(self.parseMul())
+ op = char
+ elif char == '|':
+ div_index = self.index
+ self.moveNext()
+ values.append(self.parseMul())
+ value = 0
+ op = char
+ else:
+ break
+
+ for each in values:
+ if op == '|':
+ value |= each
+ else:
+ value &= each
+
+ return value
+
+ def parseAddMinus(self):
+ values = [self.parseAndOr()]
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '+':
+ self.moveNext()
+ values.append(self.parseAndOr())
+ elif char == '-':
+ self.moveNext()
+ values.append(-1 * self.parseAndOr())
+ else:
+ break
+ return sum(values)
+
+ def parseExpr(self):
+ return self.parseAddMinus()
+
+ def getResult(self):
+ value = self.parseExpr()
+ self.skipSpace()
+ if not self.isLast():
+ raise Exception("Unexpected character found '%s'" % self.getCurr())
+ return value
+
+ def getModGuid(self, var):
+ guid = (guid for guid,name in self.dictGuidNameXref.items() if name==var)
+ try:
+ value = guid.next()
+ except Exception:
+ raise Exception("Unknown module name %s !" % var)
+ return value
+
+ def getVariable(self, var):
+ value = self.dictVariable.get(var, None)
+ if value == None:
+ raise Exception("Unrecognized variable '%s'" % var)
+ return value
+
+ def getNumber(self, var):
+ var = var.strip()
+ if var.startswith('0x'): # HEX
+ value = int(var, 16)
+ else:
+ value = int(var, 10)
+ return value
+
+ def getContent(self, value):
+ if (value >= self.fdBase) and (value < self.fdBase + self.fdSize):
+ value = value - self.fdBase
+ if value >= self.fdSize:
+ raise Exception("Invalid file offset 0x%08x !" % value)
+ return readDataFromFile (self.fdFile, value, 4)
+
+ def toAddress(self, value):
+ if value < self.fdSize:
+ value = value + self.fdBase
+ return value
+
+ def toOffset(self, value):
+ if value > self.fdBase:
+ value = value - self.fdBase
+ return value
+
+ def getGuidOff(self, value):
+ # GUID:Offset
+ symbolName = value.split(':')
+ if len(symbolName) == 2 and self.dictFfsOffset.has_key(symbolName[0]):
+ value = (int(self.dictFfsOffset[symbolName[0]], 16) + int(symbolName[1], 16)) & 0xFFFFFFFF
+ else:
+ raise Exception("Unknown GUID %s !" % value)
+ return value
+
+ def getSymbols(self, value):
+ if self.dictSymbolAddress.has_key(value):
+ # Module:Function
+ ret = int (self.dictSymbolAddress[value], 16)
+ else:
+ raise Exception("Unknown symbol %s !" % value)
+ return ret
+
+ def evaluate(self, expression, isOffset):
+ self.index = 0
+ self.synUsed = False
+ self.string = expression
+ value = self.getResult()
+ if isOffset:
+ if self.synUsed:
+ # Consider it as an address first
+ if (value >= self.fdBase) and (value < self.fdBase + self.fdSize):
+ value = value - self.fdBase
+ if value & 0x80000000:
+ # Consider it as a negative offset next
+ offset = (~value & 0xFFFFFFFF) + 1
+ if offset < self.fdSize:
+ value = self.fdSize - offset
+ if value >= self.fdSize:
+ raise Exception("Invalid offset expression !")
+ return value & 0xFFFFFFFF
+
+def usage():
+ print "Usage: \n\tPatchFv FvBuildDir [FvFileBaseNames:]FdFileBaseNameToPatch \"Offset, Value\""
+
+def main():
+ #
+ # Parse the options and args
+ #
+ symTables = Symbols()
+
+ if len(sys.argv) < 4:
+ Usage()
+ return 1
+
+ if symTables.createDicts(sys.argv[1], sys.argv[2]) != 0:
+ print "ERROR: Failed to create symbol dictionary!!"
+ return 2
+
+ fdFile = symTables.getFdFile()
+ fdSize = symTables.getFdSize()
+
+ try:
+ comment = ""
+ for fvFile in sys.argv[3:]:
+ items = fvFile.split(",")
+ if len (items) < 2:
+ raise Exception("Expect more arguments for '%s'!" % fvFile)
+
+ comment = ""
+ command = ""
+ params = []
+ for item in items:
+ item = item.strip()
+ if item.startswith("@"):
+ comment = item[1:]
+ elif item.startswith("$"):
+ command = item[1:]
+ else:
+ if len(params) == 0:
+ isOffset = True
+ else :
+ isOffset = False
+ params.append (symTables.evaluate(item, isOffset))
+
+ if command == "":
+ # Patch a DWORD
+ if len (params) == 2:
+ offset = params[0]
+ value = params[1]
+ oldvalue = readDataFromFile(fdFile, offset, 4)
+ ret = patchDataInFile (fdFile, offset, value, 4) - 4
+ else:
+ raise Exception ("Patch command needs 2 parameters !")
+
+ if ret:
+ raise Exception ("Patch failed for offset 0x%08X" % offset)
+ else:
+ print "Patched offset 0x%08X:[%08X] with value 0x%08X # %s" % (offset, oldvalue, value, comment)
+
+ elif command == "COPY":
+ # Copy binary block from source to destination
+ if len (params) == 3:
+ src = symTables.toOffset(params[0])
+ dest = symTables.toOffset(params[1])
+ clen = symTables.toOffset(params[2])
+ if (dest + clen <= fdSize) and (src + clen <= fdSize):
+ oldvalue = readDataFromFile(fdFile, src, clen)
+ ret = patchDataInFile (fdFile, dest, oldvalue, clen) - clen
+ else:
+ raise Exception ("Copy command OFFSET or LENGTH parameter is invalid !")
+ else:
+ raise Exception ("Copy command needs 3 parameters !")
+
+ if ret:
+ raise Exception ("Copy failed from offset 0x%08X to offset 0x%08X!" % (src, dest))
+ else :
+ print "Copied %d bytes from offset 0x%08X ~ offset 0x%08X # %s" % (clen, src, dest, comment)
+ else:
+ raise Exception ("Unknown command %s!" % command)
+ return 0
+
+ except Exception as (ex):
+ print "ERROR: %s" % ex
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx b/IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx Binary files differnew file mode 100644 index 0000000000..e4da8e057b --- /dev/null +++ b/IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx diff --git a/IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx b/IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx Binary files differnew file mode 100644 index 0000000000..ab1eda993e --- /dev/null +++ b/IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx |