summaryrefslogtreecommitdiff
path: root/Library/PeiLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Library/PeiLib.c')
-rw-r--r--Library/PeiLib.c1132
1 files changed, 1132 insertions, 0 deletions
diff --git a/Library/PeiLib.c b/Library/PeiLib.c
new file mode 100644
index 0000000..c3f859e
--- /dev/null
+++ b/Library/PeiLib.c
@@ -0,0 +1,1132 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/PeiLib.c 1 4/16/14 3:10a Chaseliu $
+//
+// $Revision: 1 $
+//
+// $Date: 4/16/14 3:10a $
+//*************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/PeiLib.c $
+//
+// 1 4/16/14 3:10a Chaseliu
+// [TAG] EIP163569
+// [Category] Improvement
+// [Description] Update for support 2014 BIOS Security Disclosures.
+// [Files]
+// Library\PeiLib.c
+// Library\EfiLib.c
+// Core\EM\NVRAM\NVRAMDXE.c
+// Core\EM\Capsule2_0\Capsule2_0.c
+// Core\CORE_DXE\FwVolBlock.c
+//
+// 29 2/28/14 5:41p Artems
+// EIP 154195 Fixed vulnerability where memory pointer was stored in NVRaM
+// and may be compromised
+//
+// 27 8/12/11 12:25p Artems
+// EIP 64107: Added changes for module to be compliant with PI
+// specification v 1.2
+//
+// 26 5/27/11 5:59p Felixp
+// PeiGetNextVariableName is updated:
+// The GetNextVariableName function has been renamed to NextVariableName
+// to comply with the specification.
+//
+// 25 2/05/11 3:14p Artems
+// Added compatibility functions to work in both PI 0.91 and PI 1.0
+// versions
+//
+// 24 11/05/10 2:47p Artems
+// EIP 44635 - removed commented out string
+//
+// 23 10/12/10 5:15p Artems
+// EIP 44635 Added token MAX_PEI_PERF_LOG_ENTRIES
+//
+// 22 11/25/09 1:32p Felixp
+// PeiTrace functions is updated to suppress Trace message
+// if message Level defined by the first parameter is disabled using
+// TRACE_LEVEL_MASK SDL token.
+//
+// 21 7/30/09 4:45p Vyacheslava
+// Fixed comments.
+//
+// 20 7/28/09 4:55p Vyacheslava
+// Minor bug fix. EIP#24453: Synopsis: CPU exception when printing long
+// debug messages.
+//
+// 19 7/10/09 3:49p Felixp
+// Function headers added
+//
+// 18 6/06/08 10:54a Felixp
+// SaveS3PerformanceData routine added
+//
+// 17 5/07/08 12:22p Felixp
+// Performance API added
+//
+// 16 10/22/07 6:24p Felixp
+// FindFfsFileByName routine added.
+//
+// 15 8/30/07 11:01p Felixp
+// PeiGetVariable and PeiGetNextVariableName routines added.
+//
+// 14 3/13/07 1:40a Felixp
+//
+// 13 8/24/06 9:27a Felixp
+// Preliminary x64 support (work in progress)
+//
+// 12 3/13/06 1:50a Felixp
+//
+// 11 12/09/05 2:08p Felixp
+//
+// 10 10/11/05 2:43p Felixp
+//
+// 9 10/09/05 8:52p Felixp
+//
+// 8 10/09/05 4:54p Felixp
+//
+// 7 10/09/05 4:14p Felixp
+//
+// 6 10/09/05 11:27a Felixp
+// Support for performance measurements added.
+//
+// 5 6/16/05 10:48a Felixp
+// CreateLoadHob function added (used by PEIMs to reguest reallocation to
+// RAM,
+// once memory is detected)
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 12/23/04 9:42a Felixp
+//
+// 2 11/10/04 5:16p Felixp
+// Level parameter added to PeiTrace fucntion
+//
+// 1 11/02/04 5:30p Felixp
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PeiLib.c
+//
+// Description:
+// Contains an assortment of localized PEI library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+
+#include <Token.h>
+#include <AmiPeiLib.h>
+#include <StatusCodes.h>
+#include <AmiHobs.h>
+#include <PPI/ReadOnlyVariable2.h>
+#include <PPI/LoadFile.h>
+#include <Protocol/Performance.h>
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PeiTrace
+//
+// Description:
+// VOID PeiTrace(IN UINTN Level, IN EFI_PEI_SERVICES **ppPS,
+// IN CHAR8 *sFormat, IN ...) prints a debug message using the
+// ReportStatusCode from PEI Services if the specified error level is
+// enabled.
+//
+// Input:
+// IN UINTN Level
+// The error level of the debug message.
+//
+// IN EFI_PEI_SERVICES **ppPS
+// Double pointer to PEI Services Table.
+//
+// IN CHAR8 *sFormat
+// Format string for the debug message to print.
+//
+// IN ...
+// Additional parameters utilized by the format string.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+// PrepareStatusCodeString
+// va_start
+// va_end
+// PEI_TRACE
+// Sprintf
+//
+// Notes:
+// Use the PEI_TRACE macro for debug messages in PEI! This allows the
+// DEBUG_MODE token to control the inclusion of debug messages. See
+// Sprintf function for format string syntax.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+VOID PeiTrace(UINTN Level, CONST EFI_PEI_SERVICES **ppPS, CHAR8 *sFormat,...)
+{
+ CHAR8 Buffer[256];
+ extern const UINT32 TraceLevelMask;
+ va_list ArgList;
+ if ( (Level & TraceLevelMask) == 0 ) return;
+ ArgList = va_start(ArgList,sFormat);
+ PrepareStatusCodeString( Buffer, sizeof(Buffer), sFormat, ArgList );
+ (*ppPS)->ReportStatusCode (
+ (EFI_PEI_SERVICES**)ppPS, EFI_DEBUG_CODE,
+ EFI_SOFTWARE_UNSPECIFIED, 0, NULL,
+ (EFI_STATUS_CODE_DATA *)Buffer
+ );
+ va_end(ArgList);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: CreateHobMemoryAllocationModule
+//
+// Description:
+// EFI_STATUS CreateHobMemoryAllocationModule(
+// IN EFI_PEI_SERVICES **PeiServices,
+// IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, IN UINT64 MemoryLength,
+// IN EFI_MEMORY_TYPE MemoryType, IN EFI_GUID *ModuleName,
+// IN EFI_PHYSICAL_ADDRESS EntryPoint) adds a memory allocation HOB with a
+// memory allocation module GUID using CreateHob from PEI Services.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to PEI Services Table.
+//
+// IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
+// The physical address of the module.
+//
+// IN UINT64 MemoryLength
+// The length of the module in bytes.
+//
+// IN EFI_MEMORY_TYPE MemoryType
+// Module memory type.
+//
+// IN EFI_GUID *ModuleName
+// The GUID File Name of the module.
+//
+// IN EFI_PHYSICAL_ADDRESS EntryPoint
+// The 64-bit physical address of the module's entry point.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if Hob = NULL.
+// EFI_OUT_OF_RESOURCES, if there is not enough space to create HOB.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS CreateHobMemoryAllocationModule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
+ IN UINT64 MemoryLength, IN EFI_MEMORY_TYPE MemoryType,
+ IN EFI_GUID *ModuleName,
+ IN EFI_PHYSICAL_ADDRESS EntryPoint
+)
+{
+ static EFI_GUID gHobMemAllocModGuid=EFI_HOB_MEMORY_ALLOC_MODULE_GUID;
+ EFI_STATUS Status;
+ EFI_HOB_MEMORY_ALLOCATION_MODULE *MemAllocModHob;
+
+ Status = (*PeiServices)->CreateHob(
+ PeiServices,
+ EFI_HOB_TYPE_MEMORY_ALLOCATION,
+ sizeof(EFI_HOB_MEMORY_ALLOCATION_MODULE),
+ &MemAllocModHob);
+ if (Status != EFI_SUCCESS) return Status;
+ MemAllocModHob->MemoryAllocationHeader.Name=gHobMemAllocModGuid;
+ MemAllocModHob->MemoryAllocationHeader.MemoryBaseAddress=MemoryBaseAddress;
+ MemAllocModHob->MemoryAllocationHeader.MemoryLength=MemoryLength;
+ MemAllocModHob->MemoryAllocationHeader.MemoryType=MemoryType;
+ *(UINT32*)&MemAllocModHob->MemoryAllocationHeader.Reserved=0;
+ MemAllocModHob->ModuleName=*ModuleName;
+ MemAllocModHob->EntryPoint=EntryPoint;
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: CreateHobResourceDescriptor
+//
+// Description:
+// EFI_STATUS CreateHobResourceDescriptor(IN EFI_PEI_SERVICES **PeiServices,
+// IN EFI_GUID *Owner, IN EFI_RESOURCE_TYPE ResourceType,
+// IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+// IN EFI_PHYSICAL_ADDRESS PhysicalStart, IN UINT64 ResourceLength) builds a
+// resource descriptor HOB that describes a chunk of system memory using
+// CreateHob from PEI Services.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to the PEI Services Table.
+//
+// IN EFI_GUID *Owner
+// GUID of the owner of this resource. Make this NULL if there is none.
+//
+// IN EFI_RESOURCE_TYPE ResourceType
+// The type of resource described by this HOB.
+//
+// IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute
+// The resource attributes of the memory described by this HOB.
+//
+// IN EFI_PHYSICAL_ADDRESS PhysicalStart
+// The 64-bit physical address of memory described by this HOB.
+//
+// IN UINT64 ResourceLength
+// The length of the memory described by this HOB in bytes.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if HOB = NULL.
+// EFI_OUT_OF_RESOURCES, if there is not enough space to create HOB.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS CreateHobResourceDescriptor
+(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_GUID *Owner, IN EFI_RESOURCE_TYPE ResourceType,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 ResourceLength
+)
+{
+ EFI_STATUS Status;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
+
+ Status = (*PeiServices)->CreateHob(
+ PeiServices,
+ EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
+ sizeof(EFI_HOB_RESOURCE_DESCRIPTOR),
+ &ResHob);
+ if (Status != EFI_SUCCESS) return Status;
+
+ ResHob->Owner=*Owner;
+ ResHob->ResourceType=ResourceType;
+ ResHob->ResourceAttribute=ResourceAttribute;
+ ResHob->PhysicalStart=PhysicalStart;
+ ResHob->ResourceLength=ResourceLength;
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: CreateLoadHob
+//
+// Description:
+// EFI_STATUS CreateLoadHob(IN EFI_PEI_SERVICES **ppPS,
+// IN EFI_FFS_FILE_HEADER *pFfsHeader, EFI_PEIM_ENTRY_POINT EntryPoint,
+// EFI_PEIM_ENTRY_POINT InMemEntryPoint) builds a EFI_HOB_TYPE_GUID_EXTENSION
+// HOB with a PEIM load HOB.
+//
+// Input:
+// IN EFI_PEI_SERVICES **ppPS
+// Double pointer to the PEI Services Table.
+//
+// IN EFI_FFS_FILE_HEADER *pFfsHeader
+// Pointer to the desired FFS header.
+//
+// EFI_PEIM_ENTRY_POINT EntryPoint
+// Pointer to the FFS entry point.
+//
+// EFI_PEIM_ENTRY_POINT InMemEntryPoint
+// Pointer to the FFS entry point in memory.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if HOB = NULL.
+// EFI_OUT_OF_RESOURCES, if not enough space to create HOB.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS CreateLoadHob(
+ IN EFI_PEI_SERVICES **ppPS, IN EFI_FFS_FILE_HEADER *pFfsHeader,
+ EFI_PEIM_ENTRY_POINT EntryPoint, EFI_PEIM_ENTRY_POINT InMemEntryPoint
+)
+{
+ EFI_STATUS Status;
+ PEIM_LOAD_HOB *pHob;
+ static EFI_GUID guidAmiPeimLoadHob = AMI_PEIM_LOAD_HOB_GUID;
+
+ Status=(*ppPS)->CreateHob(ppPS, EFI_HOB_TYPE_GUID_EXTENSION, sizeof(PEIM_LOAD_HOB),&pHob);
+ if (!EFI_ERROR(Status))
+ {
+ pHob->Header.Name = guidAmiPeimLoadHob;
+ pHob->pFfsHeader = pFfsHeader;
+ pHob->EntryPoint = EntryPoint;
+ pHob->InMemEntryPoint= InMemEntryPoint;
+ }
+ return Status;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PeiGetVariable
+//
+// Description:
+// EFI_STATUS PeiGetNextVariableName(IN EFI_PEI_SERVICES **PeiServices,
+// IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VariableGuid,
+// OUT UINT32 *Attributes, IN OUT UINTN *DataSize, OUT VOID *Data) reads an
+// EFI variable; it serves as a wrapper for the Read Only Variable PPI
+// GetVariable routine. The functions first locates the Read Only Variable
+// PPI instance, then makes a call to the GetVariable routine and returns
+// the EFI_STATUS of the GetVariable call.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to the PEI Services Table.
+//
+// IN CONST CHAR16 *VariableName
+// A pointer to a null-terminated string that is the variable's name.
+//
+// IN CONST EFI_GUID *VariableGuid
+// A pointer to an EFI_GUID that is the variable's GUID. The combination of
+// VariableGuid and VariableName must be unique.
+//
+// OUT UINT32 *Attributes
+// If non-NULL, on return, points to the variable's attributes.
+//
+// IN OUT UINTN *DataSize
+// On entry, points to the size in bytes of the Data buffer. On return,
+// points to the size of the data returned in Data.
+//
+// OUT VOID *Data
+// Points to the buffer which will hold the returned variable value. The
+// user is responsible for allocating this memory!
+//
+// Output:
+// EFI_BUFFER_TOO_SMALL, if DataSize is too small to hold the contents of
+// the variable. DataSize will be set to show the
+// minimum required size.
+// EFI_INVALID_PARAMETER, if VariableName, VariableGuid, DataSize, or Data
+// are equal to NULL.
+// EFI_DEVICE_ERROR, if variable could not be retrieved because of a
+// device error.
+// EFI_NOT_FOUND, if the variable or Read Only Variable PPI could
+// not be found.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// See Platform Initialization Specification for details regarding the
+// Read Only Variable PPI and GetVariable.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS PeiGetVariable(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VariableGuid,
+ OUT UINT32 *Attributes,
+ IN OUT UINTN *DataSize, OUT VOID *Data
+)
+{
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;
+ EFI_STATUS Status = (*PeiServices)->LocatePpi(
+ PeiServices, &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, &VariablePpi
+ );
+ if (EFI_ERROR(Status)) return Status;
+ return VariablePpi->GetVariable(
+ VariablePpi,VariableName, VariableGuid, Attributes, DataSize, Data
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PeiGetNextVariableName
+//
+// Description:
+// EFI_STATUS PeiGetNextVariableName(IN EFI_PEI_SERVICES **PeiServices,
+// IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName,
+// IN OUT EFI_GUID *VariableGuid) performs enumeration of the EFI variables.
+// This function serves as a wrapper for the Read Only Variable PPI
+// GetNextVariableName routine. It locates the Read Only Variable PPI
+// instance, then makes a call to the GetNextVariableName routine and returns
+// its EFI_STATUS.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to the PEI Services Table.
+//
+// IN OUT UINTN *VariableNameSize
+// On entry, points to the size of the buffer pointed to by VariableName.
+// If function returns EFI_BUFFER_TOO_SMALL, VariableNameSize is updated to
+// reflect the buffer size required for the next variable's name.
+//
+// IN OUT CHAR16 *VariableName
+// On entry, a pointer to a null-terminated string that is the variable's
+// name. On return, points to the next variable's null-terminated name
+// string.
+//
+// IN OUT EFI_GUID *VariableGuid
+// On entry, a pointer to an UEFI _GUID that is the variable's GUID. On
+// return, a pointer to the next variable's GUID.
+//
+// Output:
+// EFI_NOT_FOUND, if the variable or Read Only Variable PPI could
+// not be found.
+// EFI_BUFFER_TOO_SMALL, if VariableNameSize is too small for the resulting
+// data. VariableNameSize is updated with the size
+// required for the specified variable.
+// EFI_INVALID_PARAMETER, if VariableName, VariableNameSize, or VariableGuid
+// are NULL.
+// EFI_DEVICE_ERROR, if the variable could not be retrieved because of
+// a device error.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// See the Platform Initialization Specification for details regarding
+// the Read Only Variable PPI and NextVariableName.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS PeiGetNextVariableName(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName,
+ IN OUT EFI_GUID *VariableGuid
+)
+{
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;
+ EFI_STATUS Status = (*PeiServices)->LocatePpi(
+ PeiServices, &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, &VariablePpi
+ );
+ if (EFI_ERROR(Status)) return Status;
+ return VariablePpi->NextVariableName(
+ VariablePpi,VariableNameSize, VariableName, VariableGuid
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: FindFfsFileByName
+//
+// Description:
+// VOID* FindFfsFileByName(IN EFI_PEI_SERVICES **PeiServices,
+// IN EFI_FV_FILETYPE FileType, IN EFI_GUID *FileName) scans all available
+// firmware volumes for a FFS file of type FileType with GUID equal to
+// FileName and returns the address of the first byte of the FFS file data.
+// If more than one file matches the criteria, the function returns the
+// address of the first file found.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to the PEI Services Table.
+//
+// IN EFI_FV_FILETYPE FileType
+// Type of FFS file to find.
+//
+// IN EFI_GUID *FileName
+// GUID of FFS file to find.
+//
+// Output:
+// VOID* pointer to the first byte of the FFS file data. Returns NULL if no
+// FFS file found.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* FindFfsFileByName(
+ IN EFI_PEI_SERVICES **PeiServices, EFI_FV_FILETYPE FileType,
+ EFI_GUID *FileName
+){
+ EFI_FIRMWARE_VOLUME_HEADER* pFV;
+ UINTN FvNum=0;
+ //loop over all FV
+ while( !EFI_ERROR ((*PeiServices)->FfsFindNextVolume (PeiServices, FvNum++, &pFV) ) ){
+ EFI_FFS_FILE_HEADER* pFile = NULL;
+ EFI_STATUS Status;
+ // loop over raw files within FV
+ while(TRUE){
+ Status = (*PeiServices)->FfsFindNextFile(PeiServices, FileType, pFV, &pFile);
+ if( EFI_ERROR(Status) ) break;
+ //make sure this is our RAW file.
+ //guidcmp works like strcmp. It returns 0 when GUIDs are the same.
+ if (guidcmp(&pFile->Name,&FileName)) continue;
+ //skip file header
+ return pFile+1;
+ }
+ }
+ return NULL;
+}
+
+//****************************************************************************
+// PERFORMANCE MEASUREMENT DEFINITIONS
+//****************************************************************************
+static EFI_GUID gEfiPeiPerformanceHobGuid = EFI_PEI_PERFORMANCE_HOB_GUID;
+
+#define EFI_PERF_PEI_ENTRY_MAX_NUM 50
+
+typedef struct {
+ CHAR8 Token[EFI_PERF_PDBFILENAME_LENGTH];
+ UINT32 Duration;
+} EFI_PERF_DATA;
+
+typedef struct {
+ UINT64 BootToOs;
+ UINT64 S3Resume;
+ UINT32 S3EntryNum;
+ EFI_PERF_DATA S3Entry[EFI_PERF_PEI_ENTRY_MAX_NUM];
+ UINT64 CpuFreq;
+ UINT64 BDSRaw;
+ UINT32 Count;
+ UINT32 Signiture;
+} EFI_PERF_HEADER;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PEI_PERF_START
+//
+// Description:
+// PEI_PERF_START(Ps, Token, FileHeader, Value) is a macro which invokes
+// the PeiPerfMeasure function to log a timer entry for measuring performance
+// if the PEI_PERFORMANCE SDL token is turned on. If the PEI_PERFORMANCE SDL
+// token is turned off, the macro does nothing.
+//
+// Input:
+// IN EFI_PEI_SERVICES **Ps
+// Double pointer to the PEI Services Table.
+//
+// IN CHAR16 *Token
+// Pointer to token name.
+//
+// IN EFI_FFS_FILE_HEADER *FileHeader
+// Pointer to the file header.
+//
+// IN UINT64 Value
+// A non-zero value indicates the start time. Otherwise, GetCpuTimer is used
+// to get the current CPU timer value.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+// PeiPerfMeasure
+// GetCpuTimer
+//
+// Notes:
+// This macro is defined in AmiPeiLib.h.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PEI_PERF_END
+//
+// Description:
+// PEI_PERF_END(Ps, Token, FileHeader, Value) is a macro which invokes
+// the PeiPerfMeasure function to stop timing for an entry to determine
+// performance if the PEI_PERFORMANCE SDL token is turned on. If the
+// PEI_PERFORMANCE SDL token is turned off, the macro does nothing.
+//
+// Input:
+// IN EFI_PEI_SERVICES **Ps
+// Double pointer to the PEI Services Table.
+//
+// IN CHAR16 *Token
+// Pointer to token name.
+//
+// IN EFI_FFS_FILE_HEADER *FileHeader
+// Pointer to the file header.
+//
+// IN UINT64 Value
+// A non-zero value indicates the stop time. Otherwise, GetCpuTimer is used
+// to get the current CPU timer value.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+// PeiPerfMeasure
+// GetCpuTimer
+//
+// Notes:
+// This macro is defined in AmiPeiLib.h.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PEI_PERF_SAVE_S3_DATA
+//
+// Description:
+// PEI_PERF_SAVE_S3_DATA(Ps) is a macro which invokes the
+// SaveS3PerformanceData function in order to save the S3 performance data in
+// an EFI PEI performance HOB. This should only be called once, just before
+// the end of PEI.
+//
+// Input:
+// IN EFI_PEI_SERVICES **Ps
+// Double pointer to the PEI Services Table.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+// SaveS3PerformanceData
+//
+// Notes:
+// This macro is defined in AmiPeiLib.h.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: PeiPerfMeasure
+//
+// Description:
+// VOID PeiPerfMeasure(IN EFI_PEI_SERVICES **PeiServices, IN CHAR16 *Token,
+// IN EFI_FFS_FILE_HEADER *FileHeader, IN BOOLEAN EntryExit, IN UINT64 Value)
+// logs a timestamp count for measuring performance. See the notes for
+// proper usage.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to the PEI Services Table.
+//
+// IN CHAR16 *Token
+// Pointer to token name.
+//
+// IN EFI_FFS_FILE_HEADER *FileHeader
+// Pointer to the file header.
+//
+// IN BOOLEAN EntryExit
+// FALSE indicates start, TRUE indicates stop.
+//
+// IN UINT64 Value
+// If EntryExit is TRUE, a non-zero value indicates stop time. Otherwise if
+// EntryExit is FALSE, a non-zero value indicates start time.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+// GetCpuTimer
+//
+// Notes:
+// Use the PEI_PERF_START and PEI_PERF_END macros; this allows performance
+// monitoring to be enabled or disabled with the PEI_PERFORMANCE SDL token.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID PeiPerfMeasure (
+ EFI_PEI_SERVICES **PeiServices,
+ IN CHAR16 *Token, IN EFI_FFS_FILE_HEADER *FileHeader,
+ IN BOOLEAN EntryExit, IN UINT64 Value
+)
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *Hob;
+ EFI_HOB_GUID_DATA_PERFORMANCE_LOG *PerfHobData;
+ PEI_PERFORMANCE_MEASURE_LOG_ENTRY *Log;
+ EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor;
+ UINT64 TimeCount;
+ UINTN Index;
+ UINTN Index2;
+ EFI_GUID *Guid;
+ EFI_GUID *CheckGuid;
+
+ TimeCount = 0;
+ //
+ // Get the END time as early as possible to make it more accurate.
+ //
+ if (EntryExit) {
+ TimeCount = GetCpuTimer();
+ }
+
+ //
+ // Locate the Pei Performance Log Hob.
+ //
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiPeiPerformanceHobGuid,
+ 0,
+ &PerfHobDescriptor,
+ NULL
+ );
+
+ //
+ // If the Performance Hob was not found, build and install one.
+ //
+ if (EFI_ERROR(Status)) {
+ Status = (*PeiServices)->CreateHob (
+ PeiServices,
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof (EFI_HOB_GUID_TYPE) +
+ sizeof(EFI_HOB_GUID_DATA_PERFORMANCE_LOG) +
+ (MAX_PEI_PERF_LOG_ENTRIES-1) * sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) +
+ sizeof(EFI_PEI_PPI_DESCRIPTOR),
+ &Hob
+ );
+ ASSERT_PEI_ERROR(PeiServices, Status);
+ Hob->Name = gEfiPeiPerformanceHobGuid;
+ PerfHobData = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *)(Hob+1);
+ PerfHobData->NumberOfEntries = 0;
+ PerfHobDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)((UINT8 *)(PerfHobData+1) +
+ (sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) *
+ (MAX_PEI_PERF_LOG_ENTRIES-1)
+ )
+ );
+ PerfHobDescriptor->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ PerfHobDescriptor->Guid = &gEfiPeiPerformanceHobGuid;
+ PerfHobDescriptor->Ppi = NULL;
+
+ (*PeiServices)->InstallPpi (
+ PeiServices,
+ PerfHobDescriptor
+ );
+ }
+
+ PerfHobData = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *)(((UINT8 *)(PerfHobDescriptor)) -
+ ((sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) *
+ (MAX_PEI_PERF_LOG_ENTRIES-1)
+ )
+ + sizeof(EFI_HOB_GUID_DATA_PERFORMANCE_LOG)
+ )
+ );
+
+ if (PerfHobData->NumberOfEntries >= MAX_PEI_PERF_LOG_ENTRIES) {
+ return;
+ }
+
+ if (!EntryExit) {
+ Log = &(PerfHobData->Log[PerfHobData->NumberOfEntries]);
+ (*PeiServices)->SetMem (Log, sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY), 0);
+
+ //
+ // If not NULL pointer, copy the file name
+ //
+ if (FileHeader != NULL) {
+ Log->Name = FileHeader->Name;
+ }
+
+ //
+ // Copy the description string
+ //
+ (*PeiServices)->CopyMem (
+ &(Log->DescriptionString),
+ Token,
+ (PEI_PERF_MAX_DESC_STRING-1) * sizeof(UINT16)
+ );
+
+ //
+ // Get the start time as late as possible to make it more accurate.
+ //
+ TimeCount = GetCpuTimer();
+
+ //
+ // Record the time stamp.
+ //
+ if (Value != 0) {
+ Log->StartTimeCount = Value;
+ } else {
+ Log->StartTimeCount = TimeCount;
+ }
+ Log->StopTimeCount = 0;
+
+ //
+ // Increment the number of valid log entries.
+ //
+ PerfHobData->NumberOfEntries++;
+
+ } else {
+
+ for (Index = PerfHobData->NumberOfEntries-1; Index >= 0; Index--) {
+ Log = NULL;
+ for (Index2 = 0; Index2 < PEI_PERF_MAX_DESC_STRING; Index2++) {
+ if (PerfHobData->Log[Index].DescriptionString[Index2] == 0) {
+ Log = &(PerfHobData->Log[Index]);
+ break;
+ }
+ if (PerfHobData->Log[Index].DescriptionString[Index2] !=
+ Token[Index2]) {
+ break;
+ }
+ }
+ if (Log != NULL) {
+ if (FileHeader != NULL) {
+ Guid = &(Log->Name);
+ CheckGuid = &(FileHeader->Name);
+ if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
+ (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
+ (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
+ (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) {
+ if (Value != 0) {
+ Log->StopTimeCount = Value;
+ } else {
+ Log->StopTimeCount = TimeCount;
+ }
+ break;
+ }
+ } else {
+ if (Value != 0) {
+ Log->StopTimeCount = Value;
+ } else {
+ Log->StopTimeCount = TimeCount;
+ }
+ break;
+ }
+ }
+ }
+
+ }
+
+ return;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: SaveS3PerformanceData
+//
+// Description:
+// VOID SaveS3PerformanceData(IN EFI_PEI_SERVICES **PeiServices) saves the
+// S3 performance data in an EFI PEI performance HOB. This should only be
+// called once, just before the end of PEI. See notes for proper usage.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// Double pointer to PEI Services Table.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+// GetCpuTimer
+//
+// Notes:
+// To use this function properly, use the PEI_PERF_SAVE_S3_DATA macro. This
+// allows the PEI_PERFORMANCE SDL token to control enabling and disabling
+// performance measurements.
+// The PEI_PERF_SAVE_S3_DATA macro is used by S3Resume module to log performance data.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID SaveS3PerformanceData(IN EFI_PEI_SERVICES **PeiServices){
+ static EFI_GUID gEfiPeiPerformanceHobGuid = EFI_PEI_PERFORMANCE_HOB_GUID;
+ EFI_STATUS Status;
+ UINT64 Time;
+ UINTN VarSize;
+ EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+ EFI_PERF_HEADER *PerfHeader;
+ EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;
+ UINT32 i;
+ UINT32 j;
+ EFI_HOB_GUID_DATA_PERFORMANCE_LOG *LogHob;
+ PEI_PERFORMANCE_MEASURE_LOG_ENTRY *LogEntry;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Time = GetCpuTimer();
+ VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ Status = PeiGetVariable(
+ PeiServices,
+ L"PerfDataMemAddrInternal", &gAmiGlobalVariableGuid,
+ NULL, &VarSize, &AcpiLowMemoryBase
+
+ );
+ if (EFI_ERROR (Status)) return;
+
+ PerfHeader = (EFI_PERF_HEADER *) ((UINT32) AcpiLowMemoryBase);
+ *((UINT64 *) (&PerfHeader->S3Resume)) = Time;
+ // Get S3 detailed performance data
+ PerfHeader->S3EntryNum = 0;
+
+ (*PeiServices)->GetHobList (PeiServices, &Hob.Raw);
+ Status = FindNextHobByGuid(&gEfiPeiPerformanceHobGuid,&Hob.Raw);
+ if (EFI_ERROR (Status)) return;
+ LogHob = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));
+
+ for( i = 0;
+ ((i < LogHob->NumberOfEntries) && (PerfHeader->S3EntryNum < EFI_PERF_PEI_ENTRY_MAX_NUM));
+ i++
+ ){
+ LogEntry = &(LogHob->Log[i]);
+ if (LogEntry->StopTimeCount == 0) {
+ continue;
+ }
+ for (j = 0; j < 8; j++) {
+ PerfHeader->S3Entry[PerfHeader->S3EntryNum].Token[j] = (CHAR8) (LogEntry->DescriptionString[j]);
+ }
+ PerfHeader->S3Entry[PerfHeader->S3EntryNum].Duration = (UINT32) Div64 (
+ LogEntry->StopTimeCount - LogEntry->StartTimeCount,
+ (UINT32) PerfHeader->CpuFreq,
+ NULL
+ );
+ PerfHeader->S3EntryNum++;
+ }
+}
+
+EFI_STATUS PeiLoadFile(
+ IN CONST EFI_PEI_SERVICES ** PeiServices,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+){
+#if PI_SPECIFICATION_VERSION < 0x00010000
+ EFI_PEI_FV_FILE_LOADER_PPI *Loader;
+#else
+ EFI_PEI_LOAD_FILE_PPI *Loader;
+ UINT32 AuthenticationState;
+#endif;
+ EFI_PEI_PPI_DESCRIPTOR *Dummy;
+ EFI_STATUS Status = (*PeiServices)->LocatePpi(
+ (EFI_PEI_SERVICES**)PeiServices,
+ &gEfiPeiLoadFilePpiGuid,0, &Dummy, &Loader
+ );
+ if ((EFI_ERROR(Status))) return Status;
+ return
+#if PI_SPECIFICATION_VERSION < 0x00010000
+ Status = Loader->FvLoadFile(
+#else
+ Status = Loader->LoadFile(
+#endif
+ Loader, FileHandle, ImageAddress, ImageSize, EntryPoint
+#if PI_SPECIFICATION_VERSION >= 0x00010000
+ ,&AuthenticationState
+#endif
+ );
+}
+
+#if PI_SPECIFICATION_VERSION >= 0x00010000
+#pragma pack (1)
+typedef struct {
+ UINT16 Limit;
+ UINTN Base;
+} DESCRIPTOR_TABLE;
+#pragma pack()
+
+VOID CPULib_SaveIdt(DESCRIPTOR_TABLE *Idt);
+
+EFI_PEI_SERVICES ** GetPeiServicesTablePointer (VOID){
+ EFI_PEI_SERVICES **PeiServices;
+ DESCRIPTOR_TABLE Idtr;
+
+ CPULib_SaveIdt (&Idtr);
+ PeiServices = (EFI_PEI_SERVICES **) (*(UINTN*)(Idtr.Base - sizeof (UINTN)));
+ return PeiServices;
+}
+
+VOID SetPeiServicesTablePointer (
+ IN CONST EFI_PEI_SERVICES ** PeiServicesTablePointer
+){
+ DESCRIPTOR_TABLE Idtr;
+
+ CPULib_SaveIdt (&Idtr);
+ (*(UINTN*)(Idtr.Base - sizeof (UINTN))) = (UINTN)PeiServicesTablePointer;
+}
+#else
+EFI_PEI_SERVICES ** GetPeiServicesTablePointer (VOID){
+_asm {
+ push eax
+ push eax
+ movq [esp], mm7
+ pop eax
+ pop edx
+ emms
+ }
+}
+#endif
+
+EFI_STATUS PciCfgModify(
+ IN CONST EFI_PEI_SERVICES ** PeiServices,
+ IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN SetBits,
+ IN UINTN ClearBits
+){
+ if ((*PeiServices)->PciCfg==NULL) return EFI_NOT_AVAILABLE_YET;
+ return (*PeiServices)->PciCfg->Modify(
+ (EFI_PEI_SERVICES**)PeiServices, (*PeiServices)->PciCfg,
+ Width, Address,
+#if PI_SPECIFICATION_VERSION < 0x00010000
+ SetBits, ClearBits
+#else
+ &SetBits, &ClearBits
+#endif
+ );
+}
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************