mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
Add IntelFspPkg to support create FSP bin based on EDKII.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed off by: Ravi Rangarajan <ravi.p.rangarajan@intel.com> Reviewed by: Maurice Ma <maurice.ma@intel.com> Reviewed by: Jiewen Yao <jiewen.yao@intel.com> Reviewed by: Giri Mudusuru <giri.p.mudusuru@intel.com> Reviewed by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15705 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
0d807dae4a
commit
c8ec22a266
464
IntelFspPkg/FspDxeIpl/DxeIpl.c
Normal file
464
IntelFspPkg/FspDxeIpl/DxeIpl.c
Normal file
@ -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;
|
||||
}
|
192
IntelFspPkg/FspDxeIpl/DxeIpl.h
Normal file
192
IntelFspPkg/FspDxeIpl/DxeIpl.h
Normal file
@ -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
|
70
IntelFspPkg/FspDxeIpl/FspDxeIpl.inf
Normal file
70
IntelFspPkg/FspDxeIpl/FspDxeIpl.inf
Normal file
@ -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
|
76
IntelFspPkg/FspSecCore/FspSecCore.inf
Normal file
76
IntelFspPkg/FspSecCore/FspSecCore.inf
Normal file
@ -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
|
||||
|
552
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
Normal file
552
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
Normal file
@ -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
|
611
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
Normal file
611
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
Normal file
@ -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
|
79
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm
Normal file
79
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm
Normal file
@ -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
|
73
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s
Normal file
73
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s
Normal file
@ -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
|
103
IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16
Normal file
103
IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16
Normal file
@ -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
|
103
IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc
Normal file
103
IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc
Normal file
@ -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
|
82
IntelFspPkg/FspSecCore/Ia32/Stack.asm
Normal file
82
IntelFspPkg/FspSecCore/Ia32/Stack.asm
Normal file
@ -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
|
88
IntelFspPkg/FspSecCore/Ia32/Stacks.s
Normal file
88
IntelFspPkg/FspSecCore/Ia32/Stacks.s
Normal file
@ -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
|
63
IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc
Normal file
63
IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc
Normal file
@ -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
|
268
IntelFspPkg/FspSecCore/SecFsp.c
Normal file
268
IntelFspPkg/FspSecCore/SecFsp.c
Normal file
@ -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;
|
||||
}
|
97
IntelFspPkg/FspSecCore/SecFsp.h
Normal file
97
IntelFspPkg/FspSecCore/SecFsp.h
Normal file
@ -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
|
208
IntelFspPkg/FspSecCore/SecMain.c
Normal file
208
IntelFspPkg/FspSecCore/SecMain.c
Normal file
@ -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;
|
||||
}
|
134
IntelFspPkg/FspSecCore/SecMain.h
Normal file
134
IntelFspPkg/FspSecCore/SecMain.h
Normal file
@ -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
|
BIN
IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
Normal file
BIN
IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
Normal file
Binary file not shown.
53
IntelFspPkg/FspSecCore/Vtf0/Build.py
Normal file
53
IntelFspPkg/FspSecCore/Vtf0/Build.py
Normal file
@ -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)
|
||||
|
103
IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
Normal file
103
IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
Normal file
@ -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
|
17
IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm
Normal file
17
IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm
Normal file
@ -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"
|
110
IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
Normal file
110
IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
Normal file
@ -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()
|
||||
|
22
IntelFspPkg/Include/Guid/GuidHobFsp.h
Normal file
22
IntelFspPkg/Include/Guid/GuidHobFsp.h
Normal file
@ -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
|
30
IntelFspPkg/Include/Library/CacheAsRamLib.h
Normal file
30
IntelFspPkg/Include/Library/CacheAsRamLib.h
Normal file
@ -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
|
||||
|
62
IntelFspPkg/Include/Library/CacheLib.h
Normal file
62
IntelFspPkg/Include/Library/CacheLib.h
Normal file
@ -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
|
||||
|
29
IntelFspPkg/Include/Library/DebugDeviceLib.h
Normal file
29
IntelFspPkg/Include/Library/DebugDeviceLib.h
Normal file
@ -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
|
173
IntelFspPkg/Include/Library/FspCommonLib.h
Normal file
173
IntelFspPkg/Include/Library/FspCommonLib.h
Normal file
@ -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
|
64
IntelFspPkg/Include/Library/FspPlatformLib.h
Normal file
64
IntelFspPkg/Include/Library/FspPlatformLib.h
Normal file
@ -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
|
27
IntelFspPkg/Include/Library/FspReturnLib.h
Normal file
27
IntelFspPkg/Include/Library/FspReturnLib.h
Normal file
@ -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
|
45
IntelFspPkg/Include/Library/FspSwitchStackLib.h
Normal file
45
IntelFspPkg/Include/Library/FspSwitchStackLib.h
Normal file
@ -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
|
44
IntelFspPkg/Include/Private/FspGlobalData.h
Normal file
44
IntelFspPkg/Include/Private/FspGlobalData.h
Normal file
@ -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
|
48
IntelFspPkg/Include/Private/FspMeasurePointId.h
Normal file
48
IntelFspPkg/Include/Private/FspMeasurePointId.h
Normal file
@ -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
|
32
IntelFspPkg/Include/Private/FspPatchTable.h
Normal file
32
IntelFspPkg/Include/Private/FspPatchTable.h
Normal file
@ -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
|
19
IntelFspPkg/Include/Private/GuidHobFspGfx.h
Normal file
19
IntelFspPkg/Include/Private/GuidHobFspGfx.h
Normal file
@ -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
|
19
IntelFspPkg/Include/Private/GuidHobFspMisc.h
Normal file
19
IntelFspPkg/Include/Private/GuidHobFspMisc.h
Normal file
@ -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
|
19
IntelFspPkg/Include/Private/GuidHobFspTseg.h
Normal file
19
IntelFspPkg/Include/Private/GuidHobFspTseg.h
Normal file
@ -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
|
@ -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
|
||||
|
75
IntelFspPkg/IntelFspPkg.dsc
Normal file
75
IntelFspPkg/IntelFspPkg.dsc
Normal file
@ -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
|
@ -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]
|
||||
|
@ -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 ;
|
||||
}
|
32
IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf
Normal file
32
IntelFspPkg/Library/BaseCacheLib/BaseCacheLib.inf
Normal file
@ -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
|
||||
|
749
IntelFspPkg/Library/BaseCacheLib/CacheLib.c
Normal file
749
IntelFspPkg/Library/BaseCacheLib/CacheLib.c
Normal file
@ -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;
|
||||
}
|
||||
|
59
IntelFspPkg/Library/BaseCacheLib/CacheLibInternal.h
Normal file
59
IntelFspPkg/Library/BaseCacheLib/CacheLibInternal.h
Normal file
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
37
IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
Normal file
37
IntelFspPkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
Normal file
@ -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
|
318
IntelFspPkg/Library/BaseFspCommonLib/FspCommonLib.c
Normal file
318
IntelFspPkg/Library/BaseFspCommonLib/FspCommonLib.c
Normal file
@ -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)++];
|
||||
}
|
@ -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
|
||||
|
305
IntelFspPkg/Library/BaseFspDebugLibSerialPort/DebugLib.c
Normal file
305
IntelFspPkg/Library/BaseFspDebugLibSerialPort/DebugLib.c
Normal file
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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
|
155
IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformMemory.c
Normal file
155
IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformMemory.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
178
IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformNotify.c
Normal file
178
IntelFspPkg/Library/BaseFspPlatformLib/FspPlatformNotify.c
Normal file
@ -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.
|
||||
//
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
65
IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.asm
Normal file
65
IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.asm
Normal file
@ -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
|
64
IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.s
Normal file
64
IntelFspPkg/Library/BaseFspSwitchStackLib/Ia32/Stack.s
Normal file
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
894
IntelFspPkg/Tools/GenCfgOpt.py
Normal file
894
IntelFspPkg/Tools/GenCfgOpt.py
Normal file
@ -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())
|
567
IntelFspPkg/Tools/PatchFv.py
Normal file
567
IntelFspPkg/Tools/PatchFv.py
Normal file
@ -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())
|
BIN
IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx
Normal file
BIN
IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx
Normal file
Binary file not shown.
BIN
IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx
Normal file
BIN
IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user