diff options
Diffstat (limited to 'Core/CORE_PEI')
41 files changed, 15329 insertions, 0 deletions
diff --git a/Core/CORE_PEI/AmiPeiInit.c b/Core/CORE_PEI/AmiPeiInit.c new file mode 100644 index 0000000..33931ae --- /dev/null +++ b/Core/CORE_PEI/AmiPeiInit.c @@ -0,0 +1,887 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/EDK/PeiMain/AmiPeiInit.c 24 5/13/11 5:10p Artems $ +// +// $Revision: 24 $ +// +// $Date: 5/13/11 5:10p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/EDK/PeiMain/AmiPeiInit.c $ +// +// 24 5/13/11 5:10p Artems +// Added functions CopyMem and ZeroMem for PEI build +// +// 23 3/22/11 5:20p Felixp +// LOAD_HOB processing and AmiInitParts-related code has been restructured +// to achieve the following goals: +// - Support LOAD_HOB in PI mode +// - Reduce amount of PI version specific code +// - Minimize number of patches in the EDK portion of code +// - Eliminate global variables +// - Simplify the implementation +// +// 22 3/09/11 5:53p Artems +// Removed usage of global pointer InitFunction. Fixed bug in +// MigrateIdtTable with wrong IdtBase +// +// 21 3/08/11 10:22a Artems +// Fixed bug in MigrateIdtTable, where IdtBase assigned wrong address +// +// 20 3/04/11 4:06p Artems +// Modified FindPPI function to work with both FV hob types +// +// 19 2/05/11 3:42p Artems +// Added PI 1.0 support +// +// 18 9/22/10 7:13p Felixp +// Imrpovement: gEfiStatusCodeSpecificDataGuid variable is added. Used by +// PEI Core to report status codes. +// +// 17 8/20/10 3:26p Felixp +// LZMA compression support: ReadSection function updated. +// +// 16 8/28/09 3:08p Felixp +// More generic FindFv PPI implementation. Old implementation was assuming +// that boot FV is described by the first FV HOB. +// +// 15 8/27/09 1:58p Felixp +// AmiInitParts is updated to call InitFunction once when AmiInitParts is +// called multiple times. +// +// 14 7/30/09 4:46p Vyacheslava +// Fixed comments. +// +// 13 7/28/09 4:56p Vyacheslava +// Minor bug fix. EIP#24453: Synopsis: CPU exception when printing long +// debug messages. +// +// 12 5/04/09 3:09p Felixp +// Creation of CPU HOB moved from AmiPeiInit.c to AmiDxeInit.c +// +// 11 8/07/07 2:24p Felixp +// Additional Status Codes added +// +// 10 3/12/07 10:26a Felixp +// LoadedImage PPI support added (defined in PI 1.0; used by AmiDebugger) +// +// 8 10/18/06 11:30a Felixp +// LoadFile updated to return EFI_LOAD_ERROR when image format is invalid +// +// 7 8/24/06 9:43a Felixp +// Preliminary x64 support (work in progress) +// DXE Core interfaces are no longer passed from PEI Core. +// They are linked directly with DXE Core +// +// 6 6/04/06 9:20p Ambikas +// +// 5 5/30/06 7:06p Yakovlevs +// Fixed STACK HOB memory type from ConventionalMemory to EfiLoaderData. +// +// 4 5/20/06 12:58a Felixp +// +// 3 5/20/06 12:36a Felixp +// checkpoints added +// +// 2 5/19/06 10:38p Felixp +// Clean up +// +// 1 3/13/06 1:57a Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: AmiPeiInit.c +// +// Description: +// +//<AMI_FHDR_END> +//********************************************************************** +#include <AmiHobs.h> +#include <AmiPeiLib.h> +#include <PPI/LoadFile.h> +#include <PPI/LoadedImagePpi.h> +#include <PPI/Decompress.h> +#include <StatusCodes.h> + +typedef VOID (*INIT_PARTS)(VOID* p1, VOID*p2); +VOID InitParts(VOID* p1, VOID*p2); +VOID InitParts2(VOID* p1, VOID*p2); + +EFI_GUID gEfiStatusCodeSpecificDataGuid = EFI_STATUS_CODE_SPECIFIC_DATA_GUID; + +//defined in PeiMain.c +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +); +////////////// from PeiCore.c +#if PI_SPECIFICATION_VERSION<0x00010000 +EFI_PEI_SERVICES **ppPS = NULL; +#endif + +VOID InitPartsMem(VOID* p1, VOID*p2) +{ +#if PI_SPECIFICATION_VERSION<0x00010000 + ppPS = (EFI_PEI_SERVICES**)p2; +#endif + InitParts2(p1,p2); +} + +#if PI_SPECIFICATION_VERSION<0x00010000 +EFI_STATUS FvLoadFile( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint +); + +// PPIs +EFI_PEI_FV_FILE_LOADER_PPI FileLoader = {FvLoadFile}; + +// PPI to be installed +EFI_GUID gPeiLoadFilePpiGuid = EFI_PEI_FV_FILE_LOADER_GUID; +static EFI_PEI_PPI_DESCRIPTOR FileLoaderPpi[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiLoadFilePpiGuid, &FileLoader + } +}; + +EFI_STATUS ReadSection( + EFI_PEI_SERVICES **ppPS, IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *pFile, OUT VOID **ppData +) +{ + EFI_STATUS Status; + UINT32 SrcSize, DstSize, TmpSize; + VOID *pSrc; + EFI_PHYSICAL_ADDRESS DstAddress; + EFI_HOB_HANDOFF_INFO_TABLE *pHob; + EFI_COMPRESSION_SECTION_HEADER *pCompressionSection; + if (!ppData) return EFI_INVALID_PARAMETER; + //TODO: Support for GUIDed sections + Status = (*ppPS)->FfsFindSectionData( + ppPS, SectionType, pFile, &pSrc + ); + if (!EFI_ERROR(Status)){*ppData=pSrc; return Status; } + Status = (*ppPS)->FfsFindSectionData( + ppPS, EFI_SECTION_COMPRESSION, + pFile, &pCompressionSection + ); + if (EFI_ERROR(Status)) return Status; + SrcSize = FVSECTION_SIZE(pCompressionSection) - sizeof(EFI_COMPRESSION_SECTION_HEADER); + pSrc = pCompressionSection + 1; + if (pCompressionSection->CompressionType!=EFI_NOT_COMPRESSED){ + GET_INFO GetInfoPtr; + DECOMPRESS DecompressPtr; + BOOLEAN KnownCompressionType = GetDecompressInterface( + pCompressionSection->CompressionType, + &GetInfoPtr, &DecompressPtr + ); + if (!KnownCompressionType) return EFI_UNSUPPORTED; + Status = GetInfoPtr(pSrc, SrcSize, &DstSize, &TmpSize); + if (EFI_ERROR(Status)) return Status; + //No FreePool, so the memory is never freed + Status = (*ppPS)->AllocatePages( + ppPS,EfiBootServicesCode,(DstSize>>12)+1,&DstAddress + ); + if (EFI_ERROR(Status)) return Status; + (*ppPS)->GetHobList(ppPS,&pHob); + if (pHob->EfiFreeMemoryTop - pHob->EfiFreeMemoryBottom < TmpSize) + return EFI_OUT_OF_RESOURCES; + Status = DecompressPtr( + pSrc, SrcSize, (VOID*)DstAddress, DstSize, + (VOID*)pHob->EfiFreeMemoryBottom, TmpSize + ); + if (EFI_ERROR(Status)) return Status; + pSrc = (VOID*)(UINTN)DstAddress; + } + do { + if (((EFI_COMMON_SECTION_HEADER*)pSrc)->Type==SectionType){ + *ppData = (EFI_COMMON_SECTION_HEADER*)pSrc+1; + return EFI_SUCCESS; + } + TmpSize = FVSECTION_SIZE(pSrc); + TmpSize += (4 - (TmpSize & 3)) & 3; + if (TmpSize>=DstSize) return EFI_NOT_FOUND; + DstSize -= TmpSize; + pSrc = (UINT8*)pSrc + TmpSize; + }while(TRUE); +} + +EFI_STATUS LoadFile( + EFI_PEI_SERVICES **ppPS, + IN EFI_FFS_FILE_HEADER *pFfsHeader, + OUT VOID **ppFfsImageAddress, + OUT EFI_PHYSICAL_ADDRESS *pImageAddress, + OUT UINT64 *pImageSize, + OUT EFI_PHYSICAL_ADDRESS *pEntryPoint +) +{ + VOID *pData; + EFI_STATUS Status; + UINTN Size; + if (!pEntryPoint || !pImageAddress) return EFI_INVALID_PARAMETER; + Status = ReadSection(ppPS, EFI_SECTION_PE32, pFfsHeader, &pData); + //TODO: add TE support ??? + if (EFI_ERROR(Status)) return Status; + Size = GetImageSize(pData); + if (EFI_ERROR((*ppPS)->AllocatePages( + ppPS, EfiBootServicesCode, + (Size >> 12)+1, pImageAddress) + ) + ) return EFI_OUT_OF_RESOURCES; + + *pEntryPoint = (EFI_PHYSICAL_ADDRESS)LoadPeImage(pData,(UINT8*)*pImageAddress); + if (!*pEntryPoint) return EFI_LOAD_ERROR; + if (pImageSize) *pImageSize = Size; + if (ppFfsImageAddress) *ppFfsImageAddress = pData; + return EFI_SUCCESS; +} + +EFI_STATUS FvLoadFile( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint +) +{ + return LoadFile(ppPS,FfsHeader,NULL,ImageAddress,ImageSize,EntryPoint); +} + +typedef VOID (*PEICORE_INMEM_ENTRY_POINT)( + EFI_PHYSICAL_ADDRESS Delta, + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *PeiCoreEntryPoint, + IN UINTN Parameter1, IN UINTN Parameter2, + IN VOID *NewStack +); + +VOID SwitchCoreStacks( + IN VOID *PeiCoreEntryPoint, + IN UINTN Parameter1, + IN UINTN Parameter2, + IN VOID *NewStack +); + +VOID PeiCoreMemEntry( + EFI_PHYSICAL_ADDRESS Delta, + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *PeiCoreEntryPoint, + IN UINTN Parameter1, IN UINTN Parameter2, + IN VOID *NewStack +) +{ + ppPS = PeiServices; + if (Delta) + { + PEI_TRACE((TRACE_PEICORE,PeiServices,"PEI core reallocated to memory\n")); + // intall file loader + (*ppPS)->InstallPpi(ppPS, FileLoaderPpi); + } + SwitchCoreStacks( + (UINT8*)PeiCoreEntryPoint+(UINTN)Delta,Parameter1,Parameter2,NewStack + ); +} + +VOID AmiSwitchToMemory( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *PeiCoreEntryPoint, + IN UINTN Parameter1, IN UINTN Parameter2, + IN VOID *NewStack +) +{ + //reallocate ourself to memory + EFI_FIRMWARE_VOLUME_HEADER* pFV; + EFI_PHYSICAL_ADDRESS NewAddress, EntryPoint; + VOID *pOldAddress; + UINT64 Size; + EFI_FFS_FILE_HEADER* pFile=NULL; + PEI_PROGRESS_CODE(PeiServices,PEI_MEMORY_INSTALLED); + // if we already in memory just call memory routine + //TODO: if (pData->pLoader) PeiCoreInMem(pData, 0); + //find our FFS file header + //PEI Core must be in boot FV. + //Boot FV must be the first one returned by FfsFindNextVolume + (*PeiServices)->FfsFindNextVolume (PeiServices, 0, &pFV); + //No error checking. Since if we are here, the file is in the FV, so we should be able to find it. + (*PeiServices)->FfsFindNextFile (PeiServices, EFI_FV_FILETYPE_PEI_CORE, pFV, &pFile); + if (EFI_ERROR(LoadFile(PeiServices,pFile,&pOldAddress,&NewAddress,&Size,&EntryPoint))){ + //if we don't have enough memory, don't install FileLoader PPI + PeiCoreMemEntry(0,PeiServices,PeiCoreEntryPoint,Parameter1,Parameter2,NewStack); + }else{ + //Update LoadedImage PPI information + UpdatedLoadedImagePpi(PeiServices,NewAddress,Size,pFile); + ((PEICORE_INMEM_ENTRY_POINT)( + (UINT8*)PeiCoreMemEntry-(UINT8*)pOldAddress+(UINT8*)NewAddress + ))(NewAddress-(UINT64)(UINTN)pOldAddress,PeiServices,PeiCoreEntryPoint,Parameter1,Parameter2,NewStack); + } +} + +typedef struct { + UINTN BootFirmwareVolume; + UINTN SizeOfCacheAsRam; + EFI_PEI_PPI_DESCRIPTOR *DispatchTable; +} EFI_PEI_STARTUP_DESCRIPTOR; + +EFI_STATUS EFIAPI PeiMain( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor +); + +VOID PeiCoreEntry( + EFI_PEI_STARTUP_DESCRIPTOR StartUpDescriptor +) +{ + checkpoint(0x10); + PeiMain(&StartUpDescriptor); +} + +#include <PPI/FindFv.h> + +EFI_STATUS FindFv( + IN EFI_FIND_FV_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + UINT8 *FvNumber, + EFI_FIRMWARE_VOLUME_HEADER **FVAddress +) +{ + UINT8 Instance; + EFI_FIRMWARE_VOLUME_HEADER *BootFv; + EFI_HOB_GENERIC_HEADER *HobPointer; + EFI_STATUS Status; + + if (!FVAddress || !FvNumber) + return EFI_INVALID_PARAMETER; + + Status = (*PeiServices)->FfsFindNextVolume(PeiServices, 0, &BootFv); + if(EFI_ERROR(Status)) + return Status; + + if (*FvNumber == 0) { //0 is always Boot FV + *FVAddress = BootFv; + (*FvNumber)++; + return Status; + } + + Instance = *FvNumber; + Status = (*PeiServices)->GetHobList(PeiServices, &HobPointer); + if(EFI_ERROR(Status)) + return Status; + + while(HobPointer->HobType != EFI_HOB_TYPE_END_OF_HOB_LIST) { + if(HobPointer->HobType == EFI_HOB_TYPE_FV || HobPointer->HobType == EFI_HOB_TYPE_FV2) { + EFI_FIRMWARE_VOLUME_HEADER *Fv; + Fv = (EFI_FIRMWARE_VOLUME_HEADER *)((EFI_HOB_FIRMWARE_VOLUME *)HobPointer)->BaseAddress; + if (Fv == BootFv) { + HobPointer = NextHob(HobPointer, EFI_HOB_GENERIC_HEADER); + continue; + } + + if (Instance == 1) { + *FVAddress = Fv; + (*FvNumber)++; + return EFI_SUCCESS; + } + Instance--; + } + HobPointer = NextHob(HobPointer, EFI_HOB_GENERIC_HEADER); + } + return EFI_OUT_OF_RESOURCES; //EFI_NOT_FOUND; +} + +EFI_GUID gPeiFindFvPpiGuid = EFI_FIND_FV_PPI_GUID; + +// PPIs +EFI_FIND_FV_PPI FindFvPpi = {FindFv}; + +// PPI to be installed +EFI_PEI_PPI_DESCRIPTOR FindFvPpiDescriptor[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiFindFvPpiGuid, &FindFvPpi + } +}; + +EFI_STATUS EFIAPI InstallFindFv( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + return (*PeiServices)->InstallPpi(PeiServices,FindFvPpiDescriptor); +} +#else //#if PI_SPECIFICATION_VERSION<0x00010000 + +EFI_STATUS DecompressPpiDecompress( + IN CONST EFI_PEI_DECOMPRESS_PPI *This, + IN CONST EFI_COMPRESSION_SECTION *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize +){ + EFI_STATUS Status; + UINT32 SrcSize, DstSize, TmpSize; + VOID *pSrc; + EFI_PHYSICAL_ADDRESS DstAddress; + EFI_HOB_HANDOFF_INFO_TABLE *pHob; + EFI_COMPRESSION_SECTION_HEADER *pCompressionSection; + + if (!OutputBuffer || !OutputSize) return EFI_INVALID_PARAMETER; + + pCompressionSection = (EFI_COMPRESSION_SECTION_HEADER*)&InputSection->UncompressedLength; + SrcSize = FVSECTION_SIZE(pCompressionSection) - sizeof(EFI_COMPRESSION_SECTION_HEADER); + pSrc = pCompressionSection + 1; + if (pCompressionSection->CompressionType!=EFI_NOT_COMPRESSED){ + GET_INFO GetInfoPtr; + DECOMPRESS DecompressPtr; + EFI_PEI_SERVICES **ppPS = GetPeiServicesTablePointer(); + BOOLEAN KnownCompressionType = GetDecompressInterface( + pCompressionSection->CompressionType, + &GetInfoPtr, &DecompressPtr + ); + if (!KnownCompressionType) return EFI_UNSUPPORTED; + Status = GetInfoPtr(pSrc, SrcSize, &DstSize, &TmpSize); + if (EFI_ERROR(Status)) return Status; + //No FreePool, so the memory is never freed + Status = (*ppPS)->AllocatePages( + ppPS,EfiBootServicesCode,(DstSize>>12)+1,&DstAddress + ); + if (EFI_ERROR(Status)) return Status; + (*ppPS)->GetHobList(ppPS,&pHob); + if (pHob->EfiFreeMemoryTop - pHob->EfiFreeMemoryBottom < TmpSize) + return EFI_OUT_OF_RESOURCES; + Status = DecompressPtr( + pSrc, SrcSize, (VOID*)DstAddress, DstSize, + (VOID*)pHob->EfiFreeMemoryBottom, TmpSize + ); + if (EFI_ERROR(Status)) return Status; + *OutputBuffer = (VOID*)(UINTN)DstAddress; + *OutputSize = DstSize; + }else{ + *OutputBuffer = pSrc; + *OutputSize = SrcSize; + } + return EFI_SUCCESS; +} + +// PPI to be installed +EFI_PEI_DECOMPRESS_PPI DecomppressInterface = {DecompressPpiDecompress}; +static EFI_PEI_PPI_DESCRIPTOR DecompressPpi[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiDecompressPpiGuid, &DecomppressInterface + } +}; + + +EFI_STATUS EFIAPI InstallDecompressionPpi( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + return (*PeiServices)->InstallPpi(PeiServices, DecompressPpi); +} + +EFI_STATUS PeiMain(IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList); + +VOID PeiCoreEntry( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList) +{ + checkpoint(0x10); + PeiMain(SecCoreData,PpList); +} +#endif //#else branch of #if PI_SPECIFICATION_VERSION<0x00010000 + +VOID AmiInitParts(IN EFI_PEI_SERVICES **PeiServices, INIT_PARTS InitFunctionPtr) +{ + if (InitFunctionPtr == NULL) + return; + + (InitFunctionPtr)(NULL, PeiServices); +} + +VOID ProcessLoadHob(IN EFI_PEI_SERVICES **PeiServices) +{ + static EFI_GUID LoadHobGuid = AMI_PEIM_LOAD_HOB_GUID; + PEIM_LOAD_HOB *LoadHob; + EFI_STATUS Status; + + Status = (*PeiServices)->GetHobList(PeiServices,&LoadHob); + if (EFI_ERROR(Status)) return; + // Load PEIMs + while(!EFI_ERROR(FindNextHobByGuid(&LoadHobGuid, &LoadHob))) + { + EFI_PHYSICAL_ADDRESS Address,EntryPoint, ModuleDelta; + UINT64 Size; + // if file header is NULL, the entry is in the PEI Core binary + if (LoadHob->pFfsHeader == NULL) continue; + Status = PeiLoadFile( + PeiServices,LoadHob->pFfsHeader,&Address,&Size,&EntryPoint + ); + if (EFI_ERROR(Status)) continue; + ModuleDelta = EntryPoint - (UINT64)LoadHob->EntryPoint; + if (ModuleDelta==0) continue; // the module was not loaded +#ifdef EFI_DEBUG +{ + char sName[0x100]; + EFI_FFS_FILE_HEADER *PeimFileHeader = LoadHob->pFfsHeader; + + if (!GetName((VOID*)(UINTN)Address,sName)) + Sprintf_s(sName,sizeof(sName),"[%G]",&PeimFileHeader->Name); + PeiTrace( + TRACE_PEICORE, PeiServices, "%s.InMemEntry(%X)\n", sName, + (UINT64)LoadHob->InMemEntryPoint+ModuleDelta + ); +} +#endif + ((EFI_PEIM_ENTRY_POINT)( + (UINT64)LoadHob->InMemEntryPoint+ModuleDelta + ))(LoadHob->pFfsHeader, PeiServices); + } +} + +EFI_STATUS +PeiBuildHobStack ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a HOB for the Stack + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the Stack + + Length - The length of the stack in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + static EFI_GUID gEfiHobMemeryAllocStackGuid=EFI_HOB_MEMORY_ALLOC_STACK_GUID; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->AllocDescriptor.Name = gEfiHobMemeryAllocStackGuid; + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiLoaderData; + return EFI_SUCCESS; +} + +EFI_STATUS +PeiBuildHobMemoryAllocation ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *Name, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the memory allocation. + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the memory + + Length - The length of the memory allocation in bytes + + Name - Name for Hob + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Name != NULL) { + Hob->AllocDescriptor.Name = *Name; + } else { + (*PeiServices)->SetMem(&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID), 0); + } + + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + + return EFI_SUCCESS; +} + +EFI_STATUS +PeiBuildHobGuid ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN DataLength, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + PeiServices - The PEI core services table. + + Guid - The GUID of the custome HOB type + + DataLength - The size of the data payload for the GUIDed HOB + + Hob - Pointer to the Hob + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength), + Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ((EFI_HOB_GUID_TYPE *)(*Hob))->Name = *Guid; + + return EFI_SUCCESS; +} + +BOOLEAN CompareGuid (IN EFI_GUID *Guid1,IN EFI_GUID *Guid2) +{ + return !MemCmp(Guid1,Guid2,sizeof(EFI_GUID)); +} + +VOID CopyMem ( + IN VOID *Destination, IN VOID *Source, IN UINTN Length +) +{ + MemCpy (Destination, Source, Length); +} + +VOID ZeroMem(IN VOID *Buffer, IN UINTN Size) +{ + MemSet(Buffer,Size,0); +} + +#ifdef EFI_DEBUG + VOID + PeiDebugAssert ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) + { + PeiTrace(TRACE_ALWAYS,PeiServices,"ASSERT in %s on %i: %s\n",FileName, LineNumber, Description); + EFI_DEADLOOP() + } + + VOID + PeiDebugPrint ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) + { + CHAR8 Buffer[256]; + va_list ArgList = va_start(ArgList,Format); + PrepareStatusCodeString( Buffer, sizeof(Buffer), Format, ArgList ); + (*PeiServices)->ReportStatusCode ( + (EFI_PEI_SERVICES**)PeiServices, EFI_DEBUG_CODE, + EFI_SOFTWARE_UNSPECIFIED, 0, NULL, + (EFI_STATUS_CODE_DATA *)Buffer + ); + va_end(ArgList); + } +#endif +#if PI_SPECIFICATION_VERSION >= 0x00010000 +#pragma pack (1) +typedef struct { + UINT16 Limit; + UINTN Base; +} DESCRIPTOR_TABLE; +#pragma pack() + +VOID CPULib_LoadIdt(DESCRIPTOR_TABLE *Idt); +VOID CPULib_SaveIdt(DESCRIPTOR_TABLE *Idt); + +/*++ + +Routine Description: + + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, the no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (EFI_MAX_ADDRESS - Address + 1), then ASSERT(). + +Arguments: + + Address - The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + Length - The number of bytes to invalidate from the instruction cache. + + Returns: + Address + +**/ +VOID MigrateIdtTable (IN EFI_PEI_SERVICES **PeiServices){ + UINTN Size; + VOID *NewIdtBase; + EFI_STATUS Status; + DESCRIPTOR_TABLE IdtDescriptor; + + CPULib_SaveIdt(&IdtDescriptor); + + Size = sizeof(EFI_PEI_SERVICES**) + (IdtDescriptor.Limit + 1); + Status = (*PeiServices)->AllocatePool (PeiServices, Size, &NewIdtBase); + ASSERT_PEI_ERROR (PeiServices, Status); + (*PeiServices)->CopyMem ( + (VOID*)((UINTN)NewIdtBase + sizeof(EFI_PEI_SERVICES**)), + (VOID*)IdtDescriptor.Base, (IdtDescriptor.Limit + 1) + ); + + IdtDescriptor.Base = (UINTN)NewIdtBase + sizeof(EFI_PEI_SERVICES**); + CPULib_LoadIdt(&IdtDescriptor); + SetPeiServicesTablePointer(PeiServices); +} +/** +Routine Description: + + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the 128-bit + GUID value that matches Guid. If a match is found, then a pointer to the matching + GUID in the target buffer is returned. If no match is found, then NULL is returned. + If Length is 0, then NULL is returned. + If Length > 0 and Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 128-bit boundary, then ASSERT(). + If Length is greater than (EFI_MAX_ADDRESS ?Buffer + 1), then ASSERT(). + +Arguments: + + Buffer - Pointer to the target buffer to scan. + Length - Number of bytes in Buffer to scan. + Guid - Value to search for in the target buffer. + +Returns: + A pointer to the matching Guid in the target buffer or NULL otherwise. + +**/ +VOID *ScanGuid (IN VOID *Buffer, IN UINTN Length, IN EFI_GUID *Guid){ + EFI_GUID *GuidPtr; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + PEI_ASSERT(PeiServices, (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0)); + PEI_ASSERT(PeiServices, (Length <= (0xFFFFFFFF - (UINTN)Buffer + 1))); + PEI_ASSERT(PeiServices, ((Length & (sizeof (*GuidPtr) - 1)) == 0)); + + GuidPtr = (EFI_GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (EFI_GUID*)Buffer) { + if (!guidcmp (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} +#endif +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_PEI/CORE_PEI.cif b/Core/CORE_PEI/CORE_PEI.cif new file mode 100644 index 0000000..fb412a8 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI.cif @@ -0,0 +1,9 @@ +<component> + name = "CORE_PEI" + category = ModulePart + LocalRoot = "Core\CORE_PEI\" + RefName = "CORE_PEI" +[files] +"CORE_PEI.sdl" +"CORE_PEI.mak" +<endComponent> diff --git a/Core/CORE_PEI/CORE_PEI.mak b/Core/CORE_PEI/CORE_PEI.mak new file mode 100644 index 0000000..fa25508 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI.mak @@ -0,0 +1,163 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/BIN/Core/CORE_PEI/CORE_PEI.mak 6 5/01/09 6:12p Felixp $ +# +# $Revision: 6 $ +# +# $Date: 5/01/09 6:12p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Core/CORE_PEI/CORE_PEI.mak $ +# +# 6 5/01/09 6:12p Felixp +# Bug fix(EIP 19816). $(AMICSPLib) is linked with CORE_PEI module +# (Used to be linked with NVRAM library that caused problems on systems +# without Core Sources). +# +# 5 8/24/06 9:17a Felixp +# Preliminary x64 support (work in progress) +# +# 4 12/02/05 11:15a Felixp +# @set INCLUDE=%%INCLUDE%% removed since it's not needed. +# +# 3 6/16/05 10:47a Felixp +# 1. variables from NVRAMTokens.c moved to Tokens.c +# 2. PeiCoreMemoryInstalled initialization list added +# +# 2 2/11/05 5:46p Felixp +# Binary files organization improved: +# - extra layer of sub-component removed +# - macros initialization moved to SDL tokens to eliminate undefined +# macros situation +# - debug and release binaries have different names now (workaround for +# VeB limitation) +# +# 1 1/28/05 12:44p Felixp +# +# 3 1/18/05 3:21p Felixp +# PrintDebugMessage renamed to Trace +# +# 1 12/23/04 9:42a Felixp +# +# 2 11/01/04 8:06a Felixp +# +# 1 7/12/04 6:33p Felixp +# +# 24 3/29/04 2:32a Felixp +# +# 23 3/28/04 2:11p Felixp +# 1. PE Loader and some other commonly used code moved to the Library +# 2. Warnings fixed (from now on warning will be treated as error) +# +# 22 3/23/04 4:56p Felixp +# +# 21 3/20/04 12:03p Felixp +# +# 20 3/19/04 11:12a Robert +# +# 19 2/19/04 10:08a Felixp +# Debugging code removed. +# +# 18 2/10/04 1:24p Felixp +# +# 17 2/06/04 2:46a Felixp +# - Support for VC6 tools +# - bug fixes +# - component AddOn added +# +# 16 2/04/04 2:04a Felixp +# work in progress... +# +# 15 1/28/04 3:24a Felixp +# +# 14 1/22/04 12:47p Felixp +# +# 13 1/19/04 4:23p Felixp +# work in progress... +# +# 12 1/18/04 8:34a Felixp +# 1. From now on, OBJ files are created in a component specific +# subdirectory of $(BUILD_DIR) +# 2. New files added +# +# 11 1/15/04 11:05a Felixp +# hob.c and ffs.c files added +# +# 10 1/06/04 5:28p Yakovlevs +# +# 9 1/06/04 4:03p Felixp +# +# 8 1/06/04 11:26a Felixp +# +# 7 1/02/04 5:39p Robert +# +# 6 12/30/03 5:54p Robert +# +# 5 12/23/03 9:34a Felixp +# dependency from the makefile added +# +# 4 12/12/03 12:23p Felixp +# +# 3 12/12/03 12:07p Robert +# Added Pci Cfg and Cpu Io obj references to the mak file +# +# 2 12/12/03 11:29a Felixp +# PEICORE_OBJECTS and PEICORE_HEADERS variables created +# +# 1 12/05/03 4:15p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: Pei.mak +# +# Description: PeiCore makefile: +# -Builds EXE File +# -Invokes FFS.Mak to build PeiCore.FFS +# +#<AMI_FHDR_END> +#********************************************************************** +all : CORE_PEI + +CORE_PEI : $(BUILD_DIR)\CORE_PEI.mak CORE_PEIBin + +$(BUILD_DIR)\CORE_PEI.mak : $(CORE_PEI_DIR)\$(@B).cif $(CORE_PEI_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(CORE_PEI_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +CORE_PEIBin : $(AMIPEILIB) $(CORE_PEI_LIB) $(AMICSPLib) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\CORE_PEI.mak all\ + GUID=92685943-D810-47ff-A112-CC8490776A1F \ + ENTRY_POINT=PeiCoreEntry \ + TYPE=PEI_CORE LIBRARIES= \ + COMPRESS=0\ + EXT_HEADERS=$(BUILD_DIR)\token.h\ + "INIT_LIST=$(PeiCoreInitialize)"\ + "INIT_LIST2=$(PeiCoreMemoryInstalled)"\ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_PEI/CORE_PEI.sdl b/Core/CORE_PEI/CORE_PEI.sdl new file mode 100644 index 0000000..9177b10 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI.sdl @@ -0,0 +1,97 @@ +TOKEN + Name = "CORE_PEI_SUPPORT" + Value = "1" + Help = "Main switch to enable CORE_PEI support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "CORE_PEI_DIR" +End + +MODULE + Help = "Includes CORE_PEI.mak to Project" + File = "CORE_PEI.mak" +End + +ELINK + Name = "$(BUILD_DIR)\CORE_PEI.ffs" + Parent = "FV_BB" + Help = "PEI Core" + InvokeOrder = AfterParent +End + +ELINK + Name = "PeiCoreInitialize" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "CpuIoInit," + Parent = "PeiCoreInitialize" + InvokeOrder = AfterParent +End + +ELINK + Name = "PciCfgInit," + Parent = "PeiCoreInitialize" + InvokeOrder = AfterParent +End + +ELINK + Name = "PeiInitDxeIpl," + Parent = "PeiCoreMemoryInstalled" + InvokeOrder = AfterParent +End + +ELINK + Name = "CORE_PEI_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(CORE_PEI_DIR)\CORE_PEI$(ARCH)$(DBG).lib" + Parent = "CORE_PEI_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PeiCoreMemoryInstalled" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "PeiInitNV," + Parent = "PeiCoreInitialize" + InvokeOrder = AfterParent +End + +ELINK + Name = "InstallFindFv," + Parent = "PeiCoreInitialize" + Token = "PI_SPECIFICATION_VERSION" "<" "0x10000" + InvokeOrder = AfterParent +End + +ELINK + Name = "InstallDecompressionPpi," + Parent = "PeiCoreMemoryInstalled" + Token = "PI_SPECIFICATION_VERSION" ">=" "0x10000" + InvokeOrder = AfterParent +End + +ELINK + Name = "CpuIoMemInit," + Parent = "PeiCoreMemoryInstalled" + InvokeOrder = AfterParent +End + +ELINK + Name = "PciCfgMemInit," + Parent = "PeiCoreMemoryInstalled" + InvokeOrder = AfterParent +End + diff --git a/Core/CORE_PEI/CORE_PEISrc.cif b/Core/CORE_PEI/CORE_PEISrc.cif new file mode 100644 index 0000000..c9f5317 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEISrc.cif @@ -0,0 +1,17 @@ +<component> + name = "CORE_PEI Source(EDK)" + category = ModulePart + LocalRoot = "Core\CORE_PEI\" + RefName = "CORE_PEISrc_EDK" +[files] +"CORE_PEISrc.sdl" +"CORE_PEISrc.mak" +"AmiPeiInit.c" +"CpuIo.c" +"PciCfg.c" +"DxeIpl.c" +"PeiPerf.c" +[parts] +"CORE_PEISrcFramework_EDK" +"CORE_PEISrcPI_EDK" +<endComponent> diff --git a/Core/CORE_PEI/CORE_PEISrc.mak b/Core/CORE_PEI/CORE_PEISrc.mak new file mode 100644 index 0000000..32036c2 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEISrc.mak @@ -0,0 +1,103 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/EDK/PeiMain/CORE_PEISrc.mak 11 2/05/11 3:41p Artems $ +# +# $Revision: 11 $ +# +# $Date: 2/05/11 3:41p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/EDK/PeiMain/CORE_PEISrc.mak $ +# +# 11 2/05/11 3:41p Artems +# Added support to build source in PI 0.91 or PI 1.0 mode +# +# 10 3/05/09 1:07p Felixp +# Minor improvements: +# - Unconditional optimization (despite debug flag settings) is removed +# - Headers updated +# +# 9 8/25/06 10:58a Felixp +# +# 8 8/25/06 10:57a Felixp +# +# 7 8/25/06 10:56a Felixp +# +# 6 8/24/06 9:43a Felixp +# Preliminary x64 support (work in progress) +# DXE Core interfaces are no longer passed from PEI Core. +# They are linked directly with DXE Core +# +# 5 5/20/06 12:34a Felixp +# Optimization is always on +# +# 4 5/19/06 10:37p Felixp +# +# 3 3/17/06 4:28p Felixp +# +# 2 3/13/06 5:25p Felixp +# +# 1 3/13/06 1:57a Felixp +# +# 2 12/02/05 11:19a Felixp +# +# 1 1/28/05 12:44p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: CORE_PEISrc.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +all : CORE_PEI_LIB + +$(CORE_PEI_LIB) : CORE_PEI_LIB + +CORE_PEI_LIB : $(BUILD_DIR)\CORE_PEISrc.mak CORE_PEI_LIBBin + +$(BUILD_DIR)\CORE_PEISrc.mak : $(CORE_PEI_SRC_DIR)\$(@B).cif $(CORE_PEI_SRC_DIR)\$(@B).mak $(BUILD_RULES) +!IF $(PI_SPECIFICATION_VERSION)>=0x00010000 + $(CIF2MAK) $(CORE_PEI_SRC_DIR)\$(@B).cif $(CORE_PEI_SRC_DIR)\CORE_PEI_PI\$(@B)Pi.cif $(CIF2MAK_DEFAULTS) +!ELSE + $(CIF2MAK) $(CORE_PEI_SRC_DIR)\$(@B).cif $(CORE_PEI_SRC_DIR)\CORE_PEI_FRAMEWORK\$(@B)Framework.cif $(CIF2MAK_DEFAULTS) +!ENDIF + +CORE_PEI_LIBBin : $(BUILD_DIR)\FoundationPei.lib + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\CORE_PEISrc.mak all\ + TYPE=PEI_LIBRARY LIBRARY_NAME=$(CORE_PEI_LIB)\ + "MY_INCLUDES=/I$(Foundation_DIR)"\ +!IF "$(x64_BUILD)"=="1" + "MY_DEFINES=/Dx64_BUILD_SUPPORT"\ +!ENDIF + EXT_HEADERS=$(BUILD_DIR)\token.h NAME=CORE_PEISrc +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_PEI/CORE_PEISrc.sdl b/Core/CORE_PEI/CORE_PEISrc.sdl new file mode 100644 index 0000000..1c62c64 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEISrc.sdl @@ -0,0 +1,33 @@ +TOKEN + Name = "DXE_STACK_SIZE" + Value = "0x100000" + Help = "Size of DXE Stack" + TokenType = Integer + TargetH = Yes +End + +TOKEN + Name = "CORE_PEISrc_SUPPORT" + Value = "1" + Help = "Main switch to enable CORE_PEI Source support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "CORE_PEI_SRC_DIR" +End + +MODULE + Help = "Includes CORE_PEISrc.mak to Project" + File = "CORE_PEISrc.mak" +End + +ELINK + Name = "$(BUILD_DIR)\CORE_PEI.lib" + Parent = "$(CORE_PEI_DIR)\CORE_PEI$(ARCH)$(DBG).lib" + InvokeOrder = ReplaceParent +End + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c new file mode 100644 index 0000000..782950a --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/BootMode.c @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + BootMode.c + +Abstract: + + EFI PEI Core Boot Mode services + + + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + if (BootMode == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + *BootMode = HandOffHob->BootMode; + + + return EFI_SUCCESS; +}; + + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + HandOffHob->BootMode = BootMode; + + + return EFI_SUCCESS; +}; diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif new file mode 100644 index 0000000..9c5a51e --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/CORE_PEISrcFramework.cif @@ -0,0 +1,21 @@ +<component> + name = "CORE_PEI Source Framework (EDK)" + category = ModulePart + LocalRoot = "Core\CORE_PEI\CORE_PEI_FRAMEWORK" + RefName = "CORE_PEISrcFramework_EDK" +[files] +"BootMode.c" +"dependency.c" +"dependency.h" +"Dispatcher.c" +"FwVol.c" +"Hob.c" +"Image.c" +"MemoryServices.c" +"PeiCore.h" +"PeiMain.c" +"Ppi.c" +"Reset.c" +"Security.c" +"StatusCode.c" +<endComponent> diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c new file mode 100644 index 0000000..c82752f --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Dispatcher.c @@ -0,0 +1,604 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. 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. + +Module Name: + + Dispatcher.c + +Abstract: + + EFI PEI Core dispatch services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) + +EFI_STATUS +TransferOldDataToNewDataRange ( + IN PEI_CORE_INSTANCE *PrivateData, + OUT UINTN *PrivateDataInMem + ); + +EFI_GUID gEfiPeiCorePrivateGuid = EFI_PEI_CORE_PRIVATE_GUID; +//*** AMI PORTING BEGIN ***// +VOID AmiSwitchToMemory( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *EntryPoint, + IN UINTN Parameter1, IN UINTN Parameter2, + IN VOID *NewStack +); +//*** AMI PORTING END *****// + +EFI_STATUS +PeiDispatcher ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_DISPATCH_DATA *DispatchData + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR + PrivateData - Pointer to the private data passed in from caller + DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data. + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +{ + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + UINTN PrivateDataInMem; + BOOLEAN NextFvFound; + EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress; + EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress; + + // + // Debug data for uninstalled Peim list + // + PEI_DEBUG_CODE ( + + UINT64 DebugNotDispatchedBitmap; + EFI_GUID DebugFoundPeimList[64]; + UINT8 DebugFoundPeimPoint; + + ) + + PEI_REPORT_STATUS_CODE_CODE ( + + EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + ExtendedData.DataHeader.HeaderSize = (UINT16)sizeof (EFI_STATUS_CODE_DATA); + ExtendedData.DataHeader.Size = (UINT16)(sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - ExtendedData.DataHeader.HeaderSize); + + PeiCoreCopyMem ( + &ExtendedData.DataHeader.Type, + &gEfiStatusCodeSpecificDataGuid, + sizeof (EFI_GUID) + ); + ) + // + // save the Current FV Address so that we will not process it again if FindFv returns it later + // + DefaultFvAddress = DispatchData->BootFvAddress; + + // + // This is the main dispatch loop. It will search known FVs for PEIMs and + // attempt to dispatch them. If any PEIM gets dispatched through a single + // pass of the dispatcher, it will start over from the Bfv again to see + // if any new PEIMs dependencies got satisfied. With a well ordered + // FV where PEIMs are found in the order their dependencies are also + // satisfied, this dipatcher should run only once. + // + for (;;) { + // + // This is the PEIM search loop. It will scan through all PEIMs it can find + // looking for PEIMs to dispatch, and will dipatch them if they have not + // already been dispatched and all of their dependencies are met. + // If no more PEIMs can be found in this pass through all known FVs, + // then it will break out of this loop. + // + for (;;) { + + Status = FindNextPeim ( + &PrivateData->PS, + DispatchData->CurrentFvAddress, + &DispatchData->CurrentPeimAddress + ); + + // + // If we found a PEIM, check if it is dispatched. If so, go to the + // next PEIM. If not, dispatch it if its dependencies are satisfied. + // If its dependencies are not satisfied, go to the next PEIM. + // + if (Status == EFI_SUCCESS) { + + PEI_DEBUG_CODE ( + + // + // Fill list of found Peims for later list of those not installed + // + PeiCoreCopyMem ( + &DebugFoundPeimList[DispatchData->CurrentPeim], + &DispatchData->CurrentPeimAddress->Name, + sizeof (EFI_GUID) + ); + + ) + + if (!Dispatched ( + DispatchData->CurrentPeim, + DispatchData->DispatchedPeimBitMap + )) { + if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) { + Status = PeiLoadImage ( + &PrivateData->PS, + DispatchData->CurrentPeimAddress, + &TempPtr.Raw + ); + if (Status == EFI_SUCCESS) { + + // + // The PEIM has its dependencies satisfied, and its entry point + // has been found, so invoke it. + // + PEI_PERF_START ( + &PrivateData->PS, + L"PEIM", + (EFI_FFS_FILE_HEADER *)(DispatchData->CurrentPeimAddress), + 0 + ); + + PEI_REPORT_STATUS_CODE_CODE ( + + ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress; + + ) + + PEI_REPORT_STATUS_CODE_CODE ( + + PeiReportStatusCode ( + &(PrivateData->PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + + ) + + // + // Is this a authentic image + // + Status = VerifyPeim ( + &PrivateData->PS, + DispatchData->CurrentPeimAddress + ); + + if (Status != EFI_SECURITY_VIOLATION) { + + Status = TempPtr.PeimEntry ( + DispatchData->CurrentPeimAddress, + &PrivateData->PS + ); + } + + PEI_REPORT_STATUS_CODE_CODE ( + + PeiReportStatusCode ( + &(PrivateData->PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + + ) + PEI_PERF_END (&PrivateData->PS, L"PEIM", (EFI_FFS_FILE_HEADER *)(DispatchData->CurrentPeimAddress), 0); + + // + // Mark the PEIM as dispatched so we don't attempt to run it again + // + SetDispatched ( + &PrivateData->PS, + DispatchData->CurrentPeim, + &DispatchData->DispatchedPeimBitMap + ); + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (&PrivateData->PS); + + // + // If real system memory was discovered and installed by this + // PEIM, switch the stacks to the new memory. Since we are + // at dispatch level, only the Core's private data is preserved, + // nobody else should have any data on the stack. + // + if (PrivateData->SwitchStackSignal) { + TempPtr.PeiCore = PeiCore; + Status = TransferOldDataToNewDataRange ( + PrivateData, + &PrivateDataInMem + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + //Subtract 0x10 from the 4th parameter indicating the new stack base, + //in order to provide buffer protection against possible illegal stack + //access that might corrupt the stack. + // +//*** AMI PORTING BEGIN ***// + AmiSwitchToMemory ( + &((PEI_CORE_INSTANCE*)PrivateDataInMem)->PS, + //SwitchCoreStacks ( +//*** AMI PORTING END *****// + TempPtr.Raw, + (UINTN)PeiStartupDescriptor, + PrivateDataInMem, + (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - 0x10) + ); + } + } + } + } + DispatchData->CurrentPeim++; + continue; + + } else { + + // + // If we could not find another PEIM in the current FV, go try + // the FindFv PPI to look in other FVs for more PEIMs. If we can + // not locate the FindFv PPI, or if the FindFv PPI can not find + // anymore FVs, then exit the PEIM search loop. + // + if (DispatchData->FindFv == NULL) { + Status = PeiLocatePpi ( + &PrivateData->PS, + &gEfiFindFvPpiGuid, + 0, + NULL, + &DispatchData->FindFv + ); + if (Status != EFI_SUCCESS) { + break; + } + } + NextFvFound = FALSE; + while (!NextFvFound) { + Status = DispatchData->FindFv->FindFv ( + DispatchData->FindFv, + &PrivateData->PS, + &DispatchData->CurrentFv, + &NextFvAddress + ); + // + // if there is no next fv, get out of this loop of finding FVs + // + if (Status != EFI_SUCCESS) { + break; + } + // + // don't process the default Fv again. (we don't know the order in which the hobs were created) + // + if ((NextFvAddress != DefaultFvAddress) && + (NextFvAddress != DispatchData->CurrentFvAddress)) { + + // + // VerifyFv() is currently returns SUCCESS all the time, add code to it to + // actually verify the given FV + // + Status = VerifyFv (NextFvAddress); + if (Status == EFI_SUCCESS) { + NextFvFound = TRUE; + DispatchData->CurrentFvAddress = NextFvAddress; + DispatchData->CurrentPeimAddress = NULL; + // + // current PRIM number (CurrentPeim) must continue as is, don't reset it here + // + } + } + } + // + // if there is no next fv, get out of this loop of dispatching PEIMs + // + if (!NextFvFound) { + break; + } + // + // continue in the inner for(;;) loop with a new FV; + // + } + } + + // + // If all the PEIMs that we have found have been dispatched, then + // there is nothing left to dispatch and we don't need to go search + // through all PEIMs again. + // + if ((~(DispatchData->DispatchedPeimBitMap) & + (LShiftU64 (1, DispatchData->CurrentPeim)-1)) == 0) { + break; + } + + // + // Check if no more PEIMs that depex was satisfied + // + if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) { + break; + } + + // + // Case when Depex is not satisfied and has to traverse the list again + // + DispatchData->CurrentPeim = 0; + DispatchData->CurrentPeimAddress = 0; + DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap; + + // + // don't go back to the loop without making sure that the CurrentFvAddress is the + // same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and + // mess it up, always start processing the PEIMs from the default FV just like in the first time around. + // + DispatchData->CurrentFv = 0; + DispatchData->CurrentFvAddress = DefaultFvAddress; + } + + PEI_DEBUG_CODE ( + + DebugFoundPeimPoint = 0; + // + // Get bitmap of Peims that were not dispatched, + // + + DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ (LShiftU64 (1, DispatchData->CurrentPeim)-1)); + // + // Scan bitmap of Peims not installed and print GUIDS + // + while (DebugNotDispatchedBitmap != 0) { + if ((DebugNotDispatchedBitmap & 1) != 0) { + PEI_DEBUG ( + (&PrivateData->PS, EFI_D_INFO, + "WARNING -> PEIM Not Dispatched: %g\n", + &DebugFoundPeimList[DebugFoundPeimPoint]) + ); + } + DebugFoundPeimPoint++; + DebugNotDispatchedBitmap = RShiftU64 (DebugNotDispatchedBitmap, 1); + } + + ) + + return EFI_NOT_FOUND; +} + +VOID +InitializeDispatcherData ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + None. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (OldCoreData == NULL) { + PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume; + PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume; + } else { + + // + // Current peim has been dispatched, but not count + // + PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1); + } + + return; +} + + +BOOLEAN +Dispatched ( + IN UINT8 CurrentPeim, + IN UINT64 DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine checks to see if a particular PEIM has been dispatched during + the PEI core dispatch. + +Arguments: + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + TRUE - PEIM already dispatched + FALSE - Otherwise + +--*/ +{ + return (BOOLEAN)((DispatchedPeimBitMap & LShiftU64 (1, CurrentPeim)) != 0); +} + +VOID +SetDispatched ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 CurrentPeim, + OUT UINT64 *DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine sets a PEIM as having been dispatched once its entry + point has been invoked. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + None + +--*/ +{ + // + // Check if the total number of PEIMs exceed the bitmap. + // CurrentPeim is 0-based + // +PEI_DEBUG_CODE ( + if (CurrentPeim > (sizeof (*DispatchedPeimBitMap) * 8 - 1)) { + ASSERT_PEI_ERROR (PeiServices, EFI_OUT_OF_RESOURCES); + } +) + *DispatchedPeimBitMap |= LShiftU64 (1, CurrentPeim); + return; +} + +BOOLEAN +DepexSatisfied ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CurrentPeimAddress + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + PeiServices - The PEI Service Table + CurrentPeimAddress - Address of the PEIM Firmware File under investigation + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +{ + EFI_STATUS Status; + INT8 *DepexData; + BOOLEAN Runnable; + + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PEI_DEPEX, + CurrentPeimAddress, + &DepexData + ); + // + // If there is no DEPEX, assume the module can be executed + // + if (EFI_ERROR (Status)) { + return TRUE; + } + + // + // Evaluate a given DEPEX + // + Status = PeimDispatchReadiness ( + PeiServices, + DepexData, + &Runnable + ); + + return Runnable; +} + + +EFI_STATUS +TransferOldDataToNewDataRange ( + IN PEI_CORE_INSTANCE *PrivateData, + OUT UINTN *PrivateDataInMem + ) +/*++ + +Routine Description: + + This routine transfers the contents of the pre-permanent memory + PEI Core private data to a post-permanent memory data location. + +Arguments: + PrivateData - Pointer to the current PEI Core private data pre-permanent memory + PrivateDataInMem - Pointer to the PrivateData once the private data has been transferred + to permanent memory + +Returns: + EFI_SUCCESS - Successfully transfered + EFI_ERROR - Fail to transfer + +--*/ +{ + EFI_STATUS Status; + + Status = PeiBuildHobGuid ( + &(PrivateData->PS), + &gEfiPeiCorePrivateGuid, + sizeof (PEI_CORE_INSTANCE), + (VOID*)PrivateDataInMem + ); + if (EFI_ERROR (Status)) { + return Status; + } + (*PrivateDataInMem) += sizeof (EFI_HOB_GUID_TYPE); + PrivateData->PS->CopyMem ( + (VOID*)(*PrivateDataInMem), + (VOID*)PrivateData, + sizeof (PEI_CORE_INSTANCE) + ); + + return EFI_SUCCESS; +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c new file mode 100644 index 0000000..14eb90c --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/FwVol.c @@ -0,0 +1,488 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVol.c + +Abstract: + + Pei Core Firmware File System service routines. + +--*/ + +#include "Tiano.h" +#include "EfiImageFormat.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#define GETOCCUPIEDSIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + +STATIC +EFI_FFS_FILE_STATE +GetFileState( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Returns the highest bit set of the State field + +Arguments: + + ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY + in the Attributes field. + FfsHeader - Pointer to FFS File Header. + +Returns: + Returns the highest bit in the State field + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +STATIC +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +/*++ + +Routine Description: + + Calculates the checksum of the header of a file. + +Arguments: + + FileHeader - Pointer to FFS File Header. + +Returns: + Checksum of the header. + + The header is zero byte checksum. + - Zero means the header is good. + - Non-zero means the header is bad. + + +Bugbug: For PEI performance reason, we comments this code at this time. +--*/ +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + ptr = (UINT8 *)FileHeader; + + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8)(Sum + ptr[Index]); + Sum = (UINT8)(Sum + ptr[Index+1]); + Sum = (UINT8)(Sum + ptr[Index+2]); + Sum = (UINT8)(Sum + ptr[Index+3]); + } + + for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8)(Sum + ptr[Index]); + } + + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8)(Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +STATIC +EFI_STATUS +PeiFfsFindNextFileEx ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader, + IN BOOLEAN Flag + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) start with the first file in the + // firmware volume. Otherwise, start from the FileHeader. + // + if (*FileHeader == NULL) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + PEI_ASSERT (PeiServices, (FileOffset <= 0xFFFFFFFF)); + + while (FileOffset < (FvLength - sizeof(EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof(EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) == 0) { + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + if (Flag) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + + *FileHeader = FfsFileHeader; + + + return EFI_SUCCESS; + } + } else { + if ((SearchType == FfsFileHeader->Type) || + (SearchType == EFI_FV_FILETYPE_ALL)) { + + *FileHeader = FfsFileHeader; + + + return EFI_SUCCESS; + } + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + } else { +//*** AMI PORTING BEGIN ***// +// Skip the assert to support a more sophisiticated +// FV corruption handling outside of the Core. +// PEI_ASSERT (PeiServices, (0)); +//*** AMI PORTING END *****// + return EFI_NOT_FOUND; + } + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINT32 SectionLength; + UINT32 ParsedLength; + + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); + FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof(EFI_FFS_FILE_HEADER); + + *SectionData = NULL; + ParsedLength = 0; + while (ParsedLength < FileSize) { + if (Section->Type == SectionType) { + *SectionData = (VOID *)(Section + 1); + + + return EFI_SUCCESS; + } + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GETOCCUPIEDSIZE (SectionLength, 4); + PEI_ASSERT (PeiServices, SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; + +} + + +EFI_STATUS +FindNextPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + PeimFileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + return PeiFfsFindNextFileEx ( + PeiServices, + 0, + FwVolHeader, + PeimFileHeader, + TRUE + ); +} + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + return PeiFfsFindNextFileEx ( + PeiServices, + SearchType, + FwVolHeader, + FileHeader, + FALSE + ); +} + +EFI_STATUS +EFIAPI +PeiFvFindNextVolume ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + + Return the Firmware Volume instance requested + + BugBug -- Move this to the location of this code to where the + other FV and FFS support code lives. + Also, update to use FindFV for instances #'s >= 1. + +Arguments: + + PeiServices - The PEI core services table. + Instance - Instance of FV to find + FwVolHeader - Pointer to contain the data to return + +Returns: + Pointer to the Firmware Volume instance requested + + EFI_INVALID_PARAMETER - FwVolHeader is NULL + + EFI_SUCCESS - Firmware volume instance successfully found. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + EFI_FIND_FV_PPI *FindFvPpi; + UINT8 LocalInstance; + + + LocalInstance = (UINT8) Instance; + + Status = EFI_SUCCESS; + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + if (FwVolHeader == NULL) { + + return EFI_INVALID_PARAMETER; + } + + if (Instance == 0) { + // + // If instance is 0, the first firmware volume must be BFV. + // + *FwVolHeader = PrivateData->DispatchData.BootFvAddress; + + + return Status; + } else { + // + // Locate all instances of FindFV + // Alternately, could use FV HOBs, but the PPI is cleaner + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiFindFvPpiGuid, + 0, + NULL, + &FindFvPpi + ); + + if (Status != EFI_SUCCESS) { + Status = EFI_NOT_FOUND; + } else { + Status = FindFvPpi->FindFv ( + FindFvPpi, + PeiServices, + &LocalInstance, + FwVolHeader + ); + + } + } + return Status; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c new file mode 100644 index 0000000..cffbf6c --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Hob.c @@ -0,0 +1,198 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. 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. + +Module Name: + + Hob.c + +Abstract: + + EFI PEI Core HOB services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + + // + // Only check this parameter in debug mode + // + + PEI_DEBUG_CODE ( + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + ) + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + *HobList = PrivateData->HobList.Raw; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + + Status = PeiGetHobList (PeiServices, Hob); + if (EFI_ERROR(Status)) { + return Status; + } + + HandOffHob = *Hob; + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c new file mode 100644 index 0000000..8ccbd68 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c @@ -0,0 +1,341 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + Image.c + +Abstract: + + Pei Core Load Image Support + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_PPI_DEFINITION (LoadFile) + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + PeimFileHeader - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + VOID *Pe32Data; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; +#ifdef EFI_NT_EMULATOR + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; + EFI_PHYSICAL_ADDRESS NtEntryPoint; +#endif + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + EFI_TE_IMAGE_HEADER *TEImageHeader; + UINT16 Machine; + + PEI_DEBUG_CODE (ImageAddress = 0;) + + *EntryPoint = NULL; + TEImageHeader = NULL; + PeHdr = NULL; + // + // Try to find a PE32 section. + // + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PE32, + PeimFileHeader, + &Pe32Data + ); + // + // If we didn't find a PE32 section, try to find a TE section. + // + if (Status != EFI_SUCCESS) { + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_TE, + PeimFileHeader, + (VOID **) &TEImageHeader + ); + Pe32Data = (VOID *) TEImageHeader; + } + if (Status == EFI_SUCCESS) { + if (TEImageHeader == NULL) { + if (((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + Machine = PeHdr->FileHeader.Machine; +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of the PEIMS +//from the firmware volumes in memory. + if ( PeHdr->OptionalHeader.ImageBase + !=(UINTN)Pe32Data + ) Status=EFI_NOT_FOUND; +//Init ImageSize for to pass into UpdatedLoadedImagePpi + ImageSize = PeHdr->OptionalHeader.SizeOfImage; +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// + Machine = TEImageHeader->Machine; +//This is needed to enable execution of the PEIMS +//from the firmware volumes in memory. +//The following two lines are not needed because +//we don't support reallocation of TE image into memory. +// if ( TEImageHeader->ImageBase!=(UINTN)(TEImageHeader)) +// Status=EFI_NOT_FOUND; + +//Init ImageSize for to pass into UpdatedLoadedImagePpi. +//Let's get size from the FFS section header + ImageSize = FVSECTION_SIZE(TEImageHeader); +//*** AMI PORTING END *****// + } + // + // Check PEIM image machine. A PEIM image for different processor architecture + // from the host can't be started. + // + if (Machine != EFI_IMAGE_MACHINE_TYPE) { + return EFI_UNSUPPORTED; + } + +#ifdef EFI_NT_EMULATOR + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + &NtEntryPoint + ); + + if (EFI_ERROR (Status)) { + if (TEImageHeader != NULL) { + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } + } else { + *EntryPoint = (VOID *) (UINTN) NtEntryPoint; + } + +#else + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; + if (TEImageHeader != NULL) { + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } +#endif +//*** AMI PORTING BEGIN ***// +// } else { + } + if (Status!=EFI_SUCCESS){ +//*** AMI PORTING END *****// + // + // There was not a PE32 section, so assume that it's a Compressed section + // and use the LoadFile + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiFvFileLoaderPpiGuid, + 0, + NULL, + &FvLoadFilePpi + ); + + if (!EFI_ERROR (Status)) { + Status = FvLoadFilePpi->FvLoadFile ( + FvLoadFilePpi, + PeimFileHeader, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + + if (!EFI_ERROR (Status)) { + *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint); + if (((EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress)->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TEImageHeader = (EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress; + Machine = TEImageHeader->Machine; + } else { + if (((EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress)->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) ImageAddress + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) (UINTN) ImageAddress; + } + Machine = PeHdr->FileHeader.Machine; + } + // + // Check PEIM image machine. A PEIM image for different processor architecture + // from the host can't be started. + // + if (Machine != EFI_IMAGE_MACHINE_TYPE) { + return EFI_UNSUPPORTED; + } + } + } + } +//*** AMI PORTING BEGIN ***// +//Message is printed later. Disable this one +/* + PEI_DEBUG_CODE ( + { + EFI_IMAGE_DATA_DIRECTORY * DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry; + UINTN DirCount; + UINTN Index; + UINTN Index1; + BOOLEAN FileNameFound; + CHAR8 *AsciiString; + CHAR8 AsciiBuffer[512]; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + + if (Status == EFI_SUCCESS) { + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + PEI_DEBUG ((PeiServices, EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint)); + + // + // Find the codeview info in the image and display the file name + // being loaded. + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + DebugEntry = NULL; + DirectoryEntry = NULL; + TEImageAdjust = 0; + if (TEImageHeader == NULL) { + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); + } + } else { + if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + + TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } + + if (DebugEntry != NULL && DirectoryEntry != NULL) { + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + AsciiString = NULL; + break; + } + if (AsciiString != NULL) { + FileNameFound = FALSE; + for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { + if (AsciiString[Index] == '\\') { + Index1 = Index; + FileNameFound = TRUE; + } + } + + if (FileNameFound) { + for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { + AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; + } + AsciiBuffer[Index - (Index1 + 1)] = 0; + PEI_DEBUG ((PeiServices, EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + PEI_DEBUG ((PeiServices, EFI_D_INFO | EFI_D_LOAD, "\n")); + } + } + ) +*/ +#ifdef EFI_DEBUG +if (!EFI_ERROR (Status)){ + char sName[0x100]; + if (!GetName((VOID*)(UINTN)ImageAddress,sName)) Sprintf_s(sName,sizeof(sName),"[%G]",&PeimFileHeader->Name); + PeiTrace(TRACE_PEICORE, PeiServices, "%s.Entry(%X)\n", sName, *EntryPoint); +} +else PeiTrace(TRACE_PEICORE, PeiServices, "ERROR: attempt to load FFS file [%G] has failed\n", &PeimFileHeader->Name); +#endif +//New image is loaded and is about to be launched +//Update LoadedImage PPI information +if (!EFI_ERROR (Status)) + UpdatedLoadedImagePpi(PeiServices,ImageAddress,ImageSize,PeimFileHeader); +//*** AMI PORTING END *****// + return Status; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c new file mode 100644 index 0000000..9566e02 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/MemoryServices.c @@ -0,0 +1,440 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + MemoryServices.c + +Abstract: + + EFI PEI Core memory services + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" +#include "PeiCore.h" +#include "PeiLib.h" +//*** AMI PORTING BEGIN ***// +//use SDL token 'DXE_STACK_SIZE' to define stack size +#include <Token.h> +#undef PEI_STACK_SIZE +#define PEI_STACK_SIZE DXE_STACK_SIZE +//*** AMI PORTING END *****// + +VOID +InitializeMemoryServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT64 SizeOfCarHeap; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + PrivateData->SwitchStackSignal = FALSE; + + if (OldCoreData == NULL) { + + PrivateData->PeiMemoryInstalled = FALSE; + +//*** AMI PORTING BEGIN ***// +//The original method of getting CAR top and bootom addresses assumes that CAR base address is aligned +//on CAR size boundary, which is not always the case. +//Make the algorithm more flexible +//Comment out the old code: +// PrivateData->BottomOfCarHeap = (VOID *) (((UINTN)(VOID *)(&PrivateData)) +// & (~((PeiStartupDescriptor->SizeOfCacheAsRam) - 1))); +// PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + PeiStartupDescriptor->SizeOfCacheAsRam); +//New code: +// Private data is located towards the top of the stack. +// The stack is located at the top of the CAR. +// We assume that: +// 1) CAR address and size are at least 1K aligned. +// 2) Not more than 1K of Stack is used by SEC phase. +// The top of the CAR should be the next 1K boundary +//NOTE: New PI 1.0 spec provides a better solution. +//It expends SEC to PI hand off structure to explicitly pass CAR address +//This code will be changed once PI support is added. +#define CAR_ADDRESS_AND_SIZE_ALIGNMENT 0x400 + PrivateData->TopOfCarHeap = (VOID *)( + (((UINTN)(VOID *)(&PrivateData))+CAR_ADDRESS_AND_SIZE_ALIGNMENT) + & (~(CAR_ADDRESS_AND_SIZE_ALIGNMENT-1)) + ); + PrivateData->BottomOfCarHeap = (VOID *)( + (UINTN)(PrivateData->TopOfCarHeap) + - PeiStartupDescriptor->SizeOfCacheAsRam + ); +//*** AMI PORTING END *****// + // + // SizeOfCarHeap is 1/2 (arbitrary) of CacheAsRam Size. + // + SizeOfCarHeap = (UINT64) PeiStartupDescriptor->SizeOfCacheAsRam; + SizeOfCarHeap = RShiftU64 (SizeOfCarHeap, 1); + + PEI_DEBUG_CODE ( + { + PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam; + PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap); + } + ) + + PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap; + + PeiCoreBuildHobHandoffInfoTable ( + BOOT_WITH_FULL_CONFIGURATION, + (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap, + (UINTN) SizeOfCarHeap + ); + // + // Copy PeiServices from ROM to Cache in PrivateData + // + PeiCoreCopyMem (&(PrivateData->ServiceTableShadow), *PeiServices, sizeof (EFI_PEI_SERVICES)); + + // + // Set PS to point to ServiceTableShadow in Cache + // + PrivateData->PS = &(PrivateData->ServiceTableShadow); + } else { + // + // Set PS to point to ServiceTableShadow in Cache one time after the + // stack switched to main memory + // + PrivateData->PS = &(PrivateData->ServiceTableShadow); +} + + return; +} + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob; + EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob; + UINT64 PeiStackSize; + UINT64 EfiFreeMemorySize; + EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + +//*** AMI PORTING BEGIN ***// + if (PrivateData->PeiMemoryInstalled) { + //This function should be called once. Report error if this is the second call + PEI_ERROR_CODE(PeiServices, PEI_MEMORY_INSTALLED_TWICE, EFI_ERROR_MINOR); + }else { + //Debug message + PEI_TRACE((TRACE_PEICORE, PeiServices, "Memory Installed: Address=%lX; Length=%lX\n",MemoryBegin,MemoryLength)); + } +//*** AMI PORTING END *****// + + PrivateData->SwitchStackSignal = TRUE; + PrivateData->PeiMemoryInstalled = TRUE; + + PrivateData->StackBase = MemoryBegin; + + PeiStackSize = RShiftU64 (MemoryLength, 1); + if (PEI_STACK_SIZE > PeiStackSize) { + PrivateData->StackSize = PeiStackSize; + } else { + PrivateData->StackSize = PEI_STACK_SIZE; + } + + OldHandOffHob = PrivateData->HobList.HandoffInformationTable; + + PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize)); + NewHandOffHob = PrivateData->HobList.HandoffInformationTable; + PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob; + + EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob; + + PeiCoreCopyMem ( + NewHandOffHob, + OldHandOffHob, + (UINTN)EfiFreeMemorySize + ); + + NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength; + NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop; + NewHandOffHob->EfiMemoryBottom = MemoryBegin; + + NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize; + + NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob + + (OldHandOffHob->EfiEndOfHobList - + PhysicalAddressOfOldHob); + + ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob); + + PeiBuildHobStack (PeiServices, PrivateData->StackBase, PrivateData->StackSize); +//*** AMI PORTING BEGIN ***// +//Update LoadedImage pointers +PrivateData->LoadedImage = (EFI_PEI_PPI_DESCRIPTOR*) + ( (UINTN)PrivateData->LoadedImage + ((UINTN)NewHandOffHob - (UINTN)OldHandOffHob) ); +//*** AMI PORTING END *****// + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob)); + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob)); + } + ) + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + EFI_STATUS Status; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Check if Hob already available + // + if (!PrivateData->PeiMemoryInstalled) { + return EFI_NOT_AVAILABLE_YET; + } + + Hob.Raw = PrivateData->HobList.Raw; + + // + // Check to see if on 4k boundary + // + Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF; + + // + // If not aligned, make the allocation aligned. + // + if (Offset != 0) { + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset; + } + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < + Hob.HandoffInformationTable->EfiFreeMemoryBottom) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiAllocatePages fail: Pages - 0x%08x\n", Pages)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } else { + // + // Update the PHIT to reflect the memory usage + // + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + + // + // Update the value for the caller + // + *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop; + + // + // Create a memory allocation HOB. + // + Status = PeiBuildHobMemoryAllocation ( + PeiServices, + Hob.HandoffInformationTable->EfiFreeMemoryTop, + Pages * EFI_PAGE_SIZE + Offset, + NULL, + MemoryType + ); + + return Status; + } +} + + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_POOL *Hob; + + + Status = PeiCreateHob ( + PeiServices, + EFI_HOB_TYPE_PEI_MEMORY_POOL, + (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size), + &Hob + ); + *Buffer = Hob+1; + + + return Status; +} + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + EfiCommonLibCopyMem (Destination, Source, Length); +} + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +{ + EfiCommonLibSetMem (Buffer, Size, Value); +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h new file mode 100644 index 0000000..24130e5 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiCore.h @@ -0,0 +1,1260 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. 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. + +Module Name: + + PeiCore.h + +Abstract: + + Definition of Pei Core Structures and Services + +Revision History + +--*/ + +#ifndef _PEICORE_H_ +#define _PEICORE_H_ + +#include "EfiImage.h" +#include "Pei.h" +#include "PeiHob.h" + +#ifdef EFI64 +#include "SalApi.h" +#endif + +#include "EfiCommonLib.h" + +#include EFI_PPI_DEFINITION (FindFv) +#include EFI_PPI_DEFINITION (DxeIpl) +#include EFI_PPI_DEFINITION (StatusCode) +#include EFI_PPI_DEFINITION (Security) + + +#ifdef EFI_NT_EMULATOR +#include EFI_PPI_DEFINITION (NtPeiLoadFile) +#endif + +//*** AMI PORTING BEGIN ***// +#include <PPI/LoadedImagePpi.h> +//*** AMI PORTING END *****// + +// +//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range +// +#define EFI_PEI_CORE_PRIVATE_GUID \ + {0xd641a0f5, 0xcb7c, 0x4846, 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9} + +// +// Pei Core private data structures +// +typedef union _PEI_PPI_LIST_POINTERS { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + +#define PEI_STACK_SIZE 0x20000 + +#define MAX_PPI_DESCRIPTORS 128 + +typedef struct { + INTN PpiListEnd; + INTN NotifyListEnd; + INTN DispatchListEnd; + INTN LastDispatchedInstall; + INTN LastDispatchedNotify; + PEI_PPI_LIST_POINTERS PpiListPtrs[MAX_PPI_DESCRIPTORS]; +} PEI_PPI_DATABASE; + +typedef struct { + UINT8 CurrentPeim; + UINT8 CurrentFv; + UINT64 DispatchedPeimBitMap; + UINT64 PreviousPeimBitMap; + EFI_FFS_FILE_HEADER *CurrentPeimAddress; + EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress; + EFI_FIRMWARE_VOLUME_HEADER *BootFvAddress; + EFI_FIND_FV_PPI *FindFv; +} PEI_CORE_DISPATCH_DATA; + + +// +// Pei Core private data structure instance +// + +#define PEI_CORE_HANDLE_SIGNATURE EFI_SIGNATURE_32('P','e','i','C') + +typedef struct{ + UINTN Signature; + EFI_PEI_SERVICES *PS; // Point to ServiceTableShadow + PEI_PPI_DATABASE PpiData; + PEI_CORE_DISPATCH_DATA DispatchData; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + EFI_PHYSICAL_ADDRESS StackBase; + UINT64 StackSize; + VOID *BottomOfCarHeap; + VOID *TopOfCarHeap; + VOID *CpuIo; + PEI_SECURITY_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; +//*** AMI PORTING BEGIN ***// + EFI_PEI_PPI_DESCRIPTOR *LoadedImage; + EFI_PEI_LOADED_IMAGE_PPI LoadedImagePpi; +//*** AMI PORTING END *****// + PEI_DEBUG_CODE ( + UINTN SizeOfCacheAsRam; + VOID *MaxTopOfCarHeap; + ) +} PEI_CORE_INSTANCE; + +// +// Pei Core Instance Data Macros +// + +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + PEI_CR(a, PEI_CORE_INSTANCE, PS, PEI_CORE_HANDLE_SIGNATURE) + + +typedef +EFI_STATUS +(EFIAPI *PEI_CORE_ENTRY_POINT) ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Union of temporarily used function pointers (to save stack space) +// +typedef union { + PEI_CORE_ENTRY_POINT PeiCore; + EFI_PEIM_ENTRY_POINT PeimEntry; + EFI_PEIM_NOTIFY_ENTRY_POINT PeimNotifyEntry; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + VOID *Raw; +} PEI_CORE_TEMP_POINTERS; + + +// +// Main PEI entry +// +EFI_STATUS +EFIAPI +PeiMain ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + This function never returns + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + +--*/ +; + + +// +// Dispatcher support functions +// + +EFI_STATUS +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression, + IN OUT BOOLEAN *Runnable + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +; + + +EFI_STATUS +PeiDispatcher ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_DISPATCH_DATA *DispatchData + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR + PrivateData - Pointer to the private data passed in from caller + DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data. + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +; + + +VOID +InitializeDispatcherData ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + PeiStartupDescriptor - Information and services provided by SEC phase. + + +Returns: + + None + +--*/ +; + + +EFI_STATUS +FindNextPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + PeimFileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +BOOLEAN +Dispatched ( + IN UINT8 CurrentPeim, + IN UINT64 DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine checks to see if a particular PEIM has been dispatched during + the PEI core dispatch. + +Arguments: + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + TRUE if PEIM already dispatched + FALSE if not + +--*/ +; + +VOID +SetDispatched ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 CurrentPeim, + OUT UINT64 *DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine sets a PEIM as having been dispatched once its entry + point has been invoked. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + None + +--*/ +; + +BOOLEAN +DepexSatisfied ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CurrentPeimAddress + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + PeiServices - The PEI Service Table + CurrentPeimAddress - Address of the PEIM Firmware File under investigation + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +; + +VOID +SwitchCoreStacks ( + IN VOID *EntryPoint, + IN UINTN Parameter1, + IN UINTN Parameter2, + IN VOID *NewStack + ) +/*++ + +Routine Description: + + Routine for PEI switching stacks. + +Arguments: + + EntryPoint - Entry point with new stack. + Parameter1 - First parameter for entry point. + Parameter2 - Second parameter for entry point. + NewStack - Pointer to new stack. + +Returns: + + None + +--*/ +; + + +#ifdef EFI64 + // + // In Ipf we should make special changes for the PHIT pointers to support + // recovery boot in cache mode. + // +#define SWITCH_TO_CACHE_MODE(CoreData) SwitchToCacheMode(CoreData) +#define CACHE_MODE_ADDRESS_MASK 0x7FFFFFFFFFFFFFFF +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData +) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +; + +#else + +#define SWITCH_TO_CACHE_MODE(CoreData) + +#endif + +// +// PPI support functions +// +VOID +InitializePpiServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +; + +VOID +ConvertPpiPointers ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Migrate the Hob list from the CAR stack to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +; + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +; + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ +; + +VOID +DispatchNotify ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ +; + +// +// Boot mode support functions +// +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +; + +// +// Security support functions +// +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +; + +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +/*++ + +Routine Description: + + Provide a callout to the OEM FV verification service. + +Arguments: + + CurrentFvAddress - Pointer to the FV under investigation. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + + +EFI_STATUS +VerifyPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +; + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +; + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +; + + +// +// FFS Fw Volume support functions +// +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFvFindNextVolume ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + + Return the BFV location + + BugBug -- Move this to the location of this code to where the + other FV and FFS support code lives. + Also, update to use FindFV for instances #'s >= 1. + +Arguments: + + PeiServices - The PEI core services table. + Instance - Instance of FV to find + FwVolHeader - Pointer to contain the data to return + +Returns: + Pointer to the Firmware Volume instance requested + + EFI_INVALID_PARAMETER - FwVolHeader is NULL + + EFI_SUCCESS - Firmware volume instance successfully found. + +--*/ +; + +// +// Memory support functions +// +VOID +InitializeMemoryServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of allocation. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +; + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +; + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +; + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Get entry point of a Peim file. + +Arguments: + + PeiServices - Calling context. + + PeimFileHeader - Peim file's header. + + EntryPoint - Entry point of that Peim file. + +Returns: + + Status code. + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCoreResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +; +//*** AMI PORTING BEGIN ***// +//This function is used to update LoadedImage PPI information +//LoadedImage PPI is defined in PI 1.0 specification +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +); + +#include <AmiPeiLib.h> +//*** AMI PORTING END *****// +#endif diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c new file mode 100644 index 0000000..bfcdbe4 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/PeiMain.c @@ -0,0 +1,405 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + PeiMain.c + +Abstract: + + Pei Core Main Entry Point + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_PPI_DEFINITION (MemoryDiscovered) +#include EFI_PPI_DEFINITION (FindFv) +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +#include EFI_GUID_DEFINITION (StatusCode) + +// +//CAR is filled with this initial value during SEC phase +// +#define INIT_CAR_VALUE 0x5AA55AA5 + +#ifdef EFI_PEI_PERFORMANCE + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ); + +#endif + +//*** AMI PORTING BEGIN ***// +VOID InitParts(VOID* p1, VOID*p2); +VOID InitPartsMem(VOID* p1, VOID*p2); +VOID ProcessLoadHob(EFI_PEI_SERVICES **PeiServices); +VOID AmiInitParts(IN EFI_PEI_SERVICES **PeiServices, VOID* InitFunction); +//*** AMI PORTING END *****// + +static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiMemoryDiscoveredPpiGuid, + NULL +}; + +// +// Pei Core Module Variables +// +// +static EFI_PEI_SERVICES mPS = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFvFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + PeiCoreCopyMem, + PeiCoreSetMem, + + PeiReportStatusCode, + +//*** AMI PORTING BEGIN ***// +// This is a bug fix. +// In accordance with PEI CIS 0.91 +// this structure has been extended with two more pointers. +// PeiCoreResetSystem + PeiCoreResetSystem, + NULL, + NULL +//*** AMI PORTING END *****// +}; + +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ); + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Main entry point to the PEI Core +// +EFI_PEI_CORE_ENTRY_POINT (PeiMain) + +EFI_STATUS +EFIAPI +PeiMain ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + This function never returns + +--*/ +{ + return PeiCore (PeiStartupDescriptor, NULL); +} + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + EFI_NOT_FOUND - Never reach + +--*/ +{ + PEI_CORE_INSTANCE PrivateData; + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + PEI_CORE_DISPATCH_DATA *DispatchData; + + +#ifdef EFI_PEI_PERFORMANCE + UINT64 mTick; + + mTick = 0; + if (OldCoreData == NULL) { + GetTimerValue (&mTick); + } +#endif + + + // + // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory() + // the 63-bit of address is set to 1. + // + SWITCH_TO_CACHE_MODE (OldCoreData); + + if (OldCoreData != NULL) { + PeiCoreCopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE)); + } else { + PeiCoreSetMem (&PrivateData, sizeof (PEI_CORE_INSTANCE), 0); + } + + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + PrivateData.PS = &mPS; + + // + // Mm7 stored PeiServicesTablePointer in EdkII Glue Library + // Update Mm7 now + // +//*** AMI PORTING BEGIN ***// +//#if (defined(EFI32)) || (defined(EFIX64)) +#ifndef EFI64 +//*** AMI PORTING END *****// + AsmWriteMm7 ((UINT64)(UINTN)(&PrivateData.PS)); +#endif + + InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData); + + InitializePpiServices (&PrivateData.PS, OldCoreData); + + InitializeSecurityServices (&PrivateData.PS, OldCoreData); + + InitializeDispatcherData (&PrivateData.PS, OldCoreData, PeiStartupDescriptor); + + if (OldCoreData != NULL) { + + PEI_PERF_END (&PrivateData.PS,L"PreMem", NULL, 0); + PEI_PERF_START (&PrivateData.PS,L"PostMem", NULL, 0); + + // + // The following code dumps out interesting cache as RAM usage information + // so we can keep tabs on how the cache as RAM is being utilized. The + // PEI_DEBUG_CODE macro is used to prevent this code from being compiled + // on a debug build. + // + PEI_DEBUG_CODE ( + { + UINTN *StackPointer; + UINTN StackValue; + + StackValue = INIT_CAR_VALUE; + for (StackPointer = (UINTN *) OldCoreData->MaxTopOfCarHeap; + ((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam)) + && StackValue == INIT_CAR_VALUE; + StackPointer++) { + StackValue = *StackPointer; + } + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam)); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR stack ever used: %d bytes.\n", + ((UINTN) OldCoreData->TopOfCarHeap - (UINTN) StackPointer) + ) + ); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR heap used: %d bytes.\n", + ((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom - + (UINTN) OldCoreData->HobList.Raw) + ) + ); + } + ) + +//*** AMI PORTING BEGIN ***// + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; +//*** AMI PORTING END *****// + + // + // Alert any listeners that there is permanent memory available + // + PEI_PERF_START (&PrivateData.PS,L"DisMem", NULL, 0); + Status = PeiInstallPpi (&PrivateData.PS, &mMemoryDiscoveredPpi); + PEI_PERF_END (&PrivateData.PS,L"DisMem", NULL, 0); + + } else { + + // + // Report Status Code EFI_SW_PC_INIT + // + PEI_REPORT_STATUS_CODE ( + &(PrivateData.PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT, + 0, + NULL, + NULL + ); + + // + // If first pass, start performance measurement. + // + PEI_PERF_START (&PrivateData.PS,L"PreMem", NULL, mTick); + + // + // If SEC provided any PPI services to PEI, install them. + // + if (PeiStartupDescriptor->DispatchTable != NULL) { + Status = PeiInstallPpi (&PrivateData.PS, PeiStartupDescriptor->DispatchTable); + + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + } +//*** AMI PORTING BEGIN ***// +{ + static EFI_GUID gEfiPeiLoadedImagePpiGuid = EFI_PEI_LOADED_IMAGE_PPI_GUID; + static EFI_PEI_PPI_DESCRIPTOR LoadedImagePpiDesc = + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiLoadedImagePpiGuid, NULL + }; + PeiAllocatePool(&PrivateData.PS,sizeof(EFI_PEI_PPI_DESCRIPTOR),&PrivateData.LoadedImage); + *PrivateData.LoadedImage = LoadedImagePpiDesc; + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; + PeiInstallPpi (&PrivateData.PS, PrivateData.LoadedImage); +} +//*** AMI PORTING END *****// + } + + DispatchData = &PrivateData.DispatchData; + + // + // Call PEIM dispatcher + // +//*** AMI PORTING BEGIN ***// + if (OldCoreData != NULL) { + AmiInitParts(&PrivateData.PS, InitPartsMem); + ProcessLoadHob(&PrivateData.PS); + } else { + AmiInitParts(&PrivateData.PS, InitParts); + } +//*** AMI PORTING END *****// + PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData); + + // + // Check if InstallPeiMemory service was called. + // +//*** AMI PORTING BEGIN ***// + //report MEMORY_NOT_INSTALLED error + if (!PrivateData.PeiMemoryInstalled) + PEI_ERROR_CODE(&PrivateData.PS, PEI_MEMORY_NOT_INSTALLED, EFI_ERROR_MAJOR); +// PEI_ASSERT(&PrivateData.PS, PrivateData.PeiMemoryInstalled == TRUE); +//*** AMI PORTING END *****// + + PEI_PERF_END (&PrivateData.PS, L"PostMem", NULL, 0); + + Status = PeiLocatePpi ( + &PrivateData.PS, + &gEfiDxeIplPpiGuid, + 0, + NULL, + &TempPtr.DxeIpl + ); +//*** AMI PORTING BEGIN ***// + //report DXEIPL_NOT_FOUND error + if (EFI_ERROR(Status)) + PEI_ERROR_CODE(&PrivateData.PS, PEI_DXEIPL_NOT_FOUND, EFI_ERROR_MAJOR); +// ASSERT_PEI_ERROR (&PrivateData.PS, Status); +//*** AMI PORTING END *****// + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "DXE IPL Entry(%X)\n",TempPtr.DxeIpl->Entry)); + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.PS, +//*** AMI PORTING BEGIN ***// +// PEI CIS defines parameter as EFI_PEI_HOB_POINTERS, but +// EFI_PEI_HOB_POINTERS is not defined in PEI CIS. +// Until this is fixed PEI.h defines this parameter as VOID* +// PrivateData.HobList + PrivateData.HobList.Raw +//*** AMI PORTING END *****// + ); +//*** AMI PORTING BEGIN ***// + // If DXE IPL returned control, let's call dispatcher again + // DXE IPL might have dicovered new FV or have changed a boot mode + + // reset previous bitmap so that the dispatcher will attempt to execute any new PEIMs + DispatchData->PreviousPeimBitMap = 0; + // dispatch + PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData); + // DXE IPL + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.PS, + PrivateData.HobList.Raw + ); +//*** AMI PORTING END *****// + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + return EFI_NOT_FOUND; +} + +//*** AMI PORTING BEGIN ***// +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +) +{ + PEI_CORE_INSTANCE *Private = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + Private->LoadedImagePpi.ImageAddress = ImageAddress; + Private->LoadedImagePpi.ImageSize = ImageSize; + Private->LoadedImagePpi.FileHandle = FileHandle; + PeiReInstallPpi(PeiServices,Private->LoadedImage,Private->LoadedImage); +} +//*** AMI PORTING END *****//
\ No newline at end of file diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c new file mode 100644 index 0000000..62077e3 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Ppi.c @@ -0,0 +1,673 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + Ppi.c + +Abstract: + + EFI PEI Core PPI services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +VOID +InitializePpiServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + if (OldCoreData == NULL) { + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1; + } + + return; +} + +VOID +ConvertPpiPointers ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Convert PPI pointers after the Hob list was migrated from the CAR stack + to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + + None. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT8 Index; + PEI_PPI_LIST_POINTERS *PpiPointer; + UINTN Fixup; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob; + + for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) { + if (Index < PrivateData->PpiData.PpiListEnd || + Index > PrivateData->PpiData.NotifyListEnd) { + PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index]; + + if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the PEIM descriptor from the old HOB heap + // to the relocated HOB heap. + // + PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup); + + // + // Only when the PEIM descriptor is in the old HOB should it be necessary + // to try to convert the pointers in the PEIM descriptor + // + + if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the GUID in the PPI or NOTIFY descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup); + } + + // + // Assume that no code is located in the temporary memory, so the pointer to + // the notification function in the NOTIFY descriptor needs not be converted. + // + if (Index < PrivateData->PpiData.PpiListEnd && + (UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom && + (UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) { + // + // Convert the pointer to the PPI interface structure in the PPI descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup); + } + } + } + } +} + + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN LastCallbackInstall; + + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Index = PrivateData->PpiData.PpiListEnd; + LastCallbackInstall = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the NotifyList + // + if (Index == PrivateData->PpiData.NotifyListEnd + 1) { + return EFI_OUT_OF_RESOURCES; + } + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PrivateData->PpiData.PpiListEnd = LastCallbackInstall; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); +//*** AMI PORTING END *****// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = PpiList; + PrivateData->PpiData.PpiListEnd++; + + // + // Continue until the end of the PPI List. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + PpiList++; + Index++; + } + + // + // Dispatch any callback level notifies for newly installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCallbackInstall, + PrivateData->PpiData.PpiListEnd, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) { + break; + } + } + if (Index == PrivateData->PpiData.PpiListEnd) { + return EFI_NOT_FOUND; + } + + // + // Remove the old PPI from the database, add the new one. + // +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); +//*** AMI PORTING END *****// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = NewPpi; + + // + // Dispatch any callback level notifies for the newly installed PPI. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + 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 (Instance == 0) { + + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + + return EFI_SUCCESS; + } + Instance--; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN NotifyIndex; + INTN LastCallbackNotify; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr; + UINTN NotifyDispatchCount; + + + NotifyDispatchCount = 0; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Index = PrivateData->PpiData.NotifyListEnd; + LastCallbackNotify = Index; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the PpiList + // + if (Index == PrivateData->PpiData.PpiListEnd - 1) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + PrivateData->PpiData.NotifyListEnd = LastCallbackNotify; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyDispatchCount ++; + } + + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList; + + PrivateData->PpiData.NotifyListEnd--; + PEI_DEBUG((PeiServices, EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + // + // Go the next descriptor. Remember the NotifyList moves down. + // + NotifyList++; + Index--; + } + + // + // If there is Dispatch Notify PPI installed put them on the bottom + // + if (NotifyDispatchCount > 0) { + for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) { + if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify; + + for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){ + PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify; + } + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr; + PrivateData->PpiData.DispatchListEnd--; + } + } + + LastCallbackNotify -= NotifyDispatchCount; + } + + // + // Dispatch any callback level notifies for all previously installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiListEnd, + LastCallbackNotify, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN TempValue; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previouly installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // DispatchListEnd (with NotifyPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) { + TempValue = PrivateData->PpiData.DispatchListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.LastDispatchedNotify, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedNotify = TempValue; + } + + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // PpiListEnd (with InstallPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) { + TempValue = PrivateData->PpiData.PpiListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.PpiListEnd, + MAX_PPI_DESCRIPTORS-1, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedInstall = TempValue; + } + + if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) { + break; + } + } + return; +} + +VOID +DispatchNotify ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Remember that Installs moves up and Notifies moves down. + // + for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) { + NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify; + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { + PEI_DEBUG ( + ( + PeiServices, + EFI_D_INFO, + "Notify: PPI Guid: %g, Peim notify entry point: %x\n", + SearchGuid, + NotifyDescriptor->Notify + ) + ); + NotifyDescriptor->Notify ( + PeiServices, + NotifyDescriptor, + (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi + ); + } + } + } + + return; +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c new file mode 100644 index 0000000..bbfd4a9 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Reset.c @@ -0,0 +1,77 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + Reset.c + +Abstract: + + Pei Core Reset System Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (Reset) + +EFI_STATUS +EFIAPI +PeiCoreResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +{ + EFI_STATUS Status; + PEI_RESET_PPI *ResetPpi; + + Status = PeiLocatePpi ( + PeiServices, + &gPeiResetPpiGuid, + 0, + NULL, + &ResetPpi + ); + + // + // LocatePpi returns EFI_NOT_FOUND on error + // + if (!EFI_ERROR (Status)) { + return ResetPpi->ResetSystem (PeiServices); + } +//*** AMI PORTING BEGIN ***// + //Report error + PEI_ERROR_CODE(PeiServices,PEI_RESET_NOT_AVAILABLE,EFI_ERROR_MINOR); +//*** AMI PORTING END *****// + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c new file mode 100644 index 0000000..928e21a --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Security.c @@ -0,0 +1,194 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + Security.c + +Abstract: + + EFI PEI Core Security services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include EFI_PPI_DEFINITION (Security) + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiSecurityPpiGuid, + SecurityPpiNotifyCallback +}; + +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +{ + if (OldCoreData == NULL) { + PeiNotifyPpi (PeiServices, &mNotifyList); + } + return; +} + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Provide a callback for when the security PPI is installed. + +Arguments: + + PeiServices - The PEI core services table. + NotifyDescriptor - The descriptor for the notification event. + Ppi - Pointer to the PPI in question. + +Returns: + + EFI_SUCCESS - The function is successfully processed. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Get PEI Core private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // If there isn't a security PPI installed, use the one from notification + // + if (PrivateData->PrivateSecurityPpi == NULL) { + PrivateData->PrivateSecurityPpi = (PEI_SECURITY_PPI *)Ppi; + } + return EFI_SUCCESS; +} + +EFI_STATUS +VerifyPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + UINT32 AuthenticationStatus; + BOOLEAN StartCrisisRecovery; + + // + // Set a default authentication state + // + AuthenticationStatus = 0; + + // + // get security PPI instance from PEI private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (PrivateData->PrivateSecurityPpi == NULL) { + Status = EFI_NOT_FOUND; + } else { + // + // Check to see if the image is OK + // + Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( + PeiServices, + PrivateData->PrivateSecurityPpi, + AuthenticationStatus, + CurrentPeimAddress, + &StartCrisisRecovery + ); + if (StartCrisisRecovery) { + Status = EFI_SECURITY_VIOLATION; + } + } + return Status; +} + + +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +/*++ + +Routine Description: + + Verify a Firmware volume + +Arguments: + + CurrentFvAddress - Pointer to the current Firmware Volume under consideration + +Returns: + + EFI_SUCCESS - Firmware Volume is legal + EFI_SECURITY_VIOLATION - Firmware Volume fails integrity test + +--*/ +{ + // + // Right now just pass the test. Future can authenticate and/or check the + // FV-header or other metric for goodness of binary. + // + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c new file mode 100644 index 0000000..26cac94 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/StatusCode.c @@ -0,0 +1,102 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + StatusCode.c + +Abstract: + + Pei Core Status Code Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (StatusCode) + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +{ + EFI_STATUS Status; + PEI_STATUS_CODE_PPI *StatusCodePpi; + + + // + //Locate StatusCode Ppi. + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiStatusCodePpiGuid, + 0, + NULL, + &StatusCodePpi + ); + + if (!EFI_ERROR (Status)) { + Status = StatusCodePpi->ReportStatusCode ( + PeiServices, + CodeType, + Value, + Instance, + CallerId, + Data + ); + + + return Status; + + } + + + return EFI_NOT_AVAILABLE_YET; +} + + + diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c new file mode 100644 index 0000000..ff3b2e4 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.c @@ -0,0 +1,268 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + dependency.c + +Abstract: + + PEI Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria for + schedulability is that the dependency expression is satisfied. + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "EfiDependency.h" +#include "Dependency.h" + +STATIC +BOOLEAN +IsPpiInstalled ( + IN EFI_PEI_SERVICES **PeiServices, + IN EVAL_STACK_ENTRY *Stack + ) +/*++ + +Routine Description: + + This routine determines if a PPI has been installed. + The truth value of a GUID is determined by if the PPI has + been published and can be queried from the PPI database. + +Arguments: + PeiServices - The PEI core services table. + Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check + +Returns: + + True if the PPI is already installed. + False if the PPI has yet to be installed. + +--*/ +{ + VOID *PeiInstance; + EFI_STATUS Status; + EFI_GUID PpiGuid; + + // + // If there is no GUID to evaluate, just return current result on stack. + // + if (Stack->Operator == NULL) { + return Stack->Result; + } + + // + // Copy the Guid into a locale variable so that there are no + // possibilities of alignment faults for cross-compilation + // environments such as Intel?Itanium(TM). + // + PeiCoreCopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID)); + + // + // Check if the PPI is installed. + // + Status = (**PeiServices).LocatePpi( + PeiServices, + &PpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &PeiInstance // PPI + ); + + if (EFI_ERROR(Status)) { + return FALSE; + } + + return TRUE; +} + + +EFI_STATUS +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression, + OUT BOOLEAN *Runnable + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +{ + EFI_STATUS Status; + DEPENDENCY_EXPRESSION_OPERAND *Iterator; + EVAL_STACK_ENTRY *StackPtr; + EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; + + Status = EFI_SUCCESS; + Iterator = DependencyExpression; + *Runnable = FALSE; + + StackPtr = &EvalStack[0]; + + while (TRUE) { + + switch (*(Iterator++)) { + + // + // For performance reason we put the frequently used items in front of + // the rarely used items + // + + case (EFI_DEP_PUSH): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return EFI_INVALID_PARAMETER; + } + + // + // Push the pointer to the PUSH opcode operator (pointer to PPI GUID) + // We will evaluate if the PPI is insalled on the POP operation. + // + StackPtr->Operator = (VOID *) Iterator; + Iterator = Iterator + sizeof (EFI_GUID); + StackPtr++; + break; + + case (EFI_DEP_AND): + case (EFI_DEP_OR): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the two POPs for the AND operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did two POPs. + // + if (StackPtr < &EvalStack[2]) { + return EFI_INVALID_PARAMETER; + } + + // + // Evaluate the first POPed operator only. If the operand is + // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the + // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE, + // we don't need to check the second operator, and the result will be + // evaluation of the POPed operator. Otherwise, don't POP the second + // operator since it will now evaluate to the final result on the + // next operand that causes a POP. + // + StackPtr--; + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_AND) { + if (!(IsPpiInstalled (PeiServices, StackPtr))) { + (StackPtr-1)->Result = FALSE; + (StackPtr-1)->Operator = NULL; + } + } else { + if (IsPpiInstalled (PeiServices, StackPtr)) { + (StackPtr-1)->Result = TRUE; + (StackPtr-1)->Operator = NULL; + } + } + break; + + case (EFI_DEP_END): + StackPtr--; + // + // Check to make sure EvalStack is balanced. If not, then there is + // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. + // + if (StackPtr != &EvalStack[0]) { + return EFI_INVALID_PARAMETER; + } + *Runnable = IsPpiInstalled (PeiServices, StackPtr); + return EFI_SUCCESS; + break; + + case (EFI_DEP_NOT): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the POP for the NOT operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did a POP. + // + if (StackPtr < &EvalStack[1]) { + return EFI_INVALID_PARAMETER; + } + (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); + (StackPtr-1)->Operator = NULL; + break; + + case (EFI_DEP_TRUE): + case (EFI_DEP_FALSE): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return EFI_INVALID_PARAMETER; + } + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_TRUE) { + StackPtr->Result = TRUE; + } else { + StackPtr->Result = FALSE; + } + StackPtr->Operator = NULL; + StackPtr++; + break; + + default: + // + // The grammar should never arrive here + // + return EFI_INVALID_PARAMETER; + break; + } + } +} diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h new file mode 100644 index 0000000..9df008b --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/dependency.h @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + dependency.h + +Abstract: + + This module contains data specific to dependency expressions + and local function prototypes. + +--*/ + +#ifndef _PEI_DEPENDENCY_H_ +#define _PEI_DEPENDENCY_H_ + +#define MAX_GRAMMAR_SIZE 256 + +// +// type definitions +// +typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND; + +typedef struct { + BOOLEAN Result; + VOID *Operator; +} EVAL_STACK_ENTRY; + +#endif diff --git a/Core/CORE_PEI/CORE_PEI_PI/BootMode.c b/Core/CORE_PEI/CORE_PEI_PI/BootMode.c new file mode 100644 index 0000000..2c5845a --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/BootMode.c @@ -0,0 +1,107 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + BootMode.c + +Abstract: + + EFI PEI Core Boot Mode services + + + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + if (BootMode == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + *BootMode = HandOffHob->BootMode; + + + return EFI_SUCCESS; +}; + + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + HandOffHob->BootMode = BootMode; + + return EFI_SUCCESS; +}; diff --git a/Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif b/Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif new file mode 100644 index 0000000..62d8649 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/CORE_PEISrcPI.cif @@ -0,0 +1,21 @@ +<component> + name = "CORE_PEI Source PI (EDK)" + category = ModulePart + LocalRoot = "Core\CORE_PEI\CORE_PEI_PI" + RefName = "CORE_PEISrcPI_EDK" +[files] +"BootMode.c" +"dependency.c" +"dependency.h" +"Dispatcher.c" +"FwVol.c" +"Hob.c" +"Image.c" +"MemoryServices.c" +"PeiCore.h" +"PeiMain.c" +"Ppi.c" +"Reset.c" +"Security.c" +"StatusCode.c" +<endComponent> diff --git a/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c b/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c new file mode 100644 index 0000000..91e8821 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Dispatcher.c @@ -0,0 +1,689 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. 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. + +Module Name: + + Dispatcher.c + +Abstract: + + EFI PEI Core dispatch services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) + +//*** AMI PORTING BEGIN ***// +VOID PeiCoreEntry(IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList); +//*** AMI PORTING END *****// +VOID +DiscoverPeimsAndOrderWithApriori ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Discover all Peims and optional Apriori file in one FV. There is at most one + Apriori file in one FV. + +Arguments: + + Private - Pointer to the private data passed in from caller + VolumeHandle - Fv handle. +Returns: + + NONE + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FileHandle; + EFI_PEI_FILE_HANDLE AprioriFileHandle; + EFI_GUID *Apriori; + UINTN Index; + UINTN Index2; + UINTN PeimIndex; + UINTN PeimCount; + EFI_GUID *Guid; + EFI_PEI_FV_HANDLE TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + EFI_GUID FileGuid[PEI_CORE_MAX_PEIM_PER_FV]; + + // + // Walk the FV and find all the PEIMs and the Apriori file. + // + AprioriFileHandle = NULL; + Private->CurrentFvFileHandles[0] = NULL; + Guid = NULL; + FileHandle = NULL; + + // + // If the current Fv has been scanned, directly get its cachable record. + // + if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) { + PeiCoreCopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles)); + return; + } + + // + // Go ahead to scan this Fv, and cache FileHandles within it. + // + for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) { + Status = PeiFindFileEx ( + VolumeHandle, + NULL, + PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, + &FileHandle, + &AprioriFileHandle + ); + if (Status != EFI_SUCCESS) { + break; + } + + Private->CurrentFvFileHandles[PeimCount] = FileHandle; + } + + Private->AprioriCount = 0; + if (AprioriFileHandle != NULL) { + // + // Read the Apriori file + // + Status = PeiFfsFindSectionData (&Private->PS, EFI_SECTION_RAW, AprioriFileHandle, &Apriori); + if (!EFI_ERROR (Status)) { + // + // Calculate the number of PEIMs in the A Priori list + // + Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF; + Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER); + Private->AprioriCount /= sizeof (EFI_GUID); + + PeiCoreSetMem (FileGuid, sizeof (FileGuid), 0); + for (Index = 0; Index < PeimCount; Index++) { + // + // Make an array of file name guids that matches the FileHandle array so we can convert + // quickly from file name to file handle + // + PeiCoreCopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID)); + } + + // + // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file. + // Add avalible PEIMs in Apriori file into TempFileHandles array at first. + // + Index2 = 0; + for (Index = 0; Index2 < Private->AprioriCount; Index++) { + while (Index2 < Private->AprioriCount) { + Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]); + if (Guid != NULL) { + break; + } + } + if (Guid == NULL) { + break; + } + PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID); + TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex]; + + // + // Since we have copied the file handle we can remove it from this list. + // + Private->CurrentFvFileHandles[PeimIndex] = NULL; + } + + // + // Update valid Aprioricount + // + Private->AprioriCount = Index; + + // + // Add in any PEIMs not in the Apriori file + // + for (;Index < PeimCount; Index++) { + for (Index2 = 0; Index2 < PeimCount; Index2++) { + if (Private->CurrentFvFileHandles[Index2] != NULL) { + TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2]; + Private->CurrentFvFileHandles[Index2] = NULL; + break; + } + } + } + // + //Index the end of array contains re-range Pei moudle. + // + TempFileHandles[Index] = NULL; + + // + // Private->CurrentFvFileHandles is currently in PEIM in the FV order. + // We need to update it to start with files in the A Priori list and + // then the remaining files in PEIM order. + // + PeiCoreCopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles)); + } + } + // + // Cache the current Fv File Handle. So that we don't have to scan the Fv again. + // Instead, we can retrieve the file handles within this Fv from cachable data. + // + Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE; + PeiCoreCopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles)); + +} + + +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + Private - Pointer to the private data passed in from caller + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +{ + EFI_STATUS Status; + UINT32 Index1; + UINT32 Index2; + EFI_PEI_SERVICES **PeiServices; + VOID *PrivateInMem; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + EFI_PEI_FILE_HANDLE PeimFileHandle; + UINTN FvCount; + UINTN PeimCount; + UINT32 AuthenticationState; + EFI_PHYSICAL_ADDRESS EntryPoint; + EFI_PEIM_ENTRY_POINT PeimEntryPoint; + VOID* PeiCoreReentryPoint; + UINTN SaveCurrentPeimCount; + UINTN SaveCurrentFvCount; + EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; + + PEI_REPORT_STATUS_CODE_CODE ( + + EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + ExtendedData.DataHeader.HeaderSize = (UINT16)sizeof (EFI_STATUS_CODE_DATA); + ExtendedData.DataHeader.Size = (UINT16)(sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - ExtendedData.DataHeader.HeaderSize); + + PeiCoreCopyMem ( + &ExtendedData.DataHeader.Type, + &gEfiStatusCodeSpecificDataGuid, + sizeof (EFI_GUID) + ); + ) + + PeiServices = &Private->PS; + PeimEntryPoint = NULL; + PeimFileHandle = NULL; + + if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile + // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE. + // + SaveCurrentPeimCount = Private->CurrentPeimCount; + SaveCurrentFvCount = Private->CurrentPeimFvCount; + SaveCurrentFileHandle = Private->CurrentFileHandle; + + for (Index1 = 0;Index1 <= SaveCurrentFvCount; Index1++) { + for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) { + if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) { + PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2]; + Status = PeiLoadImage ( + &Private->PS, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + if (Status == EFI_SUCCESS) { + // + // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[Index1].PeimState[Index2]++; + Private->CurrentFileHandle = PeimFileHandle; + Private->CurrentPeimFvCount = Index1; + Private->CurrentPeimCount = Index2; + + // + // Call the PEIM entry point + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + + PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + PeimEntryPoint(PeimFileHandle, &Private->PS); + PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + } + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (&Private->PS); + } + } + } + Private->CurrentFileHandle = SaveCurrentFileHandle; + Private->CurrentPeimFvCount = SaveCurrentFvCount; + Private->CurrentPeimCount = SaveCurrentPeimCount; + } + + // + // This is the main dispatch loop. It will search known FVs for PEIMs and + // attempt to dispatch them. If any PEIM gets dispatched through a single + // pass of the dispatcher, it will start over from the Bfv again to see + // if any new PEIMs dependencies got satisfied. With a well ordered + // FV where PEIMs are found in the order their dependencies are also + // satisfied, this dipatcher should run only once. + // + do { + // + // In case that reenter PeiCore happens, the last pass record is still available. + // + if (!Private->PeimDispatcherReenter) { + Private->PeimNeedingDispatch = FALSE; + Private->PeimDispatchOnThisPass = FALSE; + } else { + Private->PeimDispatcherReenter = FALSE; + } + for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) { + Private->CurrentPeimFvCount = FvCount; + VolumeHandle = Private->Fv[FvCount].FvHeader; + + if (Private->CurrentPeimCount == 0) { + // + // When going through each FV, at first, search Apriori file to + // reorder all PEIMs to ensure the PEIMs in Apriori file to get + // dispatch at first. + // + DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle); + } + + // + // Start to dispatch all modules within the current Fv. + // + for (PeimCount = Private->CurrentPeimCount; + (PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL); + PeimCount++) { + Private->CurrentPeimCount = PeimCount; + PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount]; + + if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) { + if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) { + Private->PeimNeedingDispatch = TRUE; + } else { + Status = PeiLoadImage ( + PeiServices, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + if ((Status == EFI_SUCCESS)) { + // + // The PEIM has its dependencies satisfied, and its entry point + // has been found, so invoke it. + // + PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + + PEI_REPORT_STATUS_CODE_CODE ( + ExtendedData.Handle = PeimFileHandle; + ) + + PEI_REPORT_STATUS_CODE_CODE ( + PeiReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + ) + + Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle); + if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) { + // + // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED + // + Private->Fv[FvCount].PeimState[PeimCount]++; + + // + // Call the PEIM entry point + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + PeimEntryPoint (PeimFileHandle, PeiServices); + Private->PeimDispatchOnThisPass = TRUE; + } + + PEI_REPORT_STATUS_CODE_CODE ( + PeiReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END, + 0, + NULL, + (EFI_STATUS_CODE_DATA *)(&ExtendedData) + ); + ) + PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + } + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (PeiServices); + + // + // If permanent memory was discovered and installed by this + // PEIM, shadow PEI Core and switch the stacks to the new memory. + // + if (Private->SwitchStackSignal) { + + // + // Make sure we don't retry the same PEIM that added memory + // + Private->CurrentPeimCount++; + + // + // Indicate that PeiCore reenter + // + Private->PeimDispatcherReenter = TRUE; + // + // Migrate IDT from CAR into real memory, so after stack switches to + // the new memory, the caller can get memory version PeiServiceTable. + // + MigrateIdtTable (PeiServices); + // + // Since we are at dispatch level, only the Core's private data + // is preserved, nobody else should have any data on the stack. + // So we need to copy PEI core instance data to memory. + // + Status = PeiAllocatePool (PeiServices, sizeof (PEI_CORE_INSTANCE), &PrivateInMem); + ASSERT_PEI_ERROR (PeiServices, Status); + PeiCoreCopyMem (PrivateInMem, Private, sizeof (PEI_CORE_INSTANCE)); + + // + // Shadow PEI Core. When permanent memory is avaiable, shadow + // PEI Core and PEIMs to get high performance. + // + PeiCoreFileHandle = NULL; + // + // Find the PEI Core in the BFV + // + Status = PeiFindFileEx ( + (EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader, + NULL, + EFI_FV_FILETYPE_PEI_CORE, + &PeiCoreFileHandle, + NULL + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + // + // Shadow PEI Core into memory so it will run faster + // + Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState); + ASSERT_PEI_ERROR (PeiServices, Status); + + // + // The 2nd time around we need to call PeiCore passing in a non + // NULL value to OldCoreData. We can not call the PE COFF entry + // point (_EntryPoint) as it had codes a NULL into OldCoreData. + // We calculate the memory (shadowed) address of PeiCore by + // figuring out the offset from _EntryPoint to PeiCore and then + // adding that value to the new memory based entry point. + // + PeiCoreReentryPoint = (VOID*)(UINTN)(EntryPoint + +//*** AMI PORTING BEGIN ***// +// (((UINT8 *)(UINTN)PeiCore) - (UINT8 *)(UINTN)PeiMain)); + (((UINT8 *)(UINTN)PeiCore) - (UINT8 *)(UINTN)PeiCoreEntry)); +//*** AMI PORTING END ***// + + + // + // Switch to memory based stack and reenter PEI Core that has been + // shadowed to memory. + // + SwitchCoreStacks ( + PeiCoreReentryPoint, + (UINTN)SecCoreData, + (UINTN)NULL, + (UINTN)PrivateInMem, + (VOID*)((UINTN)Private->StackBase + (UINTN)Private->StackSize - 0x10) + ); + } + + if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \ + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // If memory is availble we shadow images by default for performance reasons. + // We call the entry point a 2nd time so the module knows it's shadowed. + // + PEI_PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + PeimEntryPoint (PeimFileHandle, PeiServices); + PEI_PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + + // + // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[FvCount].PeimState[PeimCount]++; + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (PeiServices); + } + } + } + } + + // + // We set to NULL here to optimize the 2nd entry to this routine after + // memory is found. This reprevents rescanning of the FV. We set to + // NULL here so we start at the begining of the next FV + // + Private->CurrentFileHandle = NULL; + Private->CurrentPeimCount = 0; + // + // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL + // + PeiCoreSetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0); + } + + // + // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go + // through all the FV. + // + Private->CurrentPeimFvCount = 0; + + // + // PeimNeedingDispatch being TRUE means we found a PEIM that did not get + // dispatched. So we need to make another pass + // + // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this + // pass. If we did not dispatch a PEIM there is no point in trying again + // as it will fail the next time too (nothing has changed). + // + } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass); + +//*** AMI PORTING BEGIN ***// + // Print out a list of the PEIMs that were not dispatched + PEI_DEBUG_CODE + ( + { + UINTN i = 0; + UINTN j = 0; + + for(i = 0; i < PEI_CORE_MAX_FV_SUPPORTED; i++) + { + for(j = 0; j < PEI_CORE_MAX_PEIM_PER_FV; j++) + { + if( Private->Fv[i].FvFileHandles[j] == NULL) continue; + + if(Private->Fv[i].PeimState[j] == PEIM_STATE_NOT_DISPATCHED) + PEI_DEBUG((&Private->PS, -1, "WARNING -> PEIM Not Dispatched: %g\n", &((EFI_FFS_FILE_HEADER*)(Private->Fv[i].FvFileHandles[j]))->Name )); + } + } + } + ) +//*** AMI PORTING END *****// +} + + +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + SecCoreData - Information and services provided by SEC phase. + +Returns: + + None. + +--*/ +{ + if (OldCoreData == NULL) { + PeiInitializeFv (PrivateData, SecCoreData); + } + + return; +} + + +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + + Private - Pointer to the private data passed in from caller. + FileHandle - File handle of PEIM. + PeimCount - The PEIM sequence in one FV. + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +{ + EFI_STATUS Status; + INT8 *DepexData; + + if (PeimCount < Private->AprioriCount) { + // + // If its in the A priori file then we set Depex to TRUE + // + return TRUE; + } + + Status = PeiFfsFindSectionData (&Private->PS, EFI_SECTION_PEI_DEPEX, FileHandle, &DepexData); + if (EFI_ERROR (Status)) { + // + // If there is no DEPEX, assume the module can be executed + // + return TRUE; + } + + // + // Evaluate a given DEPEX + // + return PeimDispatchReadiness (&Private->PS, DepexData); +} + + +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + This routine enable a PEIM to register itself to shadow when PEI Foundation + discovery permanent memory. + +Arguments: + FileHandle - File handle of a PEIM. + +Returns: + EFI_NOT_FOUND - The file handle doesn't point to PEIM itself. + EFI_ALREADY_STARTED - Indicate that the PEIM has been registered itself. + EFI_SUCCESS - Successfully to register itself. + +--*/ +{ + PEI_CORE_INSTANCE *Private; + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + + if (Private->CurrentFileHandle != FileHandle) { + // + // The FileHandle must be for the current PEIM + // + return EFI_NOT_FOUND; + } + + if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) { + // + // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started + // + return EFI_ALREADY_STARTED; + } + + Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW; + + return EFI_SUCCESS; +} + + + diff --git a/Core/CORE_PEI/CORE_PEI_PI/FwVol.c b/Core/CORE_PEI/CORE_PEI_PI/FwVol.c new file mode 100644 index 0000000..2ecf88e --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/FwVol.c @@ -0,0 +1,782 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVol.c + +Abstract: + + Pei Core Firmware File System service routines. + +--*/ + +#include "Tiano.h" +#include "EfiImageFormat.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiFirmwareVolumeInfoPpiGuid, + FirmwareVolmeInfoPpiNotifyCallback +}; + + + + +STATIC +EFI_FFS_FILE_STATE +GetFileState( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Returns the highest bit set of the State field + +Arguments: + + ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY + in the Attributes field. + FfsHeader - Pointer to FFS File Header. + +Returns: + Returns the highest bit in the State field + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +STATIC +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +/*++ + +Routine Description: + + Calculates the checksum of the header of a file. + +Arguments: + + FileHeader - Pointer to FFS File Header. + +Returns: + Checksum of the header. + + The header is zero byte checksum. + - Zero means the header is good. + - Non-zero means the header is bad. + + +Bugbug: For PEI performance reason, we comments this code at this time. +--*/ +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + ptr = (UINT8 *)FileHeader; + + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8)(Sum + ptr[Index]); + Sum = (UINT8)(Sum + ptr[Index+1]); + Sum = (UINT8)(Sum + ptr[Index+2]); + Sum = (UINT8)(Sum + ptr[Index+3]); + } + + for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8)(Sum + ptr[Index]); + } + + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8)(Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +STATIC +BOOLEAN +EFIAPI +PeiFileHandleToVolume ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + UINTN Index; + PEI_CORE_INSTANCE *PrivateData; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + for (Index = 0; Index < PrivateData->FvCount; Index++) { + FwVolHeader = PrivateData->Fv[Index].FvHeader; + if (((UINTN)FileHandle > (UINTN)FwVolHeader ) && \ + ((UINTN)FileHandle < ((UINTN)FwVolHeader + (UINTN)FwVolHeader->FvLength))) { + *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader; + return TRUE; + } + } + return FALSE; +} + + +EFI_STATUS +PeiFindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER **FileHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle; + FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle; + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) or FileName is not NULL, + // start with the first file in the firmware volume. Otherwise, + // start from the FileHeader. + // + if ((*FileHeader == NULL) || (FileName != NULL)) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize); + } + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + PEI_ASSERT (PeiServices,(FileOffset <= 0xFFFFFFFF)); + + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof(EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) != 0) { +//*** AMI PORTING BEGIN ***// +// Skip the assert to support a more sophisiticated +// FV corruption handling outside of the Core. +// PEI_ASSERT (PeiServices,FALSE); +//*** AMI PORTING END *****// + return EFI_NOT_FOUND; + } + + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + + if (FileName != NULL) { + if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } else if (AprioriFile != NULL) { + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) { + if (CompareGuid (&FfsFileHeader->Name, &gEfiPeiAprioriGuid)) { + *AprioriFile = FfsFileHeader; + } + } + } + } else if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + + +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize PeiCore Fv List. + +Arguments: + PrivateData - Pointer to PEI_CORE_INSTANCE. + SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +Returns: + NONE + +--*/ +{ + EFI_STATUS Status; + // + // The BFV must be the first entry. The Core FV support is stateless + // The AllFV list has a single entry per FV in PEI. + // The Fv list only includes FV that PEIMs will be dispatched from and + // its File System Format is PI 1.0 definition. + // + PrivateData->FvCount = 1; + PrivateData->Fv[0].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; + + PrivateData->AllFvCount = 1; + PrivateData->AllFv[0] = (EFI_PEI_FV_HANDLE)PrivateData->Fv[0].FvHeader; + + + // + // Post a call-back for the FvInfoPPI services to expose + // additional Fvs to PeiCore. + // + Status = (PrivateData->PS)->NotifyPpi (&PrivateData->PS, &mNotifyList); + ASSERT_PEI_ERROR (&PrivateData->PS, Status); + +} + + + +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Process Firmware Volum Information once FvInfoPPI install. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +{ + UINT8 FvCount; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (PrivateData->FvCount >= PEI_CORE_MAX_FV_SUPPORTED) { + PEI_ASSERT (GetPeiServicesTablePointer(),FALSE); + } + + Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi; + + if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) { + for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) { + if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) { + return EFI_SUCCESS; + } + } + PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo; + } + + // + // Allways add to the All list + // + PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +/*++ + +Routine Description: + + Search the next FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + Instance - The Fv Volume Instance. + VolumeHandle - Pointer to the current Fv Volume to search. + +Returns: + EFI_INVALID_PARAMETER - VolumeHandle is NULL. + EFI_NOT_FOUND - No FV Volume is found. + EFI_SUCCESS - The next FV Volume is found. + +--*/ + +{ + PEI_CORE_INSTANCE *Private; + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + if (VolumeHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Instance >= Private->AllFvCount) { + VolumeHandle = NULL; + return EFI_NOT_FOUND; + } + + *VolumeHandle = Private->AllFv[Instance]; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input FvHandle, search for the next matching type file in the FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only file of this type. + FvHandle - Pointer to the current FV to search. + FileHandle - Pointer to the file matching SearchType in FwVolHeader. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +{ + return PeiFindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL); +} + +EFI_STATUS +PeiFfsProcessSection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_COMMON_SECTION_HEADER *Section, + IN UINTN SectionSize, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *Authentication + ) +/*++ + +Routine Description: + + Go through the file to search SectionType section, + when meeting an encapsuled section, search recursively. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only section of this type. + Section - From where to search. + SectionSize - The file size to search. + OutputBuffer - Pointer to the section to search. + OutputSize - The size of the section to search. + Authentication - Authenticate the section. + +Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + UINT32 SectionLength; + UINT32 ParsedLength; + EFI_GUID_DEFINED_SECTION *GuidSection; + EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_PEI_DECOMPRESS_PPI *DecompressPpi; + VOID *PpiOutput; + UINTN PpiOutputSize; + + *OutputBuffer = NULL; + ParsedLength = 0; + while (ParsedLength < SectionSize) { + if (Section->Type == SectionType) { + *OutputBuffer = (VOID *)(Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_GUID_DEFINED) { + GuidSection = (EFI_GUID_DEFINED_SECTION *)Section; + GuidSectionPpi = PeiReturnPpi (PeiServices, &GuidSection->SectionDefinitionGuid); + if (GuidSectionPpi != NULL) { + Status = GuidSectionPpi->ExtractSection ( + GuidSectionPpi, + Section, + &PpiOutput, + &PpiOutputSize, + Authentication + ); + if (!EFI_ERROR (Status)) { + return PeiFfsProcessSection ( + PeiServices, + SectionType, + PpiOutput, + PpiOutputSize, + OutputBuffer, + OutputSize, + Authentication + ); + } + } + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + CompressionSection = (EFI_COMPRESSION_SECTION *)Section; + DecompressPpi = PeiReturnPpi (PeiServices, &gEfiPeiDecompressPpiGuid); + if (DecompressPpi != NULL) { + Status = DecompressPpi->Decompress ( + DecompressPpi, + CompressionSection, + &PpiOutput, + &PpiOutputSize + ); + if (!EFI_ERROR (Status)) { + return PeiFfsProcessSection ( + PeiServices, SectionType, PpiOutput, PpiOutputSize, OutputBuffer, OutputSize, Authentication + ); + } + } + } + + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + PEI_ASSERT (PeiServices, (SectionLength != 0)); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FileHandle - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN OutputSize; + UINT32 AuthenticationStatus; + + + FfsFileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); + FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof (EFI_FFS_FILE_HEADER); + + return PeiFfsProcessSection ( + PeiServices, + SectionType, + Section, + FileSize, + SectionData, + &OutputSize, + &AuthenticationStatus + ); +} + + +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input VolumeHandle, search for the next matching name file. + +Arguments: + + FileName - File name to search. + VolumeHandle - The current FV to search. + FileHandle - Pointer to the file matching name in VolumeHandle. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + Status = PeiFindFileEx (VolumeHandle, FileName, 0, FileHandle, NULL); + if (Status == EFI_NOT_FOUND) { + *FileHandle = NULL; + } + return Status; +} + + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +/*++ + +Routine Description: + + Collect information of given file. + +Arguments: + FileHandle - The handle to file. + FileInfo - Pointer to the file information. + +Returns: + EFI_STATUS + +--*/ +{ + UINT8 FileState; + UINT8 ErasePolarity; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_PEI_FV_HANDLE VolumeHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + if (!PeiFileHandleToVolume(FileHandle, &VolumeHandle)) { + return EFI_INVALID_PARAMETER; + } + + if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle); + + switch (FileState) { + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + break; + default: + return EFI_INVALID_PARAMETER; + } + + FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID)); + FileInfo->FileType = FileHeader->Type; + FileInfo->FileAttributes = FileHeader->Attributes; + FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER); + FileInfo->Buffer = (FileHeader + 1); + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + Collect information of given Fv Volume. + +Arguments: + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + + if (VolumeInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)VolumeHandle; + VolumeInfo->FvAttributes = FwVolHeader->Attributes; + VolumeInfo->FvStart = FwVolHeader; + VolumeInfo->FvSize = FwVolHeader->FvLength; + CopyMem (&VolumeInfo->FvFormat, &FwVolHeader->FileSystemGuid,sizeof(EFI_GUID)); + + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID)); + } + return EFI_SUCCESS; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/Hob.c b/Core/CORE_PEI/CORE_PEI_PI/Hob.c new file mode 100644 index 0000000..30b7b3f --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Hob.c @@ -0,0 +1,191 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + Hob.c + +Abstract: + + EFI PEI Core HOB services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +{ + // + // Only check this parameter in debug mode + // + + PEI_DEBUG_CODE ( + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + ) + + *HobList = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices)->HobList.Raw; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + + Status = PeiGetHobList (PeiServices, Hob); + if (EFI_ERROR(Status)) { + return Status; + } + + HandOffHob = *Hob; + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_PI/Image.c b/Core/CORE_PEI/CORE_PEI_PI/Image.c new file mode 100644 index 0000000..a6967e0 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Image.c @@ -0,0 +1,932 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. 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. + +Module Name: + + Image.c + +Abstract: + + Pei Core Load Image Support + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "PeiApi.h" +#include "EfiImage.h" +#include EFI_PROTOCOL_DEFINITION (CustomizedDecompress) + +#include EFI_PPI_DEFINITION (LoadFile2) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include EFI_PPI_DEFINITION (SectionExtraction) + + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +; + +EFI_STATUS +PeiLoadImageLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + The wrapper function of PeiLoadImageLoadImage(). + +Arguments: + + This - Pointer to EFI_PEI_LOAD_FILE_PPI. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + EFI_STATUS. + +--*/ +; + + +EFI_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for get PE image entry point. + +Arguments: + + Pe32Data - Pointer to PE image. + EntryPoint - Pointer to entry point of PE image. + +Returns: + + EFI_SUCCESS. + +--*/ +; + +EFI_IMAGE_NT_HEADERS* +EFIAPI +GetPeHeader ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Pe32Data + ) +/*++ + +Routine Description: + + Routine for get PE image header. + +Arguments: + PeiServices - The PEI core services table. + Pe32Data - Pointer to PE image. + +Returns: + + Pointer to PE header. + +--*/ +; + +static EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = { + PeiLoadImageLoadImageWrapper +}; + + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiLoadFile2PpiGuid, + &mPeiLoadImagePpi +}; + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Support routine to return the Image Read + +Arguments: + + PeiServices - PEI Services Table + + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS - If Image function location is found + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryBuffer; + + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiBootServicesData, + 0x400 / EFI_PAGE_SIZE + 1, + &MemoryBuffer + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + (*PeiServices)->CopyMem ( + (VOID *) (UINTN) MemoryBuffer, + (VOID *) (UINTN) PeiImageRead, + 0x400 + ); + + ImageContext->ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return Status; +} + +EFI_STATUS +PeiLoadImageLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + PEI_CORE_INSTANCE *Private; + VOID *Pe32Data; + EFI_TE_IMAGE_HEADER *TEImageHeader; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeCoffLoader; + +#ifdef EFI_NT_EMULATOR + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; +#else + VOID *EntryPointPtr; +#endif +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of compressed PEIMS +//and PEIMS from the firmware volumes in memory (see below). + BOOLEAN FixupRequired = FALSE; +//*** AMI PORTING END *****// + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + *EntryPoint = 0; + *AuthenticationState = 0; + ImageAddress = 0; + ImageSize = 0; + PeHdr = NULL; + + // + // Try to find a TE or PE32 section. + // + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_TE, + FileHandle, + (VOID **)&TEImageHeader + ); + Pe32Data = TEImageHeader; + if (EFI_ERROR (Status)) { + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PE32, + FileHandle, + &Pe32Data + ); + } + + if (EFI_ERROR (Status)) { + // + // NO image types we support so exit. + // + return Status; + } + + // + // Check image header machine type. If not supported, skip it. + // + if (TEImageHeader != NULL) { + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (TEImageHeader->Machine) && + !EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (TEImageHeader->Machine)) { + return EFI_UNSUPPORTED; + } + } else { + // + // Get PE32 Header to check machine type. + // + PeHdr = GetPeHeader(PeiServices, Pe32Data); + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHdr->FileHeader.Machine) && + !EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (PeHdr->FileHeader.Machine)) { + return EFI_UNSUPPORTED; + } +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of compressed PEIMS +//and PEIMS from the firmware volumes in memory. + if (PeHdr->OptionalHeader.ImageBase != (UINTN)Pe32Data) + FixupRequired = TRUE; +//*** AMI PORTING END *****// + } + + if (Private->PeiMemoryInstalled && + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || FixupRequired)) { + // + // Load, relocate, and run image in memory + // + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + if (Private->ImageReadFile == NULL) { + GetImageReadFunction (PeiServices, &ImageContext); + Private->ImageReadFile = ImageContext.ImageRead; + } else { + ImageContext.ImageRead = Private->ImageReadFile; + } + PeCoffLoader = Private->PeCoffLoader; + Status = PeCoffLoader->GetImageInfo (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + Status = PeiAllocatePages ( + PeiServices, + EfiBootServicesData, + EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), + &ImageContext.ImageAddress + ); + ASSERT_PEI_ERROR (PeiServices,Status); + + if (ImageContext.IsTeImage && + TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) { + ImageContext.ImageAddress = ImageContext.ImageAddress + + TEImageHeader->StrippedSize - + sizeof (EFI_TE_IMAGE_HEADER); + } + + // + // Load the image to our new buffer + // + Status = PeCoffLoader->LoadImage (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoader->RelocateImage (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + ImageAddress = ImageContext.ImageAddress; + ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + } +#ifndef EFI_NT_EMULATOR + else if (TEImageHeader != NULL) { + // + // Get entry point from the TE image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)TEImageHeader; +//*** AMI PORTING BEGIN ***// +//Bug fix: the function must return a valid image size +// The original implmentation always returns NULL for XIP images. + ImageSize = FVSECTION_SIZE(TEImageHeader); +// ImageSize = 0; +//*** AMI PORTING END ***// + *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + // + // Retrieve the entry point from the PE/COFF image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data; +//*** AMI PORTING BEGIN ***// +//Bug fix: the function must return a valid image size +// The original implmentation always returns NULL for XIP images. + ImageSize = PeHdr->OptionalHeader.SizeOfImage; +// ImageSize = 0; +//*** AMI PORTING END ***// + Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointPtr); + *EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPointPtr; + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } +#else + else { + if (TEImageHeader == NULL) { + PeHdr = GetPeHeader(PeiServices,Pe32Data); + } + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + EntryPoint + ); + + if (EFI_ERROR (Status)) { + if (TEImageHeader != NULL) { + *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (EFI_PHYSICAL_ADDRESS) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } + } + } +#endif + + + if (ImageAddressArg != NULL) { + *ImageAddressArg = ImageAddress; + } + + if (ImageSizeArg != NULL) { + *ImageSizeArg = ImageSize; + } + +//*** AMI PORTING BEGIN ***// +//Message is printed later. Disable this one +/* + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); + PEI_DEBUG_CODE ( + { + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + UINTN Index; + UINTN Index1; + BOOLEAN FileNameFound; + CHAR8 *AsciiString; + CHAR8 AsciiBuffer[512]; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHeader; + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + + // + // Find the codeview info in the image and display the file name + // being loaded. + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + DebugEntry = NULL; + DirectoryEntry = NULL; + TEImageAdjust = 0; + if (TEImageHeader == NULL) { + if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); + } + } else { + if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + + TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } + + if (DebugEntry != NULL && DirectoryEntry != NULL) { + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + AsciiString = NULL; + break; + } + if (AsciiString != NULL) { + FileNameFound = FALSE; + for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { + if (AsciiString[Index] == '\\') { + Index1 = Index; + FileNameFound = TRUE; + } + } + + if (FileNameFound) { + for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { + AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; + } + AsciiBuffer[Index - (Index1 + 1)] = 0; + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + } + ) + + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "\n")); +*/ +//*** AMI PORTING END ***// + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + The wrapper function of PeiLoadImageLoadImage(). + +Arguments: + + This - Pointer to EFI_PEI_LOAD_FILE_PPI. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + EFI_STATUS. + +--*/ +{ + return PeiLoadImageLoadImage ( + GetPeiServicesTablePointer (), + FileHandle, + ImageAddressArg, + ImageSizeArg, + EntryPoint, + AuthenticationState + ); +} + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for load image file. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS PpiStatus; + EFI_STATUS Status; + UINTN Index; + EFI_PEI_LOAD_FILE_PPI *LoadFile; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + UINT16 Magic; + UINT16 Machine; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + + // + // If any instances of PEI_LOAD_FILE_PPI are installed, they are called. + // one at a time, until one reports EFI_SUCCESS. + // + Index = 0; + do { + PpiStatus = PeiLocatePpi ( + PeiServices, + &gEfiLoadFile2PpiGuid, + Index, + NULL, + (VOID **)&LoadFile + ); + if (!EFI_ERROR (PpiStatus)) { + Status = LoadFile->LoadFile ( + LoadFile, + FileHandle, + &ImageAddress, + &ImageSize, + EntryPoint, + AuthenticationState + ); + if (!EFI_ERROR (Status)) { + // + // Only support image machine type that is the same as PEI core. + // Get the image's machine type to check if supported. + // + Magic = *(UINT16 *)(UINTN) ImageAddress; + if (Magic == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TeHdr = (EFI_TE_IMAGE_HEADER *)(UINTN) ImageAddress; + Machine = TeHdr->Machine; + } else { + if (Magic == EFI_IMAGE_DOS_SIGNATURE) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN) ImageAddress + (UINTN) ((((EFI_IMAGE_DOS_HEADER *)(UINTN) ImageAddress)->e_lfanew) & 0x0ffff)); + } else { + PeHdr = (EFI_IMAGE_NT_HEADERS *)(UINTN) ImageAddress; + } + Machine = PeHdr->FileHeader.Machine; + } + if (Machine == EFI_IMAGE_MACHINE_TYPE) { +//*** AMI PORTING BEGIN ***// +//break from the loop to print debug message (see below) +// return EFI_SUCCESS; + PpiStatus=EFI_SUCCESS; + break; +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// +//break from the loop to print debug message (see below) +// return EFI_UNSUPPORTED; + PpiStatus=EFI_SUCCESS; + break; +//*** AMI PORTING END *****// + } + } + } + Index++; + } while (!EFI_ERROR (PpiStatus)); +//*** AMI PORTING BEGIN ***// +//Print debug message +#ifdef EFI_DEBUG +{ + EFI_FFS_FILE_HEADER *PeimFileHeader = (EFI_FFS_FILE_HEADER*)FileHandle; + if(!EFI_ERROR(PpiStatus)) + { + char sName[0x100]; + if (!GetName((VOID*)(UINTN)ImageAddress,sName)) + Sprintf_s(sName,sizeof(sName),"[%G]",&PeimFileHeader->Name); + PeiTrace(TRACE_PEICORE, PeiServices, "%s.Entry(%X)\n", sName, *EntryPoint); + } + else + { + PeiTrace( + TRACE_PEICORE, PeiServices, + "ERROR: attempt to load FFS file [%G] has failed\n", + &PeimFileHeader->Name + ); + } +} +#endif +//New image is loaded and is about to be launched +//Update LoadedImage PPI information + if(!EFI_ERROR(PpiStatus)) + UpdatedLoadedImagePpi(PeiServices,ImageAddress,ImageSize,FileHandle); +//*** AMI PORTING END *****// + return PpiStatus; +} + + +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Regitser PeCoffLoader to PeiCore PrivateData. And install + Pei Load File PPI. + +Arguments: + + PrivateData - Pointer to PEI_CORE_INSTANCE. + OldCoreData - Pointer to PEI_CORE_INSTANCE. + +Returns: + + NONE. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + + InstallEfiPeiPeCoffLoader (&PrivateData->PS, &PeiEfiPeiPeCoffLoader, NULL); + PrivateData->PeCoffLoader = PeiEfiPeiPeCoffLoader; + + if (OldCoreData == NULL) { + // + // The first time we are XIP (running from FLASH). We need to remember the + // FLASH address so we can reinstall the memory version that runs faster + // + PrivateData->XipLoadFile = &gPpiLoadFilePpiList; + PeiInstallPpi (&PrivateData->PS, PrivateData->XipLoadFile); + } else { + // + // 2nd time we are running from memory so replace the XIP version with the + // new memory version. + // + PeiReInstallPpi (&PrivateData->PS, PrivateData->XipLoadFile, &gPpiLoadFilePpiList); + } +} + + +EFI_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for get PE image entry point. + +Arguments: + + Pe32Data - Pointer to PE image. + EntryPoint - Pointer to entry point of PE image. + +Returns: + + EFI_SUCCESS. + +--*/ +{ + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_SERVICES **PeiServices; + + PeHdr = NULL; + PeiServices = GetPeiServicesTablePointer(); + + PEI_ASSERT (PeiServices, (Pe32Data != NULL)); + PEI_ASSERT (PeiServices,(EntryPoint != NULL)); + + PeHdr = GetPeHeader(PeiServices, Pe32Data); + + // + // Calculate the entry point relative to the start of the image. + // AddressOfEntryPoint is common for PE32 & PE32+ + // + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + return EFI_SUCCESS; +} + +EFI_IMAGE_NT_HEADERS* +EFIAPI +GetPeHeader ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Pe32Data + ) +/*++ + +Routine Description: + + Routine for get PE image header. + +Arguments: + PeiServices - The PEI core services table. + Pe32Data - Pointer to PE image. + +Returns: + + Pointer to PE header. + +--*/ +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHdr; + + PeHdr = NULL; + PEI_ASSERT (PeiServices, (Pe32Data != NULL)); + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + return PeHdr; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c b/Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c new file mode 100644 index 0000000..05a0ff3 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/MemoryServices.c @@ -0,0 +1,392 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + MemoryServices.c + +Abstract: + + EFI PEI Core memory services + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" +#include "PeiCore.h" +#include "PeiLib.h" +//*** AMI PORTING BEGIN ***// +//use SDL token 'DXE_STACK_SIZE' to define stack size +#include <Token.h> +#undef PEI_STACK_SIZE +#define PEI_STACK_SIZE DXE_STACK_SIZE +//*** AMI PORTING END *****// + +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +{ + PrivateData->SwitchStackSignal = FALSE; + + if (OldCoreData == NULL) { + // + // 1st time through we are using Temp memory + // + PrivateData->PeiMemoryInstalled = FALSE; + PrivateData->BottomOfCarHeap = SecCoreData->PeiTemporaryRamBase; + PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + SecCoreData->PeiTemporaryRamSize); + + PEI_DEBUG_CODE ( + { + PrivateData->SizeOfCacheAsRam = SecCoreData->PeiTemporaryRamSize + SecCoreData->StackSize; + PrivateData->MaxTopOfCarHeap = (VOID*)((UINTN)PrivateData->BottomOfCarHeap + PrivateData->SizeOfCacheAsRam); + } + ) + + PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap; + + PeiCoreBuildHobHandoffInfoTable ( + BOOT_WITH_FULL_CONFIGURATION, + (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap, + (UINTN) SecCoreData->PeiTemporaryRamSize + ); + } + + return; +} + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob; + EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob; + UINT64 PeiStackSize; + UINT64 EfiFreeMemorySize; + EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + +//*** AMI PORTING BEGIN ***// + if (PrivateData->PeiMemoryInstalled) { + //This function should be called once. Report error if this is the second call + PEI_ERROR_CODE(PeiServices, PEI_MEMORY_INSTALLED_TWICE, EFI_ERROR_MINOR); + }else { + //Debug message + PEI_TRACE((TRACE_PEICORE, PeiServices, "Memory Installed: Address=%lX; Length=%lX\n",MemoryBegin,MemoryLength)); + } +//*** AMI PORTING END *****// + + PrivateData->SwitchStackSignal = TRUE; + PrivateData->PeiMemoryInstalled = TRUE; + + PrivateData->StackBase = MemoryBegin; + + PeiStackSize = RShiftU64 (MemoryLength, 1); + if (PEI_STACK_SIZE > PeiStackSize) { + PrivateData->StackSize = PeiStackSize; + } else { + PrivateData->StackSize = PEI_STACK_SIZE; + } + + OldHandOffHob = PrivateData->HobList.HandoffInformationTable; + + PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize)); + NewHandOffHob = PrivateData->HobList.HandoffInformationTable; + PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob; + + EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob; + + PeiCoreCopyMem ( + NewHandOffHob, + OldHandOffHob, + (UINTN)EfiFreeMemorySize + ); + + NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength; + NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop; + NewHandOffHob->EfiMemoryBottom = MemoryBegin; + + NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize; + + NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob + + (OldHandOffHob->EfiEndOfHobList - + PhysicalAddressOfOldHob); + + ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob); + + PeiBuildHobStack ((EFI_PEI_SERVICES**)PeiServices, PrivateData->StackBase, PrivateData->StackSize); + +//*** AMI PORTING BEGIN ***// +//Update LoadedImage pointers +PrivateData->LoadedImage = (EFI_PEI_PPI_DESCRIPTOR*) + ( (UINTN)PrivateData->LoadedImage + ((UINTN)NewHandOffHob - (UINTN)OldHandOffHob) ); +//*** AMI PORTING END *****// + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob)); + PEI_DEBUG ((PeiServices, EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob)); + } + ) + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + EFI_STATUS Status; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Check if Hob already available + // + if (!PrivateData->PeiMemoryInstalled) { + return EFI_NOT_AVAILABLE_YET; + } + + Hob.Raw = PrivateData->HobList.Raw; + + // + // Check to see if on 4k boundary + // + Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF; + + // + // If not aligned, make the allocation aligned. + // + if (Offset != 0) { + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset; + } + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < + Hob.HandoffInformationTable->EfiFreeMemoryBottom) { + PEI_DEBUG_CODE ( + { + PEI_DEBUG ((PeiServices, EFI_D_ERROR, "PeiAllocatePages fail: Pages - 0x%08x\n", Pages)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop)); + PEI_DEBUG ((PeiServices, EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom)); + } + ) + return EFI_OUT_OF_RESOURCES; + } else { + // + // Update the PHIT to reflect the memory usage + // + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + + // + // Update the value for the caller + // + *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop; + + // + // Create a memory allocation HOB. + // + Status = PeiBuildHobMemoryAllocation ( + (EFI_PEI_SERVICES**)PeiServices, + Hob.HandoffInformationTable->EfiFreeMemoryTop, + Pages * EFI_PAGE_SIZE + Offset, + NULL, + MemoryType + ); + + return Status; + } +} + + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_POOL *Hob; + + + Status = PeiCreateHob ( + PeiServices, + EFI_HOB_TYPE_PEI_MEMORY_POOL, + (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size), + &Hob + ); + *Buffer = Hob+1; + + + return Status; +} + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + EfiCommonLibCopyMem (Destination, Source, Length); +} + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +{ + EfiCommonLibSetMem (Buffer, Size, Value); +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/PeiCore.h b/Core/CORE_PEI/CORE_PEI_PI/PeiCore.h new file mode 100644 index 0000000..2913deb --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/PeiCore.h @@ -0,0 +1,1416 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. 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. + +Module Name: + + PeiCore.h + +Abstract: + + Definition of Pei Core Structures and Services + +Revision History + +--*/ + +#ifndef _PEICORE_H_ +#define _PEICORE_H_ + +#include "EfiImage.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiApi.h" +#include "PeiHob.h" +#include "PeiDebug.h" +#include "EfiFirmwareFileSystem.h" +#include "EfiFirmwareVolumeHeader.h" +#ifdef EFI64 +#include "SalApi.h" +#endif + +#include "EfiCommonLib.h" +#include EFI_GUID_DEFINITION (FirmwareFileSystem2) +#include EFI_GUID_DEFINITION (PeiApriori) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include EFI_PPI_DEFINITION (Reset) +#include EFI_PPI_DEFINITION (DxeIpl) +#include EFI_PPI_DEFINITION (StatusCode) +#include EFI_PPI_DEFINITION (Security2) +#include EFI_PPI_DEFINITION (Decompress) +#include EFI_PPI_DEFINITION (FirmwareVolumeInfo) +#include EFI_PPI_DEFINITION (LoadFile2) +#include EFI_PPI_DEFINITION (FirmwareVolume) +#include EFI_PPI_DEFINITION (GuidedSectionExtraction) + + +#ifdef EFI_NT_EMULATOR +#include EFI_PPI_DEFINITION (NtPeiLoadFile) +#endif + +//*** AMI PORTING BEGIN ***// +#include <PPI/LoadedImagePpi.h> +//*** AMI PORTING END *****// + +// +//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range +// +#define EFI_PEI_CORE_PRIVATE_GUID \ + {0xd641a0f5, 0xcb7c, 0x4846, 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9} + +#define PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE 0xff + +// +// Pei Core private data structures +// +typedef union { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + + +#define PEI_STACK_SIZE 0x20000 +#define MAX_PPI_DESCRIPTORS 128 + +typedef struct { + INTN PpiListEnd; + INTN NotifyListEnd; + INTN DispatchListEnd; + INTN LastDispatchedInstall; + INTN LastDispatchedNotify; + PEI_PPI_LIST_POINTERS PpiListPtrs[MAX_PPI_DESCRIPTORS]; +} PEI_PPI_DATABASE; + + +#define PEI_CORE_MAX_FV_SUPPORTED 8 +#define PEI_CORE_MAX_PEIM_PER_FV 64 + +// +// PEI_CORE_FV_HANDE.PeimState +// Do not change these values as there is code doing math to change states. +// Look for Private->Fv[FvCount].PeimState[PeimCount]++; +// +#define PEIM_STATE_NOT_DISPATCHED 0x00 +#define PEIM_STATE_DISPATCHED 0x01 +#define PEIM_STATE_REGISITER_FOR_SHADOW 0x02 +#define PEIM_STATE_DONE 0x03 + +typedef struct { + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT8 PeimState[PEI_CORE_MAX_PEIM_PER_FV]; + EFI_PEI_FILE_HANDLE FvFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + BOOLEAN ScanFv; +} PEI_CORE_FV_HANDLE; + +// +// Pei Core private data structure instance +// +#define PEI_CORE_HANDLE_SIGNATURE EFI_SIGNATURE_32('P','e','i','C') + +typedef struct{ + UINTN Signature; + EFI_PEI_SERVICES *PS; + PEI_PPI_DATABASE PpiData; + UINTN FvCount; + PEI_CORE_FV_HANDLE Fv[PEI_CORE_MAX_FV_SUPPORTED]; + EFI_PEI_FILE_HANDLE CurrentFvFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + UINTN AprioriCount; + UINTN CurrentPeimFvCount; + UINTN CurrentPeimCount; + EFI_PEI_FILE_HANDLE CurrentFileHandle; + BOOLEAN PeimNeedingDispatch; + BOOLEAN PeimDispatchOnThisPass; + BOOLEAN PeimDispatcherReenter; + UINTN AllFvCount; + EFI_PEI_FV_HANDLE AllFv[PEI_CORE_MAX_FV_SUPPORTED]; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + EFI_PHYSICAL_ADDRESS StackBase; + UINT64 StackSize; + VOID *BottomOfCarHeap; + VOID *TopOfCarHeap; + VOID *CpuIo; + EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; + UINTN SizeOfCacheAsRam; + VOID *MaxTopOfCarHeap; + EFI_PEI_PPI_DESCRIPTOR *XipLoadFile; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeCoffLoader; + EFI_PEI_PE_COFF_LOADER_READ_FILE ImageReadFile; +//*** AMI PORTING BEGIN ***// + EFI_PEI_PPI_DESCRIPTOR *LoadedImage; + EFI_PEI_LOADED_IMAGE_PPI LoadedImagePpi; +//*** AMI PORTING END *****// +} PEI_CORE_INSTANCE; + + +// +// Pei Core Instance Data Macros +// + +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + (PEI_CR(a, PEI_CORE_INSTANCE, PS, PEI_CORE_HANDLE_SIGNATURE)) + + +typedef +EFI_STATUS +(EFIAPI *PEI_CORE_ENTRY_POINT) ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, + IN PEI_CORE_INSTANCE *OldCoreData + ); + + +VOID +SwitchCoreStacks ( + IN VOID *EntryPoint, + IN UINTN Parameter1, + IN UINTN Parameter2, + IN UINTN Parameter3, + IN VOID *NewStack + ) +/*++ + +Routine Description: + + Routine for PEI switching stacks. + +Arguments: + + EntryPoint - Entry point with new stack. + Parameter1 - First parameter for entry point. + Parameter2 - Second parameter for entry point. + NewStack - Pointer to new stack. + +Returns: + + None + +--*/ +; +extern EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList; + + +typedef +VOID +(EFIAPI *SWITCH_STACK_ENTRY_POINT) ( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ); + + + +// +// Main PEI entry +// +EFI_STATUS +EFIAPI +PeiMain ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + PpList - Pointer to Ppi list provided by SEC phase. + +Returns: + + This function never returns + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + PpList - Pointer to Ppi list provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + +--*/ +; + + +// +// Dispatcher support functions +// + +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +; + + +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + Private - Pointer to the private data passed in from caller + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +; + + +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + SecCoreData - Information and services provided by SEC phase. + + +Returns: + + None + +--*/ +; + + +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + + Private - Pointer to the private data passed in from caller. + FileHandle - File handle of PEIM. + PeimCount - The PEIM sequence in one FV. + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +; + +#ifdef EFI64 + // + // In Ipf we should make special changes for the PHIT pointers to support + // recovery boot in cache mode. + // +#define SWITCH_TO_CACHE_MODE(CoreData) SwitchToCacheMode(CoreData) +#define CACHE_MODE_ADDRESS_MASK 0x7FFFFFFFFFFFFFFFULL +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData +) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +; + +#else + +#define SWITCH_TO_CACHE_MODE(CoreData) + +#endif + +// +// PPI support functions +// +VOID +InitializePpiServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +; + +VOID +ConvertPpiPointers ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Migrate the Hob list from the CAR stack to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR * PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR * OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR * NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID * Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor OPTIONAL, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +; + + +VOID * +PeiReturnPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid + ); + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR * NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +; + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ +; + +VOID +DispatchNotify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ +; + +// +// Boot mode support functions +// +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +; + +// +// Security support functions +// +VOID +InitializeSecurityServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +; + +EFI_STATUS +VerifyFv ( + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Provide a callout to the OEM FV verification service. + +Arguments: + + VolumeHandle - Pointer to the FV under investigation. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + + +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +; + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +; + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +; + + +// +// FFS Fw Volume support functions +// + +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +/*++ + +Routine Description: + + Search the next FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + Instance - The Fv Volume Instance. + VolumeHandle - Pointer to the current Fv Volume to search. + +Returns: + EFI_INVALID_PARAMETER - VolumeHandle is NULL. + EFI_NOT_FOUND - No FV Volume is found. + EFI_SUCCESS - The next FV Volume is found. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input FvHandle, search for the next matching type file in the FV Volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only file of this type. + FvHandle - Pointer to the current FV to search. + FileHandle - Pointer to the file matching SearchType in FwVolHeader. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FileHandle - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +// +// Memory support functions +// +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS * Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of allocation. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +; + +VOID +EFIAPI +PeiCoreCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +; + +VOID +EFIAPI +PeiCoreSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +/*++ + +Routine Description: + + Set Size bytes at Buffer address with Value + +Arguments: + + Buffer - Target of set + + Size - Amount of memory to set + + Value - Value to place in memory + +Returns: + + None + +--*/ +; + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for load image file. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +; + + +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize PeiCore Fv List. + +Arguments: + PrivateData - Pointer to PEI_CORE_INSTANCE. + SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +Returns: + NONE + +--*/ +; + + +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Process Firmware Volum Information once FvInfoPPI install. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input VolumeHandle, search for the next matching name file. + +Arguments: + + FileName - File name to search. + VolumeHandle - The current FV to search. + FileHandle - Pointer to the file matching name in VolumeHandle. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +/*++ + +Routine Description: + + Collect information of given file. + +Arguments: + FileHandle - The handle to file. + FileInfo - Pointer to the file information. + +Returns: + EFI_STATUS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + Collect information of given Fv Volume. + +Arguments: + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + This routine enable a PEIM to register itself to shadow when PEI Foundation + discovery permanent memory. + +Arguments: + FileHandle - File handle of a PEIM. + +Returns: + EFI_NOT_FOUND - The file handle doesn't point to PEIM itself. + EFI_ALREADY_STARTED - Indicate that the PEIM has been registered itself. + EFI_SUCCESS - Successfully to register itself. + +--*/ +; + + +EFI_STATUS +PeiFindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Regitser PeCoffLoader to PeiCore PrivateData. And install + Pei Load File PPI. + +Arguments: + + PrivateData - Pointer to PEI_CORE_INSTANCE. + OldCoreData - Pointer to PEI_CORE_INSTANCE. + +Returns: + + NONE. + +--*/ +; + +//*** AMI PORTING BEGIN ***// +//This function is used to update LoadedImage PPI information +//LoadedImage PPI is defined in PI 1.0 specification +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +); + +#include <AmiPeiLib.h> +//*** AMI PORTING END *****// +#endif diff --git a/Core/CORE_PEI/CORE_PEI_PI/PeiMain.c b/Core/CORE_PEI/CORE_PEI_PI/PeiMain.c new file mode 100644 index 0000000..31c5db1 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/PeiMain.c @@ -0,0 +1,404 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + PeiMain.c + +Abstract: + + Pei Core Main Entry Point + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include EFI_PPI_DEFINITION (MemoryDiscovered) +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +#include EFI_GUID_DEFINITION (StatusCode) + +// +// CAR is filled with this initial value during SEC phase +// +#define INIT_CAR_VALUE 0x5AA55AA5 + +#ifdef EFI_PEI_PERFORMANCE + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ); + +#endif + +//*** AMI PORTING BEGIN ***// +VOID InitParts(VOID* p1, VOID*p2); +VOID InitPartsMem(VOID* p1, VOID*p2); +VOID ProcessLoadHob(EFI_PEI_SERVICES **PeiServices); +VOID AmiInitParts(IN EFI_PEI_SERVICES **PeiServices, VOID* InitFunction); +//*** AMI PORTING END *****// + +// +// PPI that represents memory being discoverd in PEI. +// +static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiMemoryDiscoveredPpiGuid, + NULL +}; + +static EFI_PEI_SERVICES mPS = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFfsFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + PeiCoreCopyMem, + PeiCoreSetMem, + + PeiReportStatusCode, + PeiResetSystem, + + NULL, + NULL, + + PeiFfsFindFileByName, + PeiFfsGetFileInfo, + PeiFfsGetVolumeInfo, + PeiRegisterForShadow +}; + + +// +// Main entry point to the PEI Core +// +EFI_PEI_CORE_ENTRY_POINT (PeiMain) + +EFI_STATUS +EFIAPI +PeiMain ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + SecCoreData - Information about the PEI core's operating environment. + PpList - Points to a list of one or more PPI descriptors to be + installed initially by the PEI core. + +Returns: + + This function never returns + +--*/ +{ + return PeiCore (SecCoreData,PpList, NULL); +} + +EFI_STATUS +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + SecCoreData - Information and services provided by SEC phase. + PpList - Pointer to Ppi list provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + EFI_NOT_FOUND - Never reach + +--*/ +{ + PEI_CORE_INSTANCE PrivateData; + EFI_PEI_SERVICES **PeiServices; + EFI_STATUS Status; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_PEI_PCI_CFG2_PPI *PciCfg; + +#ifdef EFI_PEI_PERFORMANCE + UINT64 mTick; + + mTick = 0; + if (OldCoreData == NULL) { + GetTimerValue (&mTick); + } +#endif + + + // + // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory() + // the 63-bit of address is set to 1. + // + SWITCH_TO_CACHE_MODE (OldCoreData); + + if (OldCoreData != NULL) { + + // + // 2nd time through we are using System Memory and we restore a previous + // state by copying the OldCoreData into PrivateData. A lot of the + // init code will note initialize PrivateData on the 2nd pass. + // + PeiCoreCopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE)); + + // + // 2nd time through Pei Core has been shadowed. To Pei Services, + // CpuIo and PciCfg services may have been updated by some Pei Modules. So before + // update PrivateData.ServiceTableShadow with memory version, save the CpuIo + // PciCfg and restore them then. + // + CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo; + PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg; + PeiCoreCopyMem (&(PrivateData.ServiceTableShadow), &mPS, sizeof (EFI_PEI_SERVICES)); + PrivateData.ServiceTableShadow.CpuIo = CpuIo; + PrivateData.ServiceTableShadow.PciCfg = PciCfg; + } else { + + // + // 1st time through we are using Temp memory + // + PeiCoreSetMem (&PrivateData, sizeof (PEI_CORE_INSTANCE),0); + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + + // + // Copy PeiServices from ROM to Temp memory in PrivateData + // + PeiCoreCopyMem (&(PrivateData.ServiceTableShadow), &mPS, sizeof (EFI_PEI_SERVICES)); + } + + PrivateData.PS = &PrivateData.ServiceTableShadow; + PeiServices = &PrivateData.PS; + + InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData); + + InitializePpiServices (&PrivateData, OldCoreData); + + // + // Save PeiServicePointer so that it can be retrieved anywhere. + // + SetPeiServicesTablePointer(PeiServices); + + if (OldCoreData != NULL) { + + PEI_PERF_END (&PrivateData.PS,L"PreMem", NULL, 0); + PEI_PERF_START (&PrivateData.PS,L"PostMem", NULL, 0); + + // + // The following code dumps out interesting cache as RAM usage information + // so we can keep tabs on how the cache as RAM is being utilized. The + // PEI_DEBUG_CODE macro is used to prevent this code from being compiled + // on a debug build. + // + PEI_DEBUG_CODE ( + { + UINTN *StackPointer; + UINTN StackValue; + + StackValue = INIT_CAR_VALUE; + for (StackPointer = (UINTN *) OldCoreData->TopOfCarHeap; + ((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam)) + && StackValue == INIT_CAR_VALUE; + StackPointer++) { + StackValue = *StackPointer; + } + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam)); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR stack ever used: %d bytes.\n", + ((UINTN) OldCoreData->MaxTopOfCarHeap - (UINTN) StackPointer) + ) + ); + PEI_DEBUG ( + ( + &PrivateData.PS, EFI_D_INFO, " CAR heap used: %d bytes.\n", + ((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom - + (UINTN) OldCoreData->HobList.Raw) + ) + ); + } + ) + +//*** AMI PORTING BEGIN ***// + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; +//*** AMI PORTING END *****// + + // + // Alert any listeners that there is permanent memory available + // + PEI_PERF_START (&PrivateData.PS,L"DisMem", NULL, 0); + Status = PeiInstallPpi (&PrivateData.PS, &mMemoryDiscoveredPpi); + PEI_PERF_END (&PrivateData.PS,L"DisMem", NULL, 0); + + } else { + + // + // Report Status Code EFI_SW_PC_INIT + // + PEI_REPORT_STATUS_CODE ( + &(PrivateData.PS), + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT, + 0, + NULL, + NULL + ); + + // + // If first pass, start performance measurement. + // + PEI_PERF_START (&PrivateData.PS,L"PreMem", NULL, mTick); + + // + // If SEC provided any PPI services to PEI, install them. + // + if (PpList != NULL) { + Status = PeiInstallPpi (&PrivateData.PS, PpList); + ASSERT_PEI_ERROR (&PrivateData.PS, Status); + } +//*** AMI PORTING BEGIN ***// +{ + static EFI_GUID gEfiPeiLoadedImagePpiGuid = EFI_PEI_LOADED_IMAGE_PPI_GUID; + static EFI_PEI_PPI_DESCRIPTOR LoadedImagePpiDesc = + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiLoadedImagePpiGuid, NULL + }; + PeiAllocatePool(&PrivateData.PS,sizeof(EFI_PEI_PPI_DESCRIPTOR),&PrivateData.LoadedImage); + *PrivateData.LoadedImage = LoadedImagePpiDesc; + PrivateData.LoadedImage->Ppi = &PrivateData.LoadedImagePpi; + PeiInstallPpi (&PrivateData.PS, PrivateData.LoadedImage); +} +//*** AMI PORTING END *****// + } + + InitializeSecurityServices (&PrivateData, OldCoreData); + + InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData); + + // + // Install Pei Load File PPI. + // + InitializeImageServices (&PrivateData, OldCoreData); + + // + // Call PEIM dispatcher + // +//*** AMI PORTING BEGIN ***// + if (OldCoreData != NULL) { + AmiInitParts(PeiServices, InitPartsMem); + ProcessLoadHob(PeiServices); + } else { + AmiInitParts(PeiServices, InitParts); + } +//*** AMI PORTING END *****// + PeiDispatcher (SecCoreData, &PrivateData); + + // + // Check if InstallPeiMemory service was called. + // +//*** AMI PORTING BEGIN ***// + //report MEMORY_NOT_INSTALLED error + if (!PrivateData.PeiMemoryInstalled) + PEI_ERROR_CODE(&PrivateData.PS, PEI_MEMORY_NOT_INSTALLED, EFI_ERROR_MAJOR); +// PEI_ASSERT(&PrivateData.PS, PrivateData.PeiMemoryInstalled == TRUE); +//*** AMI PORTING END *****// + + PEI_PERF_END (&PrivateData.PS, L"PostMem", NULL, 0); + + DxeIpl = PeiReturnPpi (&PrivateData.PS, &gEfiDxeIplPpiGuid); +//*** AMI PORTING BEGIN ***// + //report DXEIPL_NOT_FOUND error + if (DxeIpl==NULL) + PEI_ERROR_CODE(&PrivateData.PS, PEI_DXEIPL_NOT_FOUND, EFI_ERROR_MAJOR); +// PEI_ASSERT (&PrivateData.PS, DxeIpl != NULL); +//*** AMI PORTING END *****// + + PEI_DEBUG ((&PrivateData.PS, EFI_D_INFO, "DXE IPL Entry\n")); + +//*** AMI PORTING BEGIN ***// + //DxeIpl->Entry (DxeIpl, &PrivateData.PS, PrivateData.HobList); + DxeIpl->Entry (DxeIpl, &PrivateData.PS, PrivateData.HobList.Raw); +//*** AMI PORTING END *****// +//*** AMI PORTING BEGIN ***// + // If DXE IPL returned control, let's call dispatcher again + // DXE IPL might have dicovered new FV or have changed a boot mode + + // reset previous bitmap so that the dispatcher will attempt to execute any new PEIMs + // dispatch + PeiDispatcher (SecCoreData, &PrivateData); + // DXE IPL + DxeIpl->Entry (DxeIpl, &PrivateData.PS, PrivateData.HobList.Raw); +//*** AMI PORTING END *****// + PEI_ASSERT (&PrivateData.PS,FALSE); + return EFI_NOT_FOUND; + +} + +//*** AMI PORTING BEGIN ***// +VOID UpdatedLoadedImagePpi( + IN EFI_PEI_SERVICES **PeiServices, + EFI_PHYSICAL_ADDRESS ImageAddress, + UINT64 ImageSize, + EFI_PEI_FILE_HANDLE FileHandle +) +{ + PEI_CORE_INSTANCE *Private = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + Private->LoadedImagePpi.ImageAddress = ImageAddress; + Private->LoadedImagePpi.ImageSize = ImageSize; + Private->LoadedImagePpi.FileHandle = FileHandle; + PeiReInstallPpi(PeiServices,Private->LoadedImage,Private->LoadedImage); +} +//*** AMI PORTING END *****// diff --git a/Core/CORE_PEI/CORE_PEI_PI/Ppi.c b/Core/CORE_PEI/CORE_PEI_PI/Ppi.c new file mode 100644 index 0000000..01236e7 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Ppi.c @@ -0,0 +1,687 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + Ppi.c + +Abstract: + + EFI PEI Core PPI services + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +VOID +InitializePpiServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +{ + if (OldCoreData == NULL) { + PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1; + } + + return; +} + +VOID +ConvertPpiPointers ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Convert PPI pointers after the Hob list was migrated from the temporary memory + to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + None + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT8 Index; + PEI_PPI_LIST_POINTERS *PpiPointer; + UINTN Fixup; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob; + + for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) { + if (Index < PrivateData->PpiData.PpiListEnd || + Index > PrivateData->PpiData.NotifyListEnd) { + PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index]; + + if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the PEIM descriptor from the old HOB heap + // to the relocated HOB heap. + // + PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup); + + // + // Only when the PEIM descriptor is in the old HOB should it be necessary + // to try to convert the pointers in the PEIM descriptor + // + + if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the GUID in the PPI or NOTIFY descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup); + } + + // + // Assume that no code is located in the temporary memory, so the pointer to + // the notification function in the NOTIFY descriptor needs not be converted. + // + if (Index < PrivateData->PpiData.PpiListEnd && + (UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom && + (UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) { + // + // Convert the pointer to the PPI interface structure in the PPI descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup); + } + } + } + } +} + + + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN LastCallbackInstall; + + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + Index = PrivateData->PpiData.PpiListEnd; + LastCallbackInstall = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the NotifyList + // + if (Index == PrivateData->PpiData.NotifyListEnd + 1) { + return EFI_OUT_OF_RESOURCES; + } + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PrivateData->PpiData.PpiListEnd = LastCallbackInstall; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); +//*** AMI PORTING END ***// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*)PpiList; + PrivateData->PpiData.PpiListEnd++; + + // + // Continue until the end of the PPI List. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + PpiList++; + Index++; + } + + // + // Dispatch any callback level notifies for newly installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCallbackInstall, + PrivateData->PpiData.PpiListEnd, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) { + break; + } + } + if (Index == PrivateData->PpiData.PpiListEnd) { + return EFI_NOT_FOUND; + } + + // + // Remove the old PPI from the database, add the new one. + // +//*** AMI PORTING BEGIN ***// +//Disable PPI messages +// PEI_DEBUG((PeiServices, EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); +//*** AMI PORTING END ***// + PrivateData->PpiData.PpiListPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR*)NewPpi; + + // + // Dispatch any callback level notifies for the newly installed PPI. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor OPTIONAL, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + 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 (Instance == 0) { + + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + + return EFI_SUCCESS; + } + Instance--; + } + } + + return EFI_NOT_FOUND; + +} + + + +VOID * +PeiReturnPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid + ) +{ + EFI_STATUS Status; + VOID *Ppi; + + Status = PeiLocatePpi (PeiServices, Guid, 0, NULL, &Ppi); + + return (EFI_ERROR (Status)) ? NULL : Ppi; +} + + + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN NotifyIndex; + INTN LastCallbackNotify; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr; + UINTN NotifyDispatchCount; + + + NotifyDispatchCount = 0; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + Index = PrivateData->PpiData.NotifyListEnd; + LastCallbackNotify = Index; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the PpiList + // + if (Index == PrivateData->PpiData.PpiListEnd - 1) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + PrivateData->PpiData.NotifyListEnd = LastCallbackNotify; + PEI_DEBUG((PeiServices, EFI_D_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyDispatchCount ++; + } + + PrivateData->PpiData.PpiListPtrs[Index].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR*)NotifyList; + + PrivateData->PpiData.NotifyListEnd--; + PEI_DEBUG((PeiServices, EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + // + // Go the next descriptor. Remember the NotifyList moves down. + // + NotifyList++; + Index--; + } + + // + // If there is Dispatch Notify PPI installed put them on the bottom + // + if (NotifyDispatchCount > 0) { + for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) { + if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify; + + for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){ + PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify; + } + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr; + PrivateData->PpiData.DispatchListEnd--; + } + } + + LastCallbackNotify -= NotifyDispatchCount; + } + + // + // Dispatch any callback level notifies for all previously installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiListEnd, + LastCallbackNotify, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN TempValue; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previouly installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // DispatchListEnd (with NotifyPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) { + TempValue = PrivateData->PpiData.DispatchListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.LastDispatchedNotify, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedNotify = TempValue; + } + + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // PpiListEnd (with InstallPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) { + TempValue = PrivateData->PpiData.PpiListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.PpiListEnd, + MAX_PPI_DESCRIPTORS-1, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedInstall = TempValue; + } + + if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) { + break; + } + } + return; +} + +VOID +DispatchNotify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Remember that Installs moves up and Notifies moves down. + // + for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) { + NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify; + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { + PEI_DEBUG ( + ( + PeiServices, + EFI_D_INFO, + "Notify: PPI Guid: %g, Peim notify entry point: %x\n", + SearchGuid, + NotifyDescriptor->Notify + ) + ); + NotifyDescriptor->Notify ( + (EFI_PEI_SERVICES**)PeiServices, + NotifyDescriptor, + (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi + ); + } + } + } + + return; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/Reset.c b/Core/CORE_PEI/CORE_PEI_PI/Reset.c new file mode 100644 index 0000000..eb824f3 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Reset.c @@ -0,0 +1,76 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + Reset.c + +Abstract: + + Pei Core Reset System Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (Reset) +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +{ + EFI_STATUS Status; + PEI_RESET_PPI *ResetPpi; + + Status = PeiLocatePpi ( + PeiServices, + &gPeiResetPpiGuid, + 0, + NULL, + (VOID **)&ResetPpi + ); + + // + // LocatePpi returns EFI_NOT_FOUND on error + // + if (!EFI_ERROR (Status)) { + return ResetPpi->ResetSystem (PeiServices); + } +//*** AMI PORTING BEGIN ***// + //Report error + PEI_ERROR_CODE(PeiServices,PEI_RESET_NOT_AVAILABLE,EFI_ERROR_MINOR); +//*** AMI PORTING END *****// + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/Core/CORE_PEI/CORE_PEI_PI/Security.c b/Core/CORE_PEI/CORE_PEI_PI/Security.c new file mode 100644 index 0000000..8d85b86 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Security.c @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + Security.c + +Abstract: + + EFI PEI Core Security services + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include EFI_PPI_DEFINITION (Security2) + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiSecurity2PpiGuid, + SecurityPpiNotifyCallback +}; + +VOID +InitializeSecurityServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +{ + if (OldCoreData == NULL) { + PeiNotifyPpi (&PrivateData->PS, &mNotifyList); + } + return; +} + + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Provide a callback for when the security PPI is installed. + +Arguments: + + PeiServices - The PEI core services table. + NotifyDescriptor - The descriptor for the notification event. + Ppi - Pointer to the PPI in question. + +Returns: + + EFI_SUCCESS - The function is successfully processed. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Get PEI Core private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // If there isn't a security PPI installed, use the one from notification + // + if (PrivateData->PrivateSecurityPpi == NULL) { + PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY2_PPI *)Ppi; + } + return EFI_SUCCESS; +} + + +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +{ + EFI_STATUS Status; + UINT32 AuthenticationStatus; + BOOLEAN DeferExection; + + // + // Set a default authentication state + // + AuthenticationStatus = 0; + + if (PrivateData->PrivateSecurityPpi == NULL) { + Status = EFI_NOT_FOUND; + } else { + // + // Check to see if the image is OK + // + Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( + &PrivateData->PS, + PrivateData->PrivateSecurityPpi, + AuthenticationStatus, + VolumeHandle, + FileHandle, + &DeferExection + ); + if (DeferExection) { + Status = EFI_SECURITY_VIOLATION; + } + } + return Status; +} + + +EFI_STATUS +VerifyFv ( + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Verify a Firmware volume + +Arguments: + + CurrentFvAddress - Pointer to the current Firmware Volume under consideration + +Returns: + + EFI_SUCCESS - Firmware Volume is legal + EFI_SECURITY_VIOLATION - Firmware Volume fails integrity test + +--*/ +{ + // + // Right now just pass the test. Future can authenticate and/or check the + // FV-header or other metric for goodness of binary. + // + return EFI_SUCCESS; +} diff --git a/Core/CORE_PEI/CORE_PEI_PI/StatusCode.c b/Core/CORE_PEI/CORE_PEI_PI/StatusCode.c new file mode 100644 index 0000000..8df4058 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/StatusCode.c @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + StatusCode.c + +Abstract: + + Pei Core Status Code Support + +Revision History + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" + +#include EFI_PPI_DEFINITION (StatusCode) + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + CodeType - Type of Status Code. + Value - Value to output for Status Code. + Instance - Instance Number of this status code. + CallerId - ID of the caller of this status code. + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +{ + EFI_STATUS Status; + PEI_STATUS_CODE_PPI *StatusCodePpi; + + + // + //Locate StatusCode Ppi. + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiStatusCodePpiGuid, + 0, + NULL, + (VOID **)&StatusCodePpi + ); + + if (!EFI_ERROR (Status)) { + Status = StatusCodePpi->ReportStatusCode ( + PeiServices, + Type, + Value, + Instance, + CallerId, + Data + ); + return Status; + } + + + return EFI_NOT_AVAILABLE_YET; +} + + + diff --git a/Core/CORE_PEI/CORE_PEI_PI/dependency.c b/Core/CORE_PEI/CORE_PEI_PI/dependency.c new file mode 100644 index 0000000..f890a42 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/dependency.c @@ -0,0 +1,265 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + dependency.c + +Abstract: + + PEI Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria for + schedulability is that the dependency expression is satisfied. + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "EfiDependency.h" +#include "Dependency.h" + +STATIC +BOOLEAN +IsPpiInstalled ( + IN EFI_PEI_SERVICES **PeiServices, + IN EVAL_STACK_ENTRY *Stack + ) +/*++ + +Routine Description: + + This routine determines if a PPI has been installed. + The truth value of a GUID is determined by if the PPI has + been published and can be queried from the PPI database. + +Arguments: + PeiServices - The PEI core services table. + Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check + +Returns: + + True if the PPI is already installed. + False if the PPI has yet to be installed. + +--*/ +{ + VOID *PeiInstance; + EFI_STATUS Status; + EFI_GUID PpiGuid; + + // + // If there is no GUID to evaluate, just return current result on stack. + // + if (Stack->Operator == NULL) { + return Stack->Result; + } + + // + // Copy the Guid into a locale variable so that there are no + // possibilities of alignment faults for cross-compilation + // environments such as Intel?Itanium(TM). + // + PeiCoreCopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID)); + + // + // Check if the PPI is installed. + // + Status = (**PeiServices).LocatePpi( + PeiServices, + &PpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &PeiInstance // PPI + ); + + if (EFI_ERROR(Status)) { + return FALSE; + } + + return TRUE; +} + + +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +{ + EFI_STATUS Status; + DEPENDENCY_EXPRESSION_OPERAND *Iterator; + EVAL_STACK_ENTRY *StackPtr; + EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; + + Status = EFI_SUCCESS; + Iterator = DependencyExpression; + + StackPtr = &EvalStack[0]; + + while (TRUE) { + + switch (*(Iterator++)) { + + // + // For performance reason we put the frequently used items in front of + // the rarely used items + // + + case (EFI_DEP_PUSH): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return FALSE; + } + + // + // Push the pointer to the PUSH opcode operator (pointer to PPI GUID) + // We will evaluate if the PPI is insalled on the POP operation. + // + StackPtr->Operator = (VOID *) Iterator; + Iterator = Iterator + sizeof (EFI_GUID); + StackPtr++; + break; + + case (EFI_DEP_AND): + case (EFI_DEP_OR): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the two POPs for the AND operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did two POPs. + // + if (StackPtr < &EvalStack[2]) { + return FALSE; + } + + // + // Evaluate the first POPed operator only. If the operand is + // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the + // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE, + // we don't need to check the second operator, and the result will be + // evaluation of the POPed operator. Otherwise, don't POP the second + // operator since it will now evaluate to the final result on the + // next operand that causes a POP. + // + StackPtr--; + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_AND) { + if (!(IsPpiInstalled (PeiServices, StackPtr))) { + (StackPtr-1)->Result = FALSE; + (StackPtr-1)->Operator = NULL; + } + } else { + if (IsPpiInstalled (PeiServices, StackPtr)) { + (StackPtr-1)->Result = TRUE; + (StackPtr-1)->Operator = NULL; + } + } + break; + + case (EFI_DEP_END): + StackPtr--; + // + // Check to make sure EvalStack is balanced. If not, then there is + // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. + // + if (StackPtr != &EvalStack[0]) { + return FALSE; + } + return IsPpiInstalled (PeiServices, StackPtr); + break; + + case (EFI_DEP_NOT): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the POP for the NOT operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did a POP. + // + if (StackPtr < &EvalStack[1]) { + return FALSE; + } + (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); + (StackPtr-1)->Operator = NULL; + break; + + case (EFI_DEP_TRUE): + case (EFI_DEP_FALSE): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return FALSE; + } + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_TRUE) { + StackPtr->Result = TRUE; + } else { + StackPtr->Result = FALSE; + } + StackPtr->Operator = NULL; + StackPtr++; + break; + + default: + // + // The grammar should never arrive here + // + return FALSE; + break; + } + } +} diff --git a/Core/CORE_PEI/CORE_PEI_PI/dependency.h b/Core/CORE_PEI/CORE_PEI_PI/dependency.h new file mode 100644 index 0000000..413c068 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/dependency.h @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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. + +Module Name: + + dependency.h + +Abstract: + + This module contains data specific to dependency expressions + and local function prototypes. + +--*/ + +#ifndef _PEI_DEPENDENCY_H_ +#define _PEI_DEPENDENCY_H_ + +#define MAX_GRAMMAR_SIZE 256 + +// +// type definitions +// +typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND; + +typedef struct { + BOOLEAN Result; + VOID *Operator; +} EVAL_STACK_ENTRY; + +#endif diff --git a/Core/CORE_PEI/CpuIo.c b/Core/CORE_PEI/CpuIo.c new file mode 100644 index 0000000..634f676 --- /dev/null +++ b/Core/CORE_PEI/CpuIo.c @@ -0,0 +1,1158 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//***************************************************************************** +// $Header: /Alaska/SOURCE/Core/EDK/PeiMain/CpuIo.c 13 3/22/11 5:14p Felixp $ +// +// $Revision: 13 $ +// +// $Date: 3/22/11 5:14p $ +//***************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/EDK/PeiMain/CpuIo.c $ +// +// 13 3/22/11 5:14p Felixp +// Method of invocation of the in-memory entry point has changed +// from LOAD_HOB to eLink registered under PeiCoreMemoryInstalled. +// This is more efficient. +// +// 12 2/05/11 3:43p Artems +// Changed functions calling interface (added CONST qualifiers) as +// required by PI 1.0 specification +// +// 11 11/05/09 4:59p Oleksiyy +// EIP 27821 Support for 64 bit operations in IoRead and IoWrite added. To +// use this functions IA32CLib.c, x64AsmLib.asm files should be updated +// also. +// +// 10 7/08/09 5:53p Vyacheslava +// Updated according to the coding standards. +// +// 9 6/16/05 10:56a Felixp +// 1. Once memory is available, PEI Core PEIMs that created PEIM_LOAD_HOB +// are reallocated to memory. +// 2. ImagePei.c removed +// 3. FileLoader moved from DxeIpl to PEI Core +// +// 8 6/10/05 5:49p Felixp +// Bug fixes in MemRead, MemWrite, IoRead, IoWrite +// +// 7 6/06/05 7:48p Felixp +// +// 6 6/06/05 1:25p Felixp +// +// 5 6/03/05 3:45p Felixp +// Updated to support changes introduced in PEI CIS 0.91 +// +// 4 3/04/05 9:38a Mandal +// +// 3 2/01/05 2:35a Felixp +// +// 2 1/18/05 3:21p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 7 1/27/04 3:58a Felixp +// Bug fixes and improvements as a part of PEI CORE integration +// +// 6 12/29/03 5:25p Felixp +// preffix 'EFI_' added to the names of the PEIM descriptor structures and +// flags +// +// 5 12/15/03 4:35p Robert +// +// 4 12/15/03 4:25p Robert +// +// 3 12/15/03 12:40p Robert +// changed position of GUID definition below PPI include +// +// 2 12/15/03 11:49a Robert +// updated PPI definitions and removed entry point definitions +// +// 1 12/11/03 5:34p Robert +// Initial Check In +// +//***************************************************************************** +//<AMI_FHDR_START> +// +// Name: CpuIo.c +// +// Description: This file contains the implementation of the CPU I/O +// specification. For questions about the specification refer to the +// PEI CIS specification chapter 9 +// +//<AMI_FHDR_END> +//***************************************************************************** + +// Module specific Includes +#include <AmiPeiLib.h> +#include <AmiHobs.h> +// Produced PPIs +#include <PPI/CpuIo.h> + +// Function Prototypes +static EFI_STATUS LocalMemRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +static EFI_STATUS LocalMemWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +static EFI_STATUS LocalIoRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +static EFI_STATUS LocalIoWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +static UINT8 LocalIoRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static UINT16 LocalIoRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static UINT32 LocalIoRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static UINT64 LocalIoRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static VOID LocalIoWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data +); + +static VOID LocalIoWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data +); + +static VOID LocalIoWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data +); + +static VOID LocalIoWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data +); + +static UINT8 MemRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static UINT16 MemRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static UINT32 MemRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static UINT64 MemRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +); + +static VOID MemWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data +); + +static VOID MemWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data +); + +static VOID MemWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data +); + +static VOID MemWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data +); + +// PPI interface definition +static EFI_PEI_CPU_IO_PPI mCpuIoPpi = { + {LocalMemRead, LocalMemWrite}, + {LocalIoRead, LocalIoWrite}, + LocalIoRead8, LocalIoRead16, LocalIoRead32, LocalIoRead64, + LocalIoWrite8, LocalIoWrite16, LocalIoWrite32, LocalIoWrite64, + MemRead8, MemRead16, MemRead32, MemRead64, + MemWrite8, MemWrite16, MemWrite32, MemWrite64 +}; + +// PPI that are installed +static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiCpuIoPpiInServiceTableGuid, + NULL + } +}; + +// Function Definitions +EFI_STATUS EFIAPI CpuIoMemInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + // Update the CpuIo pointer + (*PeiServices)->CpuIo = &mCpuIoPpi; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: CpuIoInit +// +// Description: This function installs the CPU I/O PPI and exits +// +// Input: +// *FfsHeader - pointer to the header of the current firmware file system +// **PeiServices - pointer to the Pei Services function and data structure +// +// Output: always returns EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +EFI_STATUS EFIAPI CpuIoInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_STATUS Status; + + // Install the CpuIo Ppi + (*PeiServices)->CpuIo = &mCpuIoPpi; + Status = (*PeiServices)->InstallPpi( PeiServices, mPpiList ); + + return Status; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: CalcAddrChanges +// +// Description: This function determines which addresses need to be changed +// as data is read or written. +// +// Input: +// Width - Contains the width and type of memory or I/O read that is needed +// +// Output: +// *In - The number of bytes to increment the input buffer address after +// every read or write access +// *Out - The number of bytes to increment the output buffer address after +// every read or write access +// +//============================================================================ +//<AMI_PHDR_END> + +VOID CalcAddrChanges( + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + OUT UINTN *In, + OUT UINTN *Out +) +{ + // get the number of bytes per read or write access and the turn that into + // an Hex Address Incrementing value + *In = *Out = 1 << (Width % 4); + + if ( (Width >= EfiPeiCpuIoWidthFifoUint8) && + (Width <= EfiPeiCpuIoWidthFifoUint64) ) + *Out = 0; + + else if ( (Width >= EfiPeiCpuIoWidthFillUint8) && + (Width <= EfiPeiCpuIoWidthFillUint64) ) + *In = 0; +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoRead8 +// +// Description: This function is called to read a byte from the I/O space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT8 - This is the value read from the I/O space specified by the +// value passed in by the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT8 LocalIoRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return IoRead8 ((UINT16) Address); +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoRead16 +// +// Description: This function is called to read a word from the I/O space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT16 - This is the value read from the I/O space specified by the +// by the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT16 LocalIoRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return IoRead16 ((UINT16) Address); +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoRead32 +// +// Description: This function is called to read a dword from the I/O space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT32 - This is the value read from the I/O space specified by the +// value passed in by the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT32 LocalIoRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return IoRead32 ((UINT16) Address); +} + + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoRead64 +// +// Description: This function is called to read a qword from the I/O space +// This function is not available in a 32bit system so we just return 0 if +// it is called. We cannot remove this function because it is part of the +// specification +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT64 - This is the value read from the I/O space specified by the +// value passed in by the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> +static UINT64 LocalIoRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return IoRead64 ((UINT16) Address); +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoWrite8 +// +// Description: This function is called to write a byte to the I/O space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer8 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID LocalIoWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Buffer8 +) +{ + IoWrite8 ((UINT16) Address, Buffer8); +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocaIoWrite16 +// +// Description: This function is called to write a word to the I/O space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer16 - The value to be written to location specified by Address +// +// Output: VOID +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID LocalIoWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Buffer16 +) +{ + IoWrite16 ((UINT16) Address, Buffer16); +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocaIoWrite32 +// +// Description: This function is called to write a dword to the I/O space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer32 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID LocalIoWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Buffer32 +) +{ + IoWrite32 ((UINT16) Address, Buffer32); +} + + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocaIoWrite64 +// +// Description: This function is called to write a qword to the I/O space +// This function is not available in a 32bit system so we just do nothing +// if it is called. We cannot remove this function because it is part of +// the specification +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer64 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID LocalIoWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Buffer64 +) +{ + IoWrite64 ((UINT16) Address, Buffer64); +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemRead8 +// +// Description: This function is called to read a byte from the Memory space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT8 - This is the value read from the Memory space specified by +// the input variable Address +// +// Referrals: +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT8 MemRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return *(volatile UINT8*) Address; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemRead16 +// +// Description: This function is called to read a word from the Memory space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT16 - This is the value read from the Memory space specified +// by the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT16 MemRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return *(volatile UINT16*) Address; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemRead32 +// +// Description: This function is called to read a dword from the Memory space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT32 - This is the value read from the Memory space specified by +// the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT32 MemRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return *(volatile UINT32*) Address; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemRead64 +// +// Description: This function is called to read a qword from the Memory space +// This function is not available in a 32bit system so we just return 0 if +// it is called. We cannot remove this function because it is part of the +// specification +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be read from +// +// Output: UINT64 - This is the value read from the Memory space specified by +// the input variable Address +// +//============================================================================ +//<AMI_PHDR_END> + +static UINT64 MemRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address +) +{ + return *(volatile UINT64*) Address; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemWrite8 +// +// Description: This function is called to write a byte to the Memory space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer8 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID MemWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Buffer8 +) +{ + *(volatile UINT8*) Address = Buffer8; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemWrite16 +// +// Description: This function is called to write a word to the Memory space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer16 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID MemWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Buffer16 +) +{ + *(volatile UINT16*) Address = Buffer16; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemWrite32 +// +// Description: This function is called to write a dword to the Memory space +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer32 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID MemWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Buffer32 +) +{ + *(volatile UINT32*) Address = Buffer32; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: MemWrite64 +// +// Description: This function is called to write a qword to the Memory space +// This function is not available in a 32bit system so we just do nothing +// if it is called. We cannot remove this function because it is part of +// the specification +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Address - A 64 bit address that points to the location to be written to +// Buffer64 - The value to be written to location specified by Address +// +// Output: None +// +//============================================================================ +//<AMI_PHDR_END> + +static VOID MemWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Buffer +) +{ + *(volatile UINT64*) Address = Buffer; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalMemWrite +// +// Description: This function is called to do multiple writes to the memory +// space. It also is capable of doing a memory space fill of a single value +// or a serial write from a buffer depending on the Width type being passed +// in. +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Width - Size of the I/O space that is to be written +// Address - A 64 bit address that points to the location to be read from +// Count - Number of times to write +// *Buffer - Data to be written to the I/O space +// +// Output: always returns EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +static EFI_STATUS LocalMemWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +) +{ + UINTN Idx; + UINTN OutputInc, InputInc; // Input and Output counters + + CalcAddrChanges( + Width, + &InputInc, + &OutputInc + ); + + for ( Idx = 0; Idx < Count; Idx++, Address += OutputInc, Buffer = (UINT8*)Buffer + InputInc ) { + + switch (Width) { + case EfiPeiCpuIoWidthUint8: + case EfiPeiCpuIoWidthFifoUint8: + case EfiPeiCpuIoWidthFillUint8: + MemWrite8( + PeiServices, + This, + Address, + *(UINT8*)Buffer + ); + break; + + case EfiPeiCpuIoWidthUint16: + case EfiPeiCpuIoWidthFifoUint16: + case EfiPeiCpuIoWidthFillUint16: + MemWrite16( + PeiServices, + This, + Address, + *(UINT16*)Buffer + ); + break; + + case EfiPeiCpuIoWidthUint32: + case EfiPeiCpuIoWidthFifoUint32: + case EfiPeiCpuIoWidthFillUint32: + MemWrite32( + PeiServices, + This, + Address, + *(UINT32*)Buffer + ); + break; + + case EfiPeiCpuIoWidthUint64: + case EfiPeiCpuIoWidthFifoUint64: + case EfiPeiCpuIoWidthFillUint64: + MemWrite64( + PeiServices, + This, + Address, + *(UINT64*)Buffer + ); + break; + } + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalMemRead +// +// Description: This function is called to do multiple reads from the Memory +// space. It also is capable of doing an read of an I/O space area to a +// single byte or a serial read into a buffer depending on the Width type +// being passed in. +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Width - Size of the Memory space that is to be read each time +// Address - A 64 bit address that points to the location to be read from +// Count - Number of times to read +// +// Output: always returns EFI_SUCCESS +// *Buffer - Data to be read from the Memory space +// +//============================================================================ +//<AMI_PHDR_END> + +static EFI_STATUS LocalMemRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST struct _EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +) +{ + UINTN Idx; + UINTN OutputInc, InputInc; // Input and Output counters + + CalcAddrChanges( + Width, + &InputInc, + &OutputInc + ); + + for ( Idx = 0; Idx < Count; Idx++, Address += OutputInc, Buffer = (UINT8*)Buffer + InputInc ) { + + switch (Width) { + case EfiPeiCpuIoWidthUint8: + case EfiPeiCpuIoWidthFifoUint8: + case EfiPeiCpuIoWidthFillUint8: + *(UINT8*)Buffer = MemRead8( + PeiServices, + This, + Address + ); + break; + + case EfiPeiCpuIoWidthUint16: + case EfiPeiCpuIoWidthFifoUint16: + case EfiPeiCpuIoWidthFillUint16: + *(UINT16*)Buffer = MemRead16( + PeiServices, + This, + Address + ); + break; + + case EfiPeiCpuIoWidthUint32: + case EfiPeiCpuIoWidthFifoUint32: + case EfiPeiCpuIoWidthFillUint32: + *(UINT32*)Buffer = MemRead32( + PeiServices, + This, + Address + ); + break; + + case EfiPeiCpuIoWidthUint64: + case EfiPeiCpuIoWidthFifoUint64: + case EfiPeiCpuIoWidthFillUint64: + *(UINT64*)Buffer = MemRead64( + PeiServices, + This, + Address + ); + break; + } + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoRead +// +// Description: This function is called to do multiple reads from the I/O space +// It also is capable of doing an read of an I/O space area to a single byte +// or a serial read into a buffer depending on the Width type being passed in. +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Width - Size of the I/O space that is to be read +// Address - A 64 bit address that points to the location to be read from +// Count - Number of times to read +// +// Output: always returns EFI_SUCCESS +// *Buffer - Data to be read from the I/O space +// +//============================================================================ +//<AMI_PHDR_END> + +static EFI_STATUS LocalIoRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer ) +{ + UINTN Idx; + UINTN OutputInc, InputInc; // Input and Output counters + + CalcAddrChanges( + Width, + &InputInc, + &OutputInc + ); + + for ( Idx = 0; Idx < Count; Idx++, Address += OutputInc, Buffer = (UINT8*)Buffer + InputInc ) { + + switch (Width) { + case EfiPeiCpuIoWidthUint8: + case EfiPeiCpuIoWidthFifoUint8: + case EfiPeiCpuIoWidthFillUint8: + *(UINT8*)Buffer = LocalIoRead8( + PeiServices, + This, + Address + ); + break; + + case EfiPeiCpuIoWidthUint16: + case EfiPeiCpuIoWidthFifoUint16: + case EfiPeiCpuIoWidthFillUint16: + *(UINT16*)Buffer = LocalIoRead16( + PeiServices, + This, + Address + ); + break; + + case EfiPeiCpuIoWidthUint32: + case EfiPeiCpuIoWidthFifoUint32: + case EfiPeiCpuIoWidthFillUint32: + *(UINT32*)Buffer = LocalIoRead32( + PeiServices, + This, + Address + ); + break; + + case EfiPeiCpuIoWidthUint64: + case EfiPeiCpuIoWidthFifoUint64: + case EfiPeiCpuIoWidthFillUint64: + *(UINT64*)Buffer = LocalIoRead64( + PeiServices, + This, + Address + ); + break; + } + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: LocalIoWrite +// +// Description: This function is called to do multiple writes to the I/O space +// It also is capable of doing an I/O space fill of a single value or a +// serial write from a buffer depending on the Width type being passed in. +// +// Input: +// **PeiServices - pointer to the Pei Services function and data structure +// *This - Pointer to the instance of the CPU I/O PPI structure +// Width - Size of the I/O space that is to be written +// Address - A 64 bit address that points to the location to be read from +// Count - Number of times to write +// *Buffer - Data to be written to the I/O space +// +// Output: always returns EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +static EFI_STATUS LocalIoWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer ) +{ + UINTN Idx; + UINTN OutputInc, InputInc; // Input and Output counters + + CalcAddrChanges( + Width, + &InputInc, + &OutputInc + ); + + for ( Idx = 0; Idx < Count; Idx++, Address += OutputInc, Buffer = (UINT8*)Buffer + InputInc ) { + switch (Width) { + case EfiPeiCpuIoWidthUint8: + case EfiPeiCpuIoWidthFifoUint8: + case EfiPeiCpuIoWidthFillUint8: + LocalIoWrite8( + PeiServices, + This, + Address, + *(UINT8*)Buffer + ); + break; + + case EfiPeiCpuIoWidthUint16: + case EfiPeiCpuIoWidthFifoUint16: + case EfiPeiCpuIoWidthFillUint16: + LocalIoWrite16( + PeiServices, + This, + Address, + *(UINT16*)Buffer + ); + break; + + case EfiPeiCpuIoWidthUint32: + case EfiPeiCpuIoWidthFifoUint32: + case EfiPeiCpuIoWidthFillUint32: + LocalIoWrite32( + PeiServices, + This, + Address, + *(UINT32*)Buffer + ); + break; + + case EfiPeiCpuIoWidthUint64: + case EfiPeiCpuIoWidthFifoUint64: + case EfiPeiCpuIoWidthFillUint64: + LocalIoWrite64( + PeiServices, + This, + Address, + *(UINT64*)Buffer + ); + break; + } + } + + return EFI_SUCCESS; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + diff --git a/Core/CORE_PEI/DxeIpl.c b/Core/CORE_PEI/DxeIpl.c new file mode 100644 index 0000000..8a1a129 --- /dev/null +++ b/Core/CORE_PEI/DxeIpl.c @@ -0,0 +1,838 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/Core/CORE_PEI/DxeIpl.c 4 10/25/12 8:50a Wesleychen $ +// +// $Revision: 4 $ +// +// $Date: 10/25/12 8:50a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_PEI/DxeIpl.c $ +// +// 4 10/25/12 8:50a Wesleychen +// - Update Core to 4.6.5.4. +// - Fixed system hang at CKP 0x4F during S3 resume if HT is disabled. +// +// 45 5/21/12 10:42a Artems +// [TAG] EIP87678 +// [Category] Improvement +// [Description] Select ROM image to use on BOOT_ON_FLASH_UPDATE path +// We have two images - one already in flash (old) and one in reflash +// capsule +// We can use either one to boot +// [Files] DxeIpl.c +// +// 44 4/20/12 2:23p Artems +// [TAG] EIP87678 +// [Category] New Feature +// [Description] Select image to boot from on flash update boot path - +// either old one (currently in flash) or new one (in recovery capsule) +// [Files] Recovery.c DxeIpl.c Core.sdl Tokens.c +// +// 43 11/01/11 1:57p Felixp +// [TAG] EIP 69841 and 71719 +// [Category] Improvement +// [Description] The AMI customizations are removed from the DXE memory +// manager. +// They are replaced with the Memory Type Information HOB used in Tiano +// projects. +// This is done to reduces number of descriptors in the memory map +// and to workaround Windows bug (Windows can't handle memory allocations +// that happen after the start of the OS loader). +// [Files] CORE_DXE.sdl, Page.c, BDS.c, DxeIpl.c +// +// 42 7/19/11 11:29a Oleksiyy +// [TAG] EIP64108 +// [Category] Improvement +// [Description] ACPI, convert or update all eModules to be compliant +// with PI 1.2, and UEFI 2.3.1 specifications. +// [Files] AcpiCore.c, mptable.c, AcpiS3Save.c, S3Resume.dxs, +// S3Resume.c, AcpiPeiS3Func.c, BootScriptExecuter.c and DxeIpl.c +// +// 41 6/02/11 4:49p Artems +// +// 40 5/13/11 5:12p Artems +// Preserved boot mode when recovery/flash update failed for error +// reporting +// +// 39 5/05/11 3:44p Artems +// Bugfix: different FV count for PI 0.9 and PI 1.0 specification +// +// 38 2/15/11 12:35p Artems +// Added workaround so in recovery DXE_CORE ffs will be picked from right +// FV +// +// 37 2/05/11 3:48p Artems +// Added new ROM layout infrastructure support +// Replaced call to FFS PPI with library function to work both in PI 0.91 +// and 1.0 modes +// +// 36 10/01/10 4:33p Felixp +// Debug message with DXE Core addres is moved to after the instalaltion +// of the END of PEI PPI +// +// 35 11/13/09 4:32p Felixp +// Buffer overflow protection is added (calls to Sprintf replaced with +// Sprintf_s). +// +// 34 7/10/09 4:32p Artems +// Added function headers +// +// 33 5/21/09 5:19p Felixp +// RomLayout support. Call to ReportFvDxeIpl is added. +// +// 32 5/07/08 12:23p Felixp +// Converted to use new Performance API +// +// 31 4/18/08 6:27p Felixp +// DXE_CORE_STARTED reported at the very end of PEI phase +// +// 30 4/20/07 5:10p Felixp +// Status codes added +// +// 29 4/19/07 1:03p Felixp +// +// 27 4/17/07 9:07a Felixp +// S3 & Recovery Status Codes removed. They are reported by the S3 & +// Recovery PEIM +// +// 26 3/13/07 1:46a Felixp +// Error reporting updated to use new PEI_ERROR_CODE macro +// +// 25 3/12/07 10:26a Felixp +// LoadedImage PPI support added (defined in PI 1.0; used by AmiDebugger) +// +// 23 11/02/06 10:25p Felixp +// Install EFI_PEI_END_OF_PEI_PHASE_PPI_GUID right before launching DXE +// Core +// +// 22 8/25/06 10:58a Felixp +// +// 21 8/24/06 9:43a Felixp +// Preliminary x64 support (work in progress) +// DXE Core interfaces are no longer passed from PEI Core. +// They are linked directly with DXE Core +// +// 20 6/04/06 10:50p Ambikas +// +// 19 5/22/06 12:14a Felixp +// More status/error codes added +// +// 18 3/13/06 9:51a Felixp +// +// 17 12/01/05 9:52a Felixp +// Recovery Logic changed: RecoveryModule PPI is used. Capsule processing +// is moved to Recovery.c +// +// 16 10/09/05 11:25a Felixp +// Performance measurements added. +// +// 15 6/16/05 10:56a Felixp +// 1. Once memory is available, PEI Core PEIMs that created PEIM_LOAD_HOB +// are reallocated to memory. +// 2. ImagePei.c removed +// 3. FileLoader moved from DxeIpl to PEI Core +// +// 14 6/06/05 1:25p Felixp +// Type parameter removed from AllocatePages to match PEI CIS 0.91 +// +// 13 3/25/05 5:47p Felixp +// 1. S3 boot path: call of S3RestoreConfig added +// 3. Recovery boot path: trace messages added +// +// 12 3/24/05 6:48p Felixp +// +// 11 3/22/05 10:03p Felixp +// Recovery Support +// +// 10 3/17/05 1:54p Felixp +// implementation of S3Resume boot path started +// +// 9 3/17/05 1:45p Felixp +// Bug fix in memory installed callback (status was not checked) +// +// 8 3/04/05 9:39a Mandal +// +// 7 1/25/05 3:37p Felixp +// +// 6 1/25/05 3:26p Felixp +// Once memory is available DxeIpl realocates itself to memory and +// installs +// LoadFile PPI +// +// 5 1/22/05 12:29p Felixp +// Bug fix: +// Last parameter to AllocatePages was VOID* instead of +// EFI_PHYSICAL_ADDRESS, which +// resulted in a stack corruption. +// +// 4 1/22/05 11:29a Felixp +// +// 2 1/18/05 3:21p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 19 12/20/04 5:10p Felixp +// +// 18 12/20/04 4:54p Felixp +// +// 17 12/17/04 6:59p Felixp +// PEI_DEBUG_MSG renamed to PEI_TRACE +// +// 16 11/24/04 9:38a Felixp +// format of debug message changed +// +// 15 11/19/04 1:23a Felixp +// +// 14 11/10/04 5:18p Felixp +// Debug message added +// +// 13 10/21/04 2:47p Felixp +// Support for DXE Core compression added +// +// 12 7/13/04 10:42a Felixp +// +// 11 4/11/04 2:49p Felixp +// +// 10 4/07/04 12:46a Felixp +// REAL PLATFORM DEBUGGING (lots of bug fixes) +// +// 9 3/29/04 6:06p Felixp +// +// 8 3/29/04 5:40p Felixp +// +// 7 3/28/04 2:11p Felixp +// 1. PE Loader and some other commonly used code moved to the Library +// 2. Warnings fixed (from now on warning will be treated as error) +// +// 6 3/20/04 12:03p Felixp +// +// 5 2/19/04 10:08a Felixp +// Debugging code removed. +// +// 4 2/11/04 12:29a Felixp +// +// 3 2/10/04 4:02p Felixp +// +// 2 2/04/04 2:04a Felixp +// work in progress... +// +// 1 1/28/04 3:23a Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: DxeIpl.c +// +// Description: DXE Core Loader +// +//<AMI_FHDR_END> +//********************************************************************** + +//----------------------------------------------------------------------------- + +#include <PEI.h> +#include <HOB.h> +#include <AmiHobs.h> +#include <AmiPeiLib.h> +#include <PPI/RecoveryModule.h> +#include <PPI/S3Resume2.h> +#include <PPI/S3Resume.h> +#include <PPI/LoadedImagePpi.h> +#include <Guid/MemoryTypeInformation.h> +#include <token.h> +#include <AmiHobs.h> +#include "Core/CPU/CPU.h" +#include "Core/CPU/CpuCspLib.h" + +#define SMM_ASM_FIXUP_SMM_BASE 0x38002 +#define SMM_ASM_FIXUP_IED_ZERO_MEM 0x38029 +#define SMM_ASM_BASE_CHANGE_FLAG 0x3808f +#define APIC_SMI (2 << 8) +#define APIC_LEVEL_ASSERT (1 << 14) +#define APIC_NO_SHORT_HAND (0 << 18) + +//----------------------------------------------------------------------------- + +//****************************************************************************/ +// TYPE DECLARATIONS +//****************************************************************************/ +typedef VOID (EFIAPI *DXE_ENTRY_POINT)( + IN VOID *HobStart +); + +//****************************************************************************/ +// FUNCTION DECLARATIONS +//****************************************************************************/ +EFI_STATUS EFIAPI Entry( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *HobList +); + +#ifdef x64_BUILD_SUPPORT +VOID InitLongMode( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Function, + IN VOID *Parameter1 +); +#endif + +//****************************************************************************/ +// VARIABLE DECLARATIONS +//****************************************************************************/ +// PPIs +EFI_DXE_IPL_PPI DxeIplPpi = { Entry }; +EFI_GUID guidDxeIpl = EFI_DXE_IPL_PPI_GUID; +EFI_GUID guidEndOfPei = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID; + +// PPI to be installed +static EFI_PEI_PPI_DESCRIPTOR PpiList[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &guidDxeIpl, &DxeIplPpi + } +}; + +static EFI_PEI_PPI_DESCRIPTOR EndOfPpiList[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &guidEndOfPei, NULL + } +}; + +EFI_PEI_LOADED_IMAGE_PPI LoadedImagePpi; +EFI_GUID guidLoadedImage = EFI_PEI_LOADED_IMAGE_PPI_GUID; +static EFI_PEI_PPI_DESCRIPTOR LoadedImagePpiDesc[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &guidLoadedImage, &LoadedImagePpi + } +}; + +// The order of elements in this array is important. +// It defines the order of memory types in the DXE memory map. +// The first array element corresponds to the type with the largest address. +// Keeping boot time memory types at the bottom of the list improves +// stability of the runtime portions of the memory map +// which is important during S4 resume. +CONST EFI_MEMORY_TYPE_INFORMATION DefaultMemoryTypeInformation[] = { + { EfiRuntimeServicesCode, 0x30 }, + { EfiRuntimeServicesData, 0x20 }, + { EfiACPIMemoryNVS, 0x60 }, + { EfiACPIReclaimMemory, 0x10 }, + { EfiReservedMemoryType, 0x30 }, + { EfiBootServicesCode, 0x600 }, + { EfiBootServicesData, 0x1500 }, + { EfiMaxMemoryType, 0 } // indicates the end of the table +}; + +//****************************************************************************/ +// IMPLEMENTATION +//****************************************************************************/ + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: LoadDxeCore +// +// Description: +// Loads DXE core file into memory +// +// Input: +// IN EFI_PEI_SERVICES **ppPS - pointer to PEI services structure +// IN EFI_FIRMWARE_VOLUME_HEADER *pFV - pointer to firmware volume header +// OUT EFI_FFS_FILE_HEADER **ppFile - pointer to returned FFS file header +// OUT EFI_PHYSICAL_ADDRESS *pAddress - pointer to returned address where file loaded +// OUT UINT64 *pSize - pointer to returned file size +// OUT EFI_PHYSICAL_ADDRESS *pEntry - pointer to returned address of entry point +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - DXE core loaded successfully +// EFI_ERROR - DXE core file not found or cannot be loaded +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS LoadDxeCore( + IN EFI_PEI_SERVICES **ppPS, + IN EFI_FIRMWARE_VOLUME_HEADER *pFV, + OUT EFI_FFS_FILE_HEADER **ppFile, + OUT EFI_PHYSICAL_ADDRESS *pAddress, + OUT UINT64 *pSize, + OUT EFI_PHYSICAL_ADDRESS *pEntry +) +{ + EFI_STATUS Status; + *ppFile = NULL; + // loop via all files + while(TRUE) + { + Status = (*ppPS)->FfsFindNextFile(ppPS, EFI_FV_FILETYPE_DXE_CORE, pFV, ppFile); + if( EFI_ERROR(Status) ) return Status; + Status = PeiLoadFile(ppPS,*ppFile,pAddress,pSize,pEntry); + if( !EFI_ERROR(Status) ) return Status; + } +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: S3Resume +// +// Description: +// Implementation of S3 wake boot path +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services structure +// +// Output: +// EFI_STATUS +// EFI_ERROR - S3 resume boot path is failed or cannot be found +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS S3Resume( + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_PEI_S3_RESUME2_PPI *pS32; + EFI_PEI_S3_RESUME_PPI *pS3; + EFI_PEI_PPI_DESCRIPTOR *pDummy; + EFI_STATUS Status; + PEI_TRACE((TRACE_DXEIPL, PeiServices, "S3Resume\n")); + Status = (*PeiServices)->LocatePpi(PeiServices,&gEfiPeiS3Resume2PpiGuid,0,&pDummy,&pS32); + if (EFI_ERROR(Status)) + { + Status = (*PeiServices)->LocatePpi(PeiServices,&gPeiS3ResumePpiGuid,0,&pDummy,&pS3); + if (EFI_ERROR(Status)) + { + PEI_ERROR_CODE(PeiServices,PEI_S3_RESUME_PPI_NOT_FOUND,EFI_ERROR_MAJOR); + return Status; + } + PEI_TRACE((TRACE_DXEIPL, PeiServices, "Calling S3RestoreConfig\n")); + return pS3->S3RestoreConfig(PeiServices); + } + PEI_TRACE((TRACE_DXEIPL, PeiServices, "Calling S3RestoreConfig2\n")); + return pS32->S3RestoreConfig2(pS32); +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: Recovery +// +// Description: +// Implementation of recovery boot path +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services structure +// +// Output: +// EFI_STATUS +// EFI_ERROR - recovery capsule not found +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS Recovery( + IN EFI_PEI_SERVICES **PeiServices +) +{ + static EFI_GUID guidRecoveryModule = EFI_PEI_RECOVERY_MODULE_PPI_GUID; + EFI_PEI_RECOVERY_MODULE_PPI *pRecovery; + EFI_PEI_PPI_DESCRIPTOR *pDummy; + EFI_STATUS Status = (*PeiServices)->LocatePpi(PeiServices,&guidRecoveryModule,0,&pDummy,&pRecovery); + if (EFI_ERROR(Status)){ + PEI_ERROR_CODE(PeiServices,PEI_RECOVERY_PPI_NOT_FOUND,EFI_ERROR_MAJOR); + return Status; + } + return pRecovery->LoadRecoveryCapsule(PeiServices,pRecovery); +} + +//defined in ReportFv2.c +EFI_STATUS ReportFV2Dxe( + IN VOID* RecoveryCapsule OPTIONAL, + IN EFI_PEI_SERVICES **PeiServices +); + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: FindRecoveryBuffer +// +// Description: +// Searches for recovery capsule address in HOB +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services structure +// OUT VOID **Buffer - pointer where to store found address +// +// Output: +// EFI_STATUS +// EFI_ERROR - recovery capsule not found +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FindRecoveryBuffer( + IN EFI_PEI_SERVICES **PeiServices, + OUT VOID **Buffer +) +{ + EFI_STATUS Status; + RECOVERY_IMAGE_HOB *RecoveryHob; + static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID; + + Status = (*PeiServices)->GetHobList(PeiServices, &RecoveryHob); + if(EFI_ERROR(Status)) + return Status; //we are not on recovery boot path + + Status = FindNextHobByGuid(&RecoveryHobGuid, &RecoveryHob); + if(EFI_ERROR(Status)) + return Status; //we are not on recovery boot path + + if(RecoveryHob->Status == EFI_SUCCESS && RecoveryHob->Address != NULL) { + *Buffer = (VOID *)(UINTN)RecoveryHob->Address; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +extern const BOOLEAN UseNewImage; + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: PublishDxeFv +// +// Description: +// Publishes Firmware volumes required for DXE phase +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services structure +// IN EFI_BOOT_MODE BootMode - current boot mode +// +// Output: +// UINTN - Number of next firmware volume to start search for DXE_CORE from +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINTN PublishDxeFv( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode +) +{ + EFI_STATUS Status; + UINTN FvNum = 0; + VOID *RecoveryBuffer = NULL; + EFI_FIRMWARE_VOLUME_HEADER* pFV; + +/* first check for recovery/flashupdate capsule +BOOT_IN_RECOVERY_MODE - actual recovery or flash update via recovery capsule on disk (in latter case +boot mode will be changed to BOOT_ON_FLASH_UPDATE after call to Recovery() function) +BOOT_ON_FLASH_UPDATE - flash update via recovery capsule in memory +*/ + if (BootMode == BOOT_IN_RECOVERY_MODE || BootMode == BOOT_ON_FLASH_UPDATE) { + Status = Recovery(PeiServices); + if (!EFI_ERROR(Status)) { + Status = FindRecoveryBuffer(PeiServices, &RecoveryBuffer); + (*PeiServices)->GetBootMode(PeiServices, &BootMode); //check if boot mode changed + } + + if(EFI_ERROR(Status)) { + /* we can't find recovery capsule, report error */ + PEI_ERROR_CODE(PeiServices, PEI_RECOVERY_FAILED, EFI_ERROR_MAJOR); + } + } + + if(RecoveryBuffer != NULL) { + if(BootMode == BOOT_IN_RECOVERY_MODE || UseNewImage) { +#if PI_SPECIFICATION_VERSION >= 0x00010000 + /* when we're in recovery we publish DXE Fv from recovery buffer, instead of flash */ + while( !EFI_ERROR((*PeiServices)->FfsFindNextVolume(PeiServices, FvNum, &pFV))) + FvNum++; //determine how many FVs published already +#endif + Status = ReportFV2Dxe(RecoveryBuffer, PeiServices); + if(!EFI_ERROR(Status)) { + return FvNum; + } else { + /* we can't publish recovery capsule, report error */ + PEI_ERROR_CODE(PeiServices, PEI_RECOVERY_FAILED, EFI_ERROR_MAJOR); + } + } + } + + Status = ReportFV2Dxe(NULL, PeiServices); + return 0; +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: Entry +// +// Description: +// Implementation of EFI_DXE_IPL_PPI Entry function +// +// Input: +// IN EFI_DXE_IPL_PPI *This - pointer to PPI instance +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services structure +// IN EFI_HOB_HANDOFF_INFO_TABLE *HobList - pointer to HOB list +// +// Output: +// EFI_STATUS +// EFI_ERROR - Boot failed +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS EFIAPI Entry( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *HobList +) +{ + EFI_FIRMWARE_VOLUME_HEADER* pFV; + UINTN FvNum; + EFI_PHYSICAL_ADDRESS DxeCoreAddress, DxeCoreEntry; + UINT64 DxeCoreSize; + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* pFile; + EFI_BOOT_MODE BootMode=(EFI_BOOT_MODE)-1; //set it to invalid value + EFI_PEI_LOADED_IMAGE_PPI *OldLoadedImagePpi; + EFI_PEI_PPI_DESCRIPTOR *OldLoadedImageDesc; +#ifdef EFI_DEBUG + CHAR8 sName[0x100]; +#endif + EFI_MEMORY_TYPE_INFORMATION MemoryInformationBuffer[EfiMaxMemoryType + 1]; + EFI_MEMORY_TYPE_INFORMATION *MemoryInformationPtr = NULL; + UINTN MemoryInformationSize; + EFI_HOB_GUID_TYPE *MemoryInformationHob; + + PEI_PERF_START(PeiServices,DXEIPL_TOK, NULL,0); + PEI_PROGRESS_CODE(PeiServices,PEI_DXE_IPL_STARTED); + + (*PeiServices)->GetBootMode(PeiServices, &BootMode); + if (BootMode == BOOT_ON_S3_RESUME) { +#ifndef AMI_CPU_S3_PEI_SUPPORT +#define AMI_CPU_S3_PEI_SUPPORT 0 +#endif +#if AMI_CPU_S3_PEI_SUPPORT == 0 + { + VOID *FirstHob; + SMM_HOB *SmmHob; + EFI_GUID gSmmHobGuid = SMM_HOB_GUID; + VOID *SaveBuffer; + UINT8 ApicId; + UINT8 i,j; + + (*PeiServices)->GetHobList(PeiServices, &FirstHob); + SmmHob = (SMM_HOB*)FirstHob; + while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &SmmHob))) + { + if (guidcmp(&SmmHob->EfiHobGuidType.Name, &gSmmHobGuid) == 0) + break; + } + if (!EFI_ERROR(Status)) + { + //Allocate memory for temporarly perserve the 3000:8000 data. + Status = (*PeiServices)->AllocatePool( + PeiServices, + SmmGetBaseSaveBufferSize(), + &SaveBuffer + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + SmmSetupDefaultHandler(SaveBuffer, SmmHob); + + for (i = 0, j = 0; i < SmmHob->NumCpus; ++i) + { + *(UINT32*)SMM_ASM_FIXUP_SMM_BASE = (UINT32)SmmHob->SmmBase[i]; + *(UINT8*)SMM_ASM_BASE_CHANGE_FLAG = 0; //Initialize Flag + + ApicId = j; + MemReadWrite32((UINT32*)(LOCAL_APIC_BASE + APIC_ICR_HIGH_REGISTER), ApicId << 24, 0x00ffffff); + MemReadWrite32((UINT32*)(LOCAL_APIC_BASE + APIC_ICR_LOW_REGISTER), APIC_NO_SHORT_HAND + APIC_LEVEL_ASSERT + APIC_SMI, 0); + + while (!(*(volatile UINT8*)SMM_ASM_BASE_CHANGE_FLAG)) + { + CPULib_Pause(); //Wait on Flag + } + ++*(UINT16*)SMM_ASM_FIXUP_IED_ZERO_MEM; //Only 0, for first thread to clear IED memory. + + if (IsHtEnabled()) + { + j++; + } + else + { + j += 2; + } + } + + SmmRemoveDefaultHandler(SaveBuffer); + } + } +#endif + PEI_PERF_END(PeiServices, DXEIPL_TOK, NULL, 0); + S3Resume(PeiServices); + //if S3 Resume failed, report error and reset system + PEI_ERROR_CODE(PeiServices, PEI_S3_RESUME_FAILED, EFI_ERROR_MAJOR); + (*PeiServices)->ResetSystem(PeiServices); + } else { + FvNum = PublishDxeFv(PeiServices, BootMode); + } + + while( !EFI_ERROR ((*PeiServices)->FfsFindNextVolume (PeiServices, FvNum++, &pFV) ) + && EFI_ERROR(Status=LoadDxeCore(PeiServices,pFV,&pFile,&DxeCoreAddress,&DxeCoreSize,&DxeCoreEntry)) + ); + if (EFI_ERROR(Status)) + { + PEI_ERROR_CODE(PeiServices,PEI_DXE_CORE_NOT_FOUND,EFI_ERROR_MAJOR); + PEI_PERF_END(PeiServices,DXEIPL_TOK, NULL,0); + return Status; + } + //Create module allocation HOB for DXE Core + CreateHobMemoryAllocationModule( + PeiServices, DxeCoreAddress, DxeCoreSize, + EfiBootServicesCode, &pFile->Name, + DxeCoreEntry + ); + + // Create a MemoryTypeInformation HOB (used by DXE memory manager) + + // There can only be a single memory type information HOB. + // Invalidate other HOB instances (if any). + Status = (*PeiServices)->GetHobList(PeiServices, &MemoryInformationHob); + ASSERT_PEI_ERROR(PeiServices, Status); + while (!EFI_ERROR( + FindNextHobByGuid(&gEfiMemoryTypeInformationGuid, &MemoryInformationHob) + )) MemoryInformationHob->Header.HobType = EFI_HOB_TYPE_UNUSED; + + MemoryInformationSize = sizeof(MemoryInformationBuffer); + + // In case of S4 resume, use memory type information + // from the last full boot (S5 resume). + // This preserves the memory map across sessions. + Status = PeiGetVariable ( + PeiServices, + (BootMode == BOOT_ON_S4_RESUME) + ? L"PreviousMemoryTypeInformation" + : EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, + &gEfiMemoryTypeInformationGuid, + NULL, &MemoryInformationSize, MemoryInformationBuffer + ); + if (EFI_ERROR(Status)){ + MemoryInformationPtr = (EFI_MEMORY_TYPE_INFORMATION*)DefaultMemoryTypeInformation; + MemoryInformationSize = sizeof(DefaultMemoryTypeInformation); + }else{ + MemoryInformationPtr=MemoryInformationBuffer; + } + Status = (*PeiServices)->CreateHob ( + PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(EFI_HOB_GUID_TYPE) + MemoryInformationSize, + &MemoryInformationHob + ); + if (!EFI_ERROR(Status)) { + MemoryInformationHob->Name = gEfiMemoryTypeInformationGuid; + MemCpy( MemoryInformationHob+1, MemoryInformationPtr, MemoryInformationSize); + } + + + //Update LoadedImage PPI information + LoadedImagePpi.ImageAddress = DxeCoreAddress; + LoadedImagePpi.ImageSize = DxeCoreSize; + LoadedImagePpi.FileHandle = pFile; + Status = (*PeiServices)->LocatePpi ( + PeiServices, &guidLoadedImage, + 0, &OldLoadedImageDesc, &OldLoadedImagePpi + ); + if (!(EFI_ERROR(Status))) { // if Loaded Image PPI was located + Status = (*PeiServices)->ReInstallPpi ( + PeiServices, OldLoadedImageDesc, LoadedImagePpiDesc + ); + } else { + // Loaded Image PPI not found, try installing it again. + Status = (*PeiServices)->InstallPpi( + PeiServices,LoadedImagePpiDesc + ); + } + PEI_PERF_END(PeiServices,DXEIPL_TOK, NULL,0); + (*PeiServices)->InstallPpi(PeiServices,EndOfPpiList); +#ifdef EFI_DEBUG + if (!GetName((VOID*)DxeCoreAddress,sName)) Sprintf_s(sName,sizeof(sName),"DXE-Core"); + PeiTrace(TRACE_DXEIPL, PeiServices, "%s.Entry(%X)\n", sName, DxeCoreEntry); +#endif + PEI_PROGRESS_CODE(PeiServices,DXE_CORE_STARTED); +#ifdef x64_BUILD_SUPPORT + InitLongMode( + PeiServices, (VOID*)(UINTN)DxeCoreEntry, HobList + ); +#else + ((DXE_ENTRY_POINT )DxeCoreEntry)(HobList); +#endif + return EFI_NOT_FOUND; +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Name: PeiInitDxeIpl +// +// Description: +// DXE loader entry point +// +// Input: +// IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to FFS file header +// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services structure +// +// Output: +// EFI_STATUS +// EFI_SUCCESS - EFI_DXE_IPL_PPI installed successfully +// EFI_ERROR - error occured during execution +// +// Notes: +//----------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS PeiInitDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + return (*PeiServices)->InstallPpi(PeiServices,PpiList); +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_PEI/PciCfg.c b/Core/CORE_PEI/PciCfg.c new file mode 100644 index 0000000..c831953 --- /dev/null +++ b/Core/CORE_PEI/PciCfg.c @@ -0,0 +1,491 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//***************************************************************************** +// $Header: /Alaska/SOURCE/Core/EDK/PeiMain/PciCfg.c 12 8/12/11 12:24p Artems $ +// +// $Revision: 12 $ +// +// $Date: 8/12/11 12:24p $ +//***************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/EDK/PeiMain/PciCfg.c $ +// +// 12 8/12/11 12:24p Artems +// EIP 64107: Added changes for module to be compliant with PI +// specification v 1.2 +// +// 11 3/22/11 5:15p Felixp +// Method of invocation of the in-memory entry point has changed +// from LOAD_HOB to eLink registered under PeiCoreMemoryInstalled. +// This is more efficient. +// +// 10 2/05/11 3:44p Artems +// Changed functions calling interfaces to meet PI 1.0 specification +// requirements +// +// 9 11/05/09 5:01p Oleksiyy +// EIP 27821 Support for 64 bit operations in PciRead and PciWrite added. +// To use this functions CpuIo.c, IA32CLib.c, x64AsmLib.asm files should +// be updated also. +// +// 8 7/08/09 5:53p Vyacheslava +// Updated according to the coding standards. +// +// 7 6/16/05 10:56a Felixp +// 1. Once memory is available, PEI Core PEIMs that created PEIM_LOAD_HOB +// are reallocated to memory. +// 2. ImagePei.c removed +// 3. FileLoader moved from DxeIpl to PEI Core +// +// 6 6/06/05 7:49p Felixp +// +// 5 6/06/05 1:25p Felixp +// +// 4 6/03/05 3:45p Felixp +// Updated to support changes introduced in PEI CIS 0.91 +// +// 3 3/04/05 9:43a Mandal +// +// 2 1/18/05 3:21p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 8 1/28/04 3:24a Felixp +// +// 7 1/27/04 3:58a Felixp +// Bug fixes and improvements as a part of PEI CORE integration +// +// 6 12/29/03 5:25p Felixp +// preffix 'EFI_' added to the names of the PEIM descriptor structures and +// flags +// +// 5 12/15/03 4:35p Robert +// +// 4 12/15/03 4:25p Robert +// +// 3 12/15/03 12:41p Robert +// changed position of GUID definition below PPI include +// +// 2 12/15/03 11:54a Robert +// Updated the definitions of PPI includes and removed the entry point +// definitions +// +// 1 12/11/03 5:34p Robert +// Initial Check in +// +//***************************************************************************** +//<AMI_FHDR_START> +// +// Name: PciCfg.c +// +// Description: This file contains the implementation of the PCI Cfg I/O +// specification. For questions about the specification refer to the +// PEI CIS specification chapter 9 +// +//<AMI_FHDR_END> +//***************************************************************************** + +// Module specific Includes +#include <AmiPeiLib.h> +// PPI Produced +#include <PPI/PciCfg2.h> + +// Module specific macros +// Make a PCI Access address out of the value that is passed in. Clear the lowest 2 bits +// PCI accesses are always 4 byte aligned +#define GET_PCI_ADDRESS(x) \ +(0x080000000 | (((UINTN)x & 0x0FF000000) >> 8) | (((UINTN)x & 0x0FF0000)>> 5) | (x & 0x0700) | (x & 0x0FC)) + +// Function Prototypes +EFI_STATUS PciRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +); + +EFI_STATUS PciWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +); + +EFI_STATUS PciModify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, +#if PI_SPECIFICATION_VERSION<0x00010000 + IN UINTN SetBits, + IN UINTN ClearBits +#else + IN VOID *SetBits, + IN VOID *ClearBits +#endif +); + + +// Local Definitions +EFI_PEI_PCI_CFG2_PPI mPciCfgPpi = { + PciRead, + PciWrite, + PciModify +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPciCfg2PpiGuid, + &mPciCfgPpi + } +}; + +// Function Definitions + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: PciCfgMemInit +// +// Description: This function installs the PCI Configuration PPI and exits +// +// Input: +// *FfsHeader - pointer to the header of the current firmware file system +// **PeiServices - pointer to the Pei Services function and data structure +// +// Output: EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +EFI_STATUS EFIAPI PciCfgMemInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + // update PCI Config pointer + (*PeiServices)->PciCfg = &mPciCfgPpi; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: PciCfgInit +// +// Description: This function installs the PCI Configuration PPI and exits +// +// Input: +// *FfsHeader - pointer to the header of the current firmware file system +// **PeiServices - pointer to the Pei Services function and data structure +// +// Output: EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +EFI_STATUS EFIAPI PciCfgInit ( + IN EFI_PEI_FILE_HANDLE FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_STATUS Status; + + // Install the PCI Config Ppi + (*PeiServices)->PciCfg = &mPciCfgPpi; + Status = (*PeiServices)->InstallPpi( PeiServices, mPpiList ); + return Status; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: PciRead +// +// Description: This function Reads a value from the PCI Config space and +// returns that value in Buffer. +// +// Input: +// **PeiServices - Pointer to the PEI Core data Structure +// *This - Pointer to the instance of the PCI Config PPI +// Width - Size of the data to be read from the configuration space +// Address - PCI address of the register to be read(Bus/Dev/Func/Reg) +// *Buffer - The data read from the requested PCI Configuration register +// +// Output: EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +EFI_STATUS PciRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +) +{ + UINT64 IoAddr; + UINT32 PciAddr; + EFI_PEI_CPU_IO_PPI *CpuIo = (*PeiServices)->CpuIo; + EFI_PEI_PCI_CFG_PPI_WIDTH TmpWidth; + UINT8 *Buffer8=(UINT8*)Buffer; + + if (((Width & 3) == EfiPeiPciCfgWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiPeiPciCfgWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + // Make a usable PCI address out of the Address passed in + PciAddr = (UINT32)GET_PCI_ADDRESS(Address); + + // Access 0xCF8 and use corrected address to enable the read to PCI + IoAddr = 0x0CF8; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + + // Access 0xCFC to get the data requested. Increment IoAddr to + // read the correct register from the PCI Config space + IoAddr = 0x0CFC + (Address & 0x03); + + TmpWidth=Width; + + if ((Width & 3) > EfiPeiPciCfgWidthUint32)TmpWidth=Width-1; + // Read the register requested. Use the passed in Width value to + // indicate the number of bytes to read. If Width = 8 bytes - split into two reads + CpuIo->Io.Read( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)Buffer8 + ); + // no formatting should be needed on the output data. Read the correct + // register and the correct width should format the data properly + + if (Width == TmpWidth) return EFI_SUCCESS; + + IoAddr = 0x0CF8; + PciAddr = PciAddr + 4; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + // Read the next 4 bytes + IoAddr = 0x0CFC; + CpuIo->Io.Read( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)(Buffer8+4) + ); + + + + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: PciWrite +// +// Description: This function writes a value to the PCI Config space +// +// Input: +// **PeiServices - Pointer to the PEI Core data Structure +// *This - Pointer to the instance of the PCI Config PPI +// Width - Size of the data to write to the configuration space +// Address - PCI address of the register to write to (Bus/Dev/Func/Reg) +// *Buffer - The data to write to the requested PCI Configuration register +// +// Output: EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +EFI_STATUS PciWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +) +{ + UINT64 IoAddr; + UINT32 PciAddr; + EFI_PEI_CPU_IO_PPI *CpuIo = (*PeiServices)->CpuIo; + EFI_PEI_PCI_CFG_PPI_WIDTH TmpWidth; + UINT8 *Buffer8=(UINT8*)Buffer; + if (((Width & 3) == EfiPeiPciCfgWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiPeiPciCfgWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + // Make a usable PCI address out of the Address passed in + PciAddr = (UINT32)GET_PCI_ADDRESS(Address); + + // Access 0xCF8 and use corrected address to enable the read to PCI + IoAddr = 0x0CF8; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + + // Access 0xCFC to get the data requested. Increment IoAddr to + // read the correct register from the PCI Config space + IoAddr = 0x0CFC + (Address & 0x03); + + TmpWidth=Width; + + if ((Width & 3) > EfiPeiPciCfgWidthUint32) TmpWidth = Width - 1; + // Write the register requested. Use the passed in Width value to + // indicate the number of bytes to read. If Width = 8 bytes - split into two writes + CpuIo->Io.Write( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)Buffer8 + ); + + + if (Width == TmpWidth) return EFI_SUCCESS; + + // Access 0xCF8 and use next 4 bytes address to enable the read to PCI + IoAddr = 0x0CF8; + PciAddr = PciAddr + 4; + CpuIo->Io.Write( + PeiServices, + CpuIo, + EfiPeiCpuIoWidthUint32, + IoAddr, + 1, + (VOID*)(&PciAddr) + ); + + // Write the next 4 bytes + IoAddr = 0x0CFC; + CpuIo->Io.Write( + PeiServices, + CpuIo, + TmpWidth, + IoAddr, + 1, + (VOID*)(Buffer8+4) + ); + + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//============================================================================ +// Procedure: PciModify +// +// Description: This function modifies a value in the PCI Config space. +// This function uses the SetBits and ClearBits values to modify the +// register. First the ClearBits value is used to clear the unwanted bits +// then the SetBits value is used to set the wanted bits. +// +// Input: +// **PeiServices - Pointer to the PEI Core data Structure +// *This - Pointer to the instance of the PCI Config PPI +// Width - Size of the data to write to the configuration space +// Address - PCI address of the register to write to (Bus/Dev/Func/Reg) +// SetBits - The bits in the register that need to be set +// ClearBits - The bits in the register that should be cleared +// +// Output: EFI_SUCCESS +// +//============================================================================ +//<AMI_PHDR_END> + +EFI_STATUS PciModify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, +#if PI_SPECIFICATION_VERSION<0x00010000 + IN UINTN SetBits, + IN UINTN ClearBits +#else + IN VOID *SetBits, + IN VOID *ClearBits +#endif +) +{ + EFI_STATUS Status; + UINTN Data; + if (((Width & 3) == EfiPeiPciCfgWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiPeiPciCfgWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + Status = PciRead ( + PeiServices, + This, + Width, + Address, + &Data + ); +#if PI_SPECIFICATION_VERSION<0x00010000 + Data = SetBits | (Data & (~ClearBits)); +#else + Data = *(UINTN*)SetBits | (Data & (~*(UINTN*)ClearBits)); +#endif + Status = PciWrite ( + PeiServices, + This, + Width, + Address, + &Data + ); + + return Status; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Core/CORE_PEI/PeiPerf.c b/Core/CORE_PEI/PeiPerf.c new file mode 100644 index 0000000..4922163 --- /dev/null +++ b/Core/CORE_PEI/PeiPerf.c @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + Perf.c + +Abstract: + + Support for performance primitives. + +--*/ +#include <AmiLib.h> + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ) +{ + *TimerValue = GetCpuTimer(); + return EFI_SUCCESS; +} |