diff options
Diffstat (limited to 'EDK/Foundation/Library/Pei')
50 files changed, 11603 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/Pei/Hob/PeiHobLib.c b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.c new file mode 100644 index 0000000..15421df --- /dev/null +++ b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.c @@ -0,0 +1,721 @@ + +/*++ + +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. + +MemoryAllocationModule Name: + + Peihoblib.c + +Abstract: + + PEI Library Functions + +--*/ + +#include "Tiano.h" +#include "PeiHob.h" +#include "peihoblib.h" +#include "peilib.h" +#include EFI_GUID_DEFINITION(MemoryAllocationHob) + + +EFI_PEI_HOB_POINTERS +BuildHobEndOfHobList ( + IN VOID *HobStart + ) +/*++ + +Routine Description: + + Builds an end of HOB list HOB + +Arguments: + + HobStart - The HOB to build + +Returns: + + A pointer to the next HOB + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = HobStart; + + Hob.Header->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + Hob.Header->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + + Hob.Header++; + return Hob; +} + +EFI_STATUS +BuildHobHandoffInfoTable ( + IN VOID *HobStart, + IN UINT16 Version, + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS EfiMemoryTop, + IN EFI_PHYSICAL_ADDRESS EfiMemoryBottom, + IN EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop, + IN EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom + ) +/*++ + +Routine Description: + + Builds a HandoffInformationTable Information Table HOB + +Arguments: + + HobStart - Start pointer of hob list + Version - The version number pertaining to the PHIT HOB definition. + BootMode - The system boot mode as determined during the HOB producer phase. + EfiMemoryTop - The highest address location of memory that is allocated for use by the HOB + producer phase. + EfiMemoryBottom - The lowest address location of memory that is allocated for use by the HOB + producer phase. + EfiFreeMemoryTop - The highest address location of free memory that is currently available for use + by the HOB producer phase. + EfiFreeMemoryBottom - The lowest address location of free memory that is available for + use by the HOB producer phase. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_PEI_HOB_POINTERS HandOffHob; + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HobEnd; + + + HandOffHob.Raw = HobStart; + Hob.Raw = HobStart; + Hob.Header->HobType = EFI_HOB_TYPE_HANDOFF; + Hob.Header->HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + + Hob.HandoffInformationTable->Version = Version; + Hob.HandoffInformationTable->BootMode = BootMode; + + Hob.HandoffInformationTable->EfiMemoryTop = EfiMemoryTop; + Hob.HandoffInformationTable->EfiMemoryBottom = EfiMemoryBottom; + Hob.HandoffInformationTable->EfiFreeMemoryTop = EfiFreeMemoryTop; + Hob.HandoffInformationTable->EfiFreeMemoryBottom = EfiFreeMemoryBottom; + + HobEnd.Raw = (VOID*)(Hob.HandoffInformationTable + 1); + Hob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd.Raw; + Hob = BuildHobEndOfHobList (HobEnd.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + + + +EFI_STATUS +BuildHobModule ( + IN VOID *HobStart, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +/*++ + +Routine Description: + + Builds a HOB for a loaded PE32 module + +Arguments: + + HobStart - Start pointer of hob list + + ModuleName - The GUID File Name of the HON from the Firmware Volume + + MemoryAllocationModule - The 64 bit physical address of the module + + ModuleLength - The length of the module in bytes + + EntryPoint - The 64 bit physical address of the entry point to the module + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID*)(UINTN)(HandOffHob.HandoffInformationTable->EfiEndOfHobList); + + Hob.Header->HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION; + Hob.Header->HobLength = sizeof(EFI_HOB_MEMORY_ALLOCATION_MODULE); + + CopyMem(&(Hob.MemoryAllocationModule->ModuleName), ModuleName, sizeof(EFI_GUID)); + CopyMem(&(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name), &gEfiHobMemeryAllocModuleGuid, sizeof(EFI_GUID)); + Hob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob.MemoryAllocationModule->MemoryAllocationHeader.MemoryType = EfiConventionalMemory; + + Hob.MemoryAllocationModule->EntryPoint = EntryPoint; + + Hob.MemoryAllocationModule++; + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + +EFI_STATUS +BuildHobResourceDescriptor ( + IN VOID * HobStart, + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +/*++ + +Routine Description: + + Builds a HOB that describes a chunck of system memory + +Arguments: + + HobStart - Start pointer of hob list + + ResourceType - The type of memory described by this HOB + + ResourceAttribute - The memory attributes of the memory described by this HOB + + PhysicalStart - The 64 bit physical address of memory described by this HOB + + NumberOfBytes - The length of the memoty described by this HOB in bytes + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID *)(UINTN)(HandOffHob.HandoffInformationTable->EfiEndOfHobList); + + Hob.Header->HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR; + Hob.Header->HobLength = sizeof(EFI_HOB_RESOURCE_DESCRIPTOR); + + Hob.ResourceDescriptor->ResourceType = ResourceType; + Hob.ResourceDescriptor->ResourceAttribute = ResourceAttribute; + Hob.ResourceDescriptor->PhysicalStart = PhysicalStart; + Hob.ResourceDescriptor->ResourceLength = NumberOfBytes; + + Hob.ResourceDescriptor++; + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + +EFI_STATUS +BuildHobGuidType ( + IN VOID *HobStart, + IN EFI_GUID *Guid, + IN VOID *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + HobStart - Start pointer of hob list + + Guid - The GUID of the custome HOB type + + Buffer - A pointer to the data for the custom HOB type + + BufferSize - The size in byte of BufferSize + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + UINTN Length; + + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID *)(UINTN)HandOffHob.HandoffInformationTable->EfiEndOfHobList; + + + Hob.Header->HobType = EFI_HOB_TYPE_GUID_EXTENSION; + Length = sizeof(EFI_HOB_GUID_TYPE) + BufferSize; + Hob.Header->HobLength = (UINT16)Length; + CopyMem(&Hob.Guid->Name, Guid, sizeof(EFI_GUID)); + CopyMem(Hob.Raw + sizeof(EFI_HOB_GUID_TYPE), Buffer, BufferSize); + Hob.Raw += Length; + + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + +EFI_STATUS +BuildHobFvDescriptor ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a Firmware Volume HOB + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The base address of the Firmware Volume + + Length - The size of the Firmware Volume in bytes + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID*)(UINTN)(HandOffHob.HandoffInformationTable->EfiEndOfHobList); + + Hob.Header->HobType = EFI_HOB_TYPE_FV; + Hob.Header->HobLength = sizeof(EFI_HOB_FIRMWARE_VOLUME); + + Hob.FirmwareVolume->BaseAddress = BaseAddress; + Hob.FirmwareVolume->Length = Length; + + Hob.FirmwareVolume++; + + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + +EFI_STATUS +BuildHobCpu ( + IN VOID *HobStart, + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +/*++ + +Routine Description: + + Builds a HOB for the CPU + +Arguments: + + HobStart - Start pointer of hob list + + SizeOfMemorySpace - Identifies the maximum + physical memory addressibility of the processor. + + SizeOfIoSpace - Identifies the maximum physical I/O addressibility + of the processor. + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID*)(UINTN)HandOffHob.HandoffInformationTable->EfiEndOfHobList; + + Hob.Header->HobType = EFI_HOB_TYPE_CPU; + Hob.Header->HobLength = sizeof(EFI_HOB_CPU); + + Hob.Cpu->SizeOfMemorySpace = SizeOfMemorySpace; + Hob.Cpu->SizeOfIoSpace = SizeOfIoSpace; + + Hob.Cpu++; + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + + + +EFI_STATUS +BuildHobStack ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a HOB for the Stack + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The 64 bit physical address of the Stack + + Length - The length of the stack in bytes + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID*)(UINTN)HandOffHob.HandoffInformationTable->EfiEndOfHobList; + + Hob.Header->HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION; + Hob.Header->HobLength = sizeof(EFI_HOB_MEMORY_ALLOCATION_STACK); + + CopyMem(&(Hob.MemoryAllocationStack->AllocDescriptor.Name), &gEfiHobMemeryAllocStackGuid, sizeof(EFI_GUID)); + (Hob.MemoryAllocationStack->AllocDescriptor).MemoryBaseAddress = BaseAddress; + (Hob.MemoryAllocationStack->AllocDescriptor).MemoryLength = Length; + (Hob.MemoryAllocationStack->AllocDescriptor).MemoryType = EfiBootServicesData; + + Hob.MemoryAllocationStack++; + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + + + +EFI_STATUS +BuildHobBspStore ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the bsp store + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The 64 bit physical address of bsp store + + Length - The length of the bsp store in bytes + + MemoryType - Memory type of the bsp store + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID *)(UINTN)HandOffHob.HandoffInformationTable->EfiEndOfHobList; + Hob.Header->HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION; + Hob.Header->HobLength = sizeof(EFI_HOB_MEMORY_ALLOCATION_BSP_STORE); + + (Hob.MemoryAllocationBspStore->AllocDescriptor).MemoryBaseAddress = BaseAddress; + (Hob.MemoryAllocationBspStore->AllocDescriptor).MemoryLength = Length; + (Hob.MemoryAllocationBspStore->AllocDescriptor).MemoryType = MemoryType; + CopyMem(&(Hob.MemoryAllocationBspStore->AllocDescriptor).Name, &gEfiHobMemeryAllocBspStoreGuid, sizeof(EFI_GUID)); + Hob.MemoryAllocationBspStore++; + + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + + +EFI_STATUS +BuildMemoryAllocationHob ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *Name, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for memory allocation + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The base address of memory allocated by this HOB. + + Length - The length in bytes of memory allocated by this HOB. + + Name - A GUID that defines the memory allocation region¡¯s type and purpose, + as well as other fields within the memory allocation HOB. + + MemoryType - Defines the type of memory allocated by this HOB. + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HandOffHob; + + + HandOffHob.Raw = HobStart; + Hob.Raw = (VOID*)(UINTN)HandOffHob.HandoffInformationTable->EfiEndOfHobList; + + Hob.Header->HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION; + Hob.Header->HobLength = sizeof(EFI_HOB_MEMORY_ALLOCATION); + + if (Name != NULL) { + CopyMem(&(Hob.MemoryAllocation->AllocDescriptor.Name), &Name, sizeof(EFI_GUID)); + } else { + ZeroMem(&Hob.MemoryAllocation->AllocDescriptor.Name, sizeof(EFI_GUID)); + } + + (Hob.MemoryAllocation->AllocDescriptor).MemoryBaseAddress = BaseAddress; + (Hob.MemoryAllocation->AllocDescriptor).MemoryLength = Length; + (Hob.MemoryAllocation->AllocDescriptor).MemoryType = MemoryType; + + Hob.MemoryAllocation++; + HandOffHob.HandoffInformationTable->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + Hob = BuildHobEndOfHobList(Hob.Raw); + HandOffHob.HandoffInformationTable->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) Hob.Raw; + return EFI_SUCCESS; +} + +EFI_STATUS +GetFirstGuidHob ( + IN VOID **HobStart, + IN EFI_GUID *Guid, + OUT VOID **Buffer, + OUT UINTN *BufferSize OPTIONAL + ) +/*++ + +Routine Description: + + This function searches the first instance of a HOB among the whole HOB list. + +Arguments: + + HobStart - A pointer to the start pointer of hob list. + + Guid - A pointer to the GUID to match with in the HOB list. + + Buffer - A pointer to the pointer to the data for the custom HOB type. + + BufferSize - A Pointer to the size in byte of BufferSize. + +Returns: + EFI_SUCCESS + The first instance of the matched GUID HOB among the whole HOB list + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = *HobStart; + + for (Status = EFI_NOT_FOUND; EFI_ERROR (Status); ) { + + if (END_OF_HOB_LIST (GuidHob)) { + return EFI_NOT_FOUND; + } + + if (GuidHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) { + if ( ((INT32 *)Guid)[0] == ((INT32 *)&GuidHob.Guid->Name)[0] && + ((INT32 *)Guid)[1] == ((INT32 *)&GuidHob.Guid->Name)[1] && + ((INT32 *)Guid)[2] == ((INT32 *)&GuidHob.Guid->Name)[2] && + ((INT32 *)Guid)[3] == ((INT32 *)&GuidHob.Guid->Name)[3] ) { + Status = EFI_SUCCESS; + *Buffer = (VOID *)((UINT8 *)(&GuidHob.Guid->Name) + sizeof (EFI_GUID)); + if (BufferSize) { + *BufferSize = GuidHob.Header->HobLength - sizeof (EFI_HOB_GUID_TYPE); + } + } + } + + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + + return Status; +} + +VOID * +GetHob ( + IN UINT16 Type, + IN VOID *HobStart + ) +/*++ + +Routine Description: + + This function returns the first instance of a HOB type in a HOB list. + +Arguments: + + Type The HOB type to return. + HobStart The first HOB in the HOB list. + +Returns: + + HobStart There were no HOBs found with the requested type. + else Returns the first HOB with the matching type. + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = HobStart; + // + // Return input if not found + // + if (HobStart == NULL) { + return HobStart; + } + + // + // Parse the HOB list, stop if end of list or matching type found. + // + while (!END_OF_HOB_LIST (Hob)) { + + if (Hob.Header->HobType == Type) { + break; + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + // + // Return input if not found + // + if (END_OF_HOB_LIST (Hob)) { + return HobStart; + } + + return (VOID *) (Hob.Raw); +} + +EFI_STATUS +GetNextGuidHob ( + IN OUT VOID **HobStart, + IN EFI_GUID * Guid, + OUT VOID **Buffer, + OUT UINTN *BufferSize OPTIONAL + ) +/*++ + +Routine Description: + Get the next guid hob. + +Arguments: + HobStart A pointer to the start hob. + Guid A pointer to a guid. + Buffer A pointer to the buffer. + BufferSize Buffer size. + +Returns: + Status code. + + EFI_NOT_FOUND - Next Guid hob not found + + EFI_SUCCESS - Next Guid hob found and data for this Guid got + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS GuidHob; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + for (Status = EFI_NOT_FOUND; EFI_ERROR (Status);) { + + GuidHob.Raw = *HobStart; + if (END_OF_HOB_LIST (GuidHob)) { + return EFI_NOT_FOUND; + } + + GuidHob.Raw = GetHob (EFI_HOB_TYPE_GUID_EXTENSION, *HobStart); + if (GuidHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) { + if ( ((INT32 *)Guid)[0] == ((INT32 *)&GuidHob.Guid->Name)[0] && + ((INT32 *)Guid)[1] == ((INT32 *)&GuidHob.Guid->Name)[1] && + ((INT32 *)Guid)[2] == ((INT32 *)&GuidHob.Guid->Name)[2] && + ((INT32 *)Guid)[3] == ((INT32 *)&GuidHob.Guid->Name)[3] ) { + Status = EFI_SUCCESS; + *Buffer = (VOID *) ((UINT8 *) (&GuidHob.Guid->Name) + sizeof (EFI_GUID)); + if (BufferSize != NULL) { + *BufferSize = GuidHob.Header->HobLength - sizeof (EFI_HOB_GUID_TYPE); + } + } + } + + *HobStart = GET_NEXT_HOB (GuidHob); + } + + return Status; +} diff --git a/EDK/Foundation/Library/Pei/Hob/PeiHobLib.cif b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.cif new file mode 100644 index 0000000..e43a597 --- /dev/null +++ b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.cif @@ -0,0 +1,11 @@ +<component> + name = "PeiHobLib" + category = ModulePart + LocalRoot = "EDK\Foundation\Library\Pei\Hob\" + RefName = "PeiHobLib" +[files] +"PeiHobLib.sdl" +"PeiHobLib.mak" +"PeiHobLib.c" +"PeiHobLib.inf" +<endComponent> diff --git a/EDK/Foundation/Library/Pei/Hob/PeiHobLib.inf b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.inf new file mode 100644 index 0000000..ba2e8b2 --- /dev/null +++ b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.inf @@ -0,0 +1,51 @@ +#/*++ +# +# 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: +# +# PeiHobLib.inf +# +# Abstract: +# +# Component description file for the PEI library. +# +#--*/ + +[defines] +BASE_NAME = PeiHobLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + PeiHobLib.c + +[sources.ia32] + +[sources.ipf] + +[libraries.common] + +[includes.common] + $(EDK_SOURCE)\Foundation + $(EDK_SOURCE)\Foundation\Efi + . + $(EDK_SOURCE)\Foundation\Core\Dxe + $(EDK_SOURCE)\Foundation\Include + $(EDK_SOURCE)\Foundation\Efi\Include + $(EDK_SOURCE)\Foundation\Framework\Include + $(EDK_SOURCE)\Foundation\Include\IndustryStandard + $(EDK_SOURCE)\Foundation\Include\Pei + $(EDK_SOURCE)\Foundation\Library\Pei\Include + $(EDK_SOURCE)\Foundation\Core\Pei\Include + $(EDK_SOURCE)\Foundation\Library\Dxe\Include + $(EDK_SOURCE)\Foundation\Framework + +[nmake.common] + C_STD_INCLUDE= diff --git a/EDK/Foundation/Library/Pei/Hob/PeiHobLib.mak b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.mak new file mode 100644 index 0000000..4e07ccb --- /dev/null +++ b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.mak @@ -0,0 +1,69 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (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/Modules/SharkBayRefCodes/IntelEDK/PeiHobLib/PeiHobLib.mak 1 1/20/12 4:10a Jeffch $ +# +# $Revision: 1 $ +# +# $Date: 1/20/12 4:10a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/IntelEDK/PeiHobLib/PeiHobLib.mak $ +# +# 1 1/20/12 4:10a Jeffch +# Create Intel EDK 1117 Patch 7. +# +# 1 9/27/11 6:32a Wesleychen +# Intel EDK initially releases. +# +# 2 9/02/09 3:57a Iminglin +# EIP24919 +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: PeiHobLib.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +$(PEIHOBLIB) : PeiHobLib + +$(BUILD_DIR)\PeiHobLib.lib : PeiHobLib + +PeiHobLib : $(BUILD_DIR)\PeiHobLib.mak PeiHobLibBin + +$(BUILD_DIR)\PeiHobLib.mak : $(PeiHobLib_DIR)\$(@B).cif $(PeiHobLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PeiHobLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PeiHobLibBin : + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS)\ + /f $(BUILD_DIR)\PeiHobLib.mak all\ + TYPE=PEI_LIBRARY \ +#********************************************************************** +#********************************************************************** +#** ** +#** (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/EDK/Foundation/Library/Pei/Hob/PeiHobLib.sdl b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.sdl new file mode 100644 index 0000000..45fd030 --- /dev/null +++ b/EDK/Foundation/Library/Pei/Hob/PeiHobLib.sdl @@ -0,0 +1,26 @@ +TOKEN + Name = "PeiHobLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PeiHobLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "PEIHOBLIB" + Value = "$(BUILD_DIR)\PeiHobLib.lib" + TokenType = Expression + TargetMAK = Yes +End + +PATH + Name = "PeiHobLib_DIR" +End + +MODULE + Help = "Includes PeiHobLib.mak to Project" + File = "PeiHobLib.mak" +End + diff --git a/EDK/Foundation/Library/Pei/Include/PeiLib.h b/EDK/Foundation/Library/Pei/Include/PeiLib.h new file mode 100644 index 0000000..3c24e24 --- /dev/null +++ b/EDK/Foundation/Library/Pei/Include/PeiLib.h @@ -0,0 +1,1455 @@ +/*++ + +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: + + PeiLib.h + +Abstract: + + PEI Library Functions + +--*/ + +#ifndef _PEI_LIB_H_ +#define _PEI_LIB_H_ + +#include "Tiano.h" +#include "Pei.h" +#include "peiHobLib.h" +#include EFI_PROTOCOL_DEFINITION (Decompress) +#include EFI_PROTOCOL_DEFINITION (TianoDecompress) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include EFI_PPI_DEFINITION (FindFv) + +//;;## ...AMI_OVERRIDE... Support PI1.x start + +#if (PI_SPECIFICATION_VERSION >= 0x00010000) + +typedef struct { + UINT32 PeiServiceTable; +} PEI_IDT_TABLE; + + +VOID * +EFIAPI +ScanGuid ( + IN VOID *Buffer, + IN UINTN Length, + IN EFI_GUID *Guid + ) +/*++ + +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 * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +/*++ + +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 + +**/ +; + +EFI_STATUS +EFIAPI +PeiLibFfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindNextVolume. + +Arguments: + + Instance - The Fv Volume Instance. + VolumeHandle - Pointer to the current Fv Volume to search. + +Returns: + EFI_STATUS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLibFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindNextFile. + +Arguments: + + 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 +PeiLibFfsFindFileByName ( + IN EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindFileByName. + +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 +PeiLibFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindSectionData. + +Arguments: + + 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_STATUS +--*/ +; + +EFI_STATUS +EFIAPI +PeiLibFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsGetVolumeInfo. + +Arguments: + + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS +--*/ +; + +EFI_STATUS +EFIAPI +PeiServicesLocatePpi ( + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function LocatePpi. + +Arguments: + + 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 +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Build FvHob. + +Arguments: + + BaseAddress - Fv base address. + Length - Fv Length. + +Returns: + NONE. + +--*/ +; + +VOID +EFIAPI +BuildFvHob2 ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *FvNameGuid, + IN EFI_GUID *FileNameGuid + ) +/*++ + +Routine Description: + + Build FvHob2. + +Arguments: + + BaseAddress - Fv base address. + Length - Fv length. + FvNameGuid - Fv name. + FileNameGuid - File name which contians encapsulated Fv. + +Returns: + NONE. +--*/ +; + + +VOID +EFIAPI +BuildGuidDataHob ( + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +/*++ + +Routine Description: + + Build Guid data Hob. + +Arguments: + + Guid - guid to build data hob. + Data - data to build data hob. + DataLength - the length of data. + +Returns: + NONE + +--*/ +; + +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +/*++ + +Routine Description: + + Allocate Memory. + +Arguments: + + Pages - Pages to allocate. + +Returns: + Address if successful to allocate memory. + NULL if fail to allocate memory. + +--*/ +; + +VOID +SetPeiServicesTablePointer ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Save PeiService pointer so that it can be retrieved anywhere. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + +Returns: + NONE + +--*/ +; + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ) +/*++ + +Routine Description: + + Get PeiService pointer. + +Arguments: + + NONE. + +Returns: + The direct pointer to PeiServiceTable. + +--*/ +; + +VOID +MigrateIdtTable ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Migrate IDT from CAR to real memory where preceded with 4 bytes for + storing PeiService pointer. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + +Returns: + + NONE. + +--*/ +; + + +UINTN +ReadIdtBase ( + VOID + ) +/*++ + +Routine Description: + + Read IDT Register BaseAddress. + +Arguments: + + NONE + +Returns: + IDT Register BaseAddress. + +--*/ +; + + +UINT16 +ReadIdtLimit ( + VOID + ) +/*++ + +Routine Description: + + Read IDT Register Limit. + +Arguments: + + NONE + +Returns: + IDT Register Limit. + +--*/ +; + + +VOID +SetIdtBase ( + UINT32 IdtBase, + UINT16 IdtLimit + ) +/*++ + +Routine Description: + + Set IDT Register BaseAddress. + +Arguments: + + IdtBase - IDT.BaseAddress + IdtLimit - IDT.Limit + +Returns: + NONE +--*/ +; + +VOID +AsmWriteKr7 ( + UINT64 Address + ) +/*++ + +Routine Description: + + Write 64 bit into Kernel Register7 on IPF. + +Arguments: + + Address - Data to write into kr7. + +Returns: + NONE + +--*/ +; + + +UINT64 +AsmReadKr7 ( + VOID + ) +/*++ + +Routine Description: + + Read 64 bit from Kernel Register7 on IPF. + +Arguments: + + NONE + +Returns: + Data in kr7. + +--*/ +; + +#endif +//;;## ...AMI_OVERRIDE... Support PI1.x end + +VOID +PeiCopyMem ( + 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 +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + Set Buffer to zero for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + +Returns: + + None + +--*/ +; + +VOID +CopyMem ( + 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 + +--*/ +; + +BOOLEAN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares two GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = TRUE if Guid1 == Guid2 + = FALSE if Guid1 != Guid2 + +--*/ +; + +EFI_STATUS +InstallEfiPeiPeCoffLoader ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL **This, + IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi + ) +/*++ + +Routine Description: + + Install EFI Pei PE coff loader protocol. + +Arguments: + + PeiServices - The PEI core services table. + + This - Pointer to get Pei PE coff loader protocol as output + + ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform + +Returns: + + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +InstallEfiPeiPeCoffLoader64 ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL **This, + IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi + ); + + + +EFI_STATUS +InstallEfiDecompress ( + EFI_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install EFI decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - EFI decompress protocol successfully installed. + +--*/ +; + +EFI_STATUS +InstallTianoDecompress ( + EFI_TIANO_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install Tiano decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - Tiano decompress protocol successfully installed. + +--*/ +; + +VOID +PeiPerfMeasure ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log a timestamp count. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + EntryExit - Indicates start or stop measurement + + Value - The start time or the stop time + +Returns: + +--*/ +; + +VOID +PeiPerfMeasureEx ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN UINT16 Identifier, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log a timestamp count. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + Identifier - Progress Identifier + + EntryExit - Indicates start or stop measurement + + Value - The start time or the stop time + +Returns: + +--*/ +; + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ) +/*++ + +Routine Description: + + Get timer value. + +Arguments: + + TimerValue - Pointer to the returned timer value + +Returns: + + EFI_SUCCESS - Successfully got timer value + +--*/ +; + +#ifdef FIRMWARE_PERFORMANCE +#define PEI_PERF_START(Ps, Token, FileHeader, Value) PeiPerfMeasure (Ps, Token, FileHeader, FALSE, Value) +#define PEI_PERF_END(Ps, Token, FileHeader, Value) PeiPerfMeasure (Ps, Token, FileHeader, TRUE, Value) +#define PEI_PERF_START_EX(Ps, Token, FileHeader, Identifier, Value) PeiPerfMeasureEx (Ps, Token, FileHeader, Identifier, FALSE, Value) +#define PEI_PERF_END_EX(Ps, Token, FileHeader, Identifier, Value) PeiPerfMeasureEx (Ps, Token, FileHeader, Identifier, TRUE, Value) +#else +#define PEI_PERF_START(Ps, Token, FileHeader, Value) +#define PEI_PERF_END(Ps, Token, FileHeader, Value) +#define PEI_PERF_START_EX(Ps, Token, FileHeader, Identifier, Value) +#define PEI_PERF_END_EX(Ps, Token, FileHeader, Identifier, Value) +#endif + +#ifdef EFI_NT_EMULATOR +EFI_STATUS +PeCoffLoaderWinNtLoadAsDll ( + IN CHAR8 *PdbFileName, + IN VOID **ImageEntryPoint, + OUT VOID **ModHandle + ) +/*++ + +Routine Description: + + Loads the .DLL file is present when a PE/COFF file is loaded. This provides source level + debugging for drivers that have cooresponding .DLL files on the local system. + +Arguments: + + PdbFileName - The name of the .PDB file. This was found from the PE/COFF + file's debug directory entry. + + ImageEntryPoint - A pointer to the DLL entry point of the .DLL file was loaded. + + ModHandle - Pointer to loaded library. + +Returns: + + EFI_SUCCESS - The .DLL file was loaded, and the DLL entry point is returned in ImageEntryPoint + + EFI_NOT_FOUND - The .DLL file could not be found + + EFI_UNSUPPORTED - The .DLL file was loaded, but the entry point to the .DLL file could not + determined. + +--*/ +; + +#endif +// +// hob.c +// +EFI_STATUS +PeiBuildHobModule ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS Module, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +/*++ + +Routine Description: + + Builds a HOB for a loaded PE32 module + +Arguments: + + PeiServices - The PEI core services table. + ModuleName - The GUID File Name of the module + Memory - The 64 bit physical address of the module + ModuleLength - The length of the module in bytes + EntryPoint - The 64 bit physical address of the entry point + to the module + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobResourceDescriptor ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +/*++ + +Routine Description: + + Builds a HOB that describes a chunck of system memory + +Arguments: + + PeiServices - The PEI core services table. + + ResourceType - The type of resource described by this HOB + + ResourceAttribute - The resource attributes of the memory described by this HOB + + PhysicalStart - The 64 bit physical address of memory described by this HOB + + NumberOfBytes - The length of the memoty described by this HOB in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +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 +PeiBuildHobGuidData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +/*++ + +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 + + Data - The data to be copied into the GUIDed HOB data field. + + DataLength - The data field length. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobFv ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a Firmware Volume HOB + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The base address of the Firmware Volume + + Length - The size of the Firmware Volume in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobCpu ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +/*++ + +Routine Description: + + Builds a HOB for the CPU + +Arguments: + + PeiServices - The PEI core services table. + + SizeOfMemorySpace - Identifies the maximum + physical memory addressibility of the processor. + + SizeOfIoSpace - Identifies the maximum physical I/O addressibility + of the processor. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +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 +PeiBuildHobBspStore ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the bsp store + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the bsp store + + Length - The length of the bsp store in bytes + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +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 + +--*/ +; + +// +// print.c +// +UINTN +AvSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN StrSize, + IN CONST CHAR8 *Format, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + AvSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + +Arguments: + + StartOfBuffer - Ascii buffer to print the results of the parsing of Format into. + + StrSize - Maximum number of characters to put into buffer. Zero means + no limit. + + FormatString - Ascii format string see file header for more details. + + Marker - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +; + +UINTN +ASPrint ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN CONST CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + ASPrint function to process format and place the results in Buffer. + +Arguments: + + Buffer - Ascii buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means no + limit. + + Format - Ascii format string see file header for more details. + + ... - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +; + +// +// math.c +// +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be multiplied with a 32 bit + value returns 64bit result. + No checking if the result is greater than 64bits + +Arguments: + + Multiplicand - multiplicand + Multiplier - multiplier + +Returns: + + Multiplicand * Multiplier + +--*/ +; + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be divided with a 32 bit value returns + 64bit result and the Remainder. + N.B. only works for 31bit divisors!! + +Arguments: + + Dividend - dividend + Divisor - divisor + Remainder - buffer for remainder + +Returns: + + Dividend / Divisor + Remainder = Dividend mod Divisor + +--*/ +; + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be right shifted by 32 bits and returns the + shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + Count - Number of times to shift right. + +Returns: + + Value shifted right identified by the Count. + +--*/ +; + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be left shifted by 32 bits and + returns the shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + Count - Number of times to shift left. + +Returns: + + Value shifted left identified by the Count. + +--*/ +; + +VOID +RegisterNativeCpuIo ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CpuIo + ) +/*++ + +Routine Description: + + Register a native Cpu IO + +Arguments: + + PeiServices - Calling context + CpuIo - CpuIo instance to register + +Returns: + + None + +--*/ +; + +VOID +GetNativeCpuIo ( + IN EFI_PEI_SERVICES **PeiServices, + OUT VOID **CpuIo + ) +/*++ + +Routine Description: + + Get registered Cpu IO. + +Arguments: + + PeiServices - Calling context + CpuIo - CpuIo instance registered before + +Returns: + + None + +--*/ +; + +EFI_STATUS +FindFv ( + IN EFI_FIND_FV_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT8 *FvNumber, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FVAddress + ) +/*++ + +Routine Description: + + Search Fv in Hob. + +Arguments: + + This - Interface pointer that implement the Find Fv PPI + + PeiServices - Pointer to the PEI Service Table + + FvNumber - The index of the fireware volume to locate + + FVAddress - The address of the volume to discover + +Returns: + + EFI_SUCCESS - An addtional fv found + EFI_OUT_OF_RESOURCES - There are no fireware volume for given fvnumber + EFI_INVALID_PARAMETER - *FvAddress is NULL + +--*/ +; + + + +EFI_STATUS +EFIAPI +PeiLibPciCfgModify ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PCI_CFG_PPI *PciCfg, + IN PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN SetBits, + IN UINTN ClearBits + ) +/*++ + +Routine Description: + + PCI read-modify-write operations. + + PIWG's PI specification replaces Inte's EFI Specification 1.10. + EFI_PEI_PCI_CFG_PPI defined in Inte's EFI Specification 1.10 is replaced by + EFI_PEI_PCI_CFG2_PPI in PI 1.0. "Modify" function in these two PPI are not + compatibile with each other. + + + For Framework code that make the following call: + + PciCfg->Modify ( + PeiServices, + PciCfg, + Width, + Address, + SetBits, + ClearBits + ); + it will be updated to the following code which call this library API: + PeiLibPciCfgModify ( + PeiServices, + PciCfg, + Width, + Address, + SetBits, + ClearBits + ); + + The + +Arguments: + + PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + PciCfg A pointer to the this pointer of EFI_PEI_PCI_CFG_PPI. + This parameter is unused as a place holder to make + the parameter list identical to PEI_PCI_CFG_PPI_RW. + Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + + Address The physical address of the access. + + SetBits Points to value to bitwise-OR with the read configuration value. + + The size of the value is determined by Width. + + ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + +Returns: + + EFI_SUCCESS The function completed successfully. + + EFI_DEVICE_ERROR There was a problem with the transaction. + +--*/ +; + +#endif diff --git a/EDK/Foundation/Library/Pei/Include/peihoblib.h b/EDK/Foundation/Library/Pei/Include/peihoblib.h new file mode 100644 index 0000000..9a8b455 --- /dev/null +++ b/EDK/Foundation/Library/Pei/Include/peihoblib.h @@ -0,0 +1,346 @@ +/*++ + +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: + + PeiHobLib.h + +Abstract: + + +--*/ + +#ifndef _EFI_PEI_HOB_LIB_H_ +#define _EFI_PEI_HOB_LIB_H_ + +#include "PeiApi.h" // EFI_PEI_SERVICES definition +#define EFI_STACK_SIZE 0x20000 +#define EFI_BSP_STORE_SIZE 0x4000 + +EFI_STATUS +BuildHobHandoffInfoTable ( + IN VOID *HobStart, + IN UINT16 Version, + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS EfiMemoryTop, + IN EFI_PHYSICAL_ADDRESS EfiMemoryBottom, + IN EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop, + IN EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom + ) +/*++ + +Routine Description: + + Builds a HandoffInformationTable Information Table HOB + +Arguments: + + HobStart - Start pointer of hob list + Version - The version number pertaining to the PHIT HOB definition. + BootMode - The system boot mode as determined during the HOB producer phase. + EfiMemoryTop - The highest address location of memory that is allocated for use by the HOB + producer phase. + EfiMemoryBottom - The lowest address location of memory that is allocated for use by the HOB + producer phase. + EfiFreeMemoryTop - The highest address location of free memory that is currently available for use + by the HOB producer phase. + EfiFreeMemoryBottom - The lowest address location of free memory that is available for + use by the HOB producer phase. + +Returns: + + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +BuildHobModule ( + IN VOID *HobStart, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS Module, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +/*++ + +Routine Description: + + Builds a HOB for a loaded PE32 module + +Arguments: + + HobStart - Start pointer of hob list + + ModuleName - The GUID File Name of the HON from the Firmware Volume + + Module - The 64 bit physical address of the module + + ModuleLength - The length of the module in bytes + + EntryPoint - The 64 bit physical address of the entry point to the module + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildHobResourceDescriptor ( + IN VOID *HobStart, + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +/*++ + +Routine Description: + + Builds a HOB that describes a chunck of system memory + +Arguments: + + HobStart - Start pointer of hob list + + ResourceType - The type of memory described by this HOB + + ResourceAttribute - The memory attributes of the memory described by this HOB + + PhysicalStart - The 64 bit physical address of memory described by this HOB + + NumberOfBytes - The length of the memoty described by this HOB in bytes + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildHobGuidType ( + IN VOID *HobStart, + IN EFI_GUID *Guid, + IN VOID *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + HobStart - Start pointer of hob list + + Guid - The GUID of the custome HOB type + + Buffer - A pointer to the data for the custom HOB type + + BufferSize - The size in byte of BufferSize + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildHobFvDescriptor ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a Firmware Volume HOB + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The base address of the Firmware Volume + + Length - The size of the Firmware Volume in bytes + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildHobCpu ( + IN VOID *HobStart, + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +/*++ + +Routine Description: + + Builds a HOB for the CPU + +Arguments: + + HobStart - Start pointer of hob list + + SizeOfMemorySpace - Identifies the maximum + physical memory addressibility of the processor. + + SizeOfIoSpace - Identifies the maximum physical I/O addressibility + of the processor. + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildHobStack ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a HOB for the Stack + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The 64 bit physical address of the Stack + + Length - The length of the stack in bytes + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildHobBspStore ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the bsp store + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The 64 bit physical address of bsp store + + Length - The length of the bsp store in bytes + + MemoryType - Memory type of the bsp store + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +BuildMemoryAllocationHob ( + IN VOID *HobStart, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *Name, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for memory allocation + +Arguments: + + HobStart - Start pointer of hob list + + BaseAddress - The base address of memory allocated by this HOB. + + Length - The length in bytes of memory allocated by this HOB. + + Name - A GUID that defines the memory allocation region¡¯s type and purpose, + as well as other fields within the memory allocation HOB. + + MemoryType - Defines the type of memory allocated by this HOB. + +Returns: + + EFI_SUCCESS + EFI_NOT_AVAILABLE_YET + +--*/ +; + +EFI_STATUS +GetNextGuidHob ( + IN OUT VOID **HobStart, + IN EFI_GUID * Guid, + OUT VOID **Buffer, + OUT UINTN *BufferSize OPTIONAL + ) +/*++ + +Routine Description: + Get the next guid hob. + +Arguments: + HobStart A pointer to the start hob. + Guid A pointer to a guid. + Buffer A pointer to the buffer. + BufferSize Buffer size. + +Returns: + Status code. + + EFI_NOT_FOUND - Next Guid hob not found + + EFI_SUCCESS - Next Guid hob found and data for this Guid got + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/Debug.c b/EDK/Foundation/Library/Pei/PeiLib/Debug.c new file mode 100644 index 0000000..3f2fe67 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Debug.c @@ -0,0 +1,158 @@ +/*++ + +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: + + Debug.c + +Abstract: + + Support for Debug primatives. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "EfiPrintLib.h" +#include "EfiStatusCode.h" +#include "EfiCommonLib.h" +#include EFI_GUID_DEFINITION (StatusCodeCallerId) +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) +#include EFI_PPI_DEFINITION (DebugMask) + +UINTN gErrorLevel = EFI_DBUG_MASK | EFI_D_LOAD | EFI_D_INFO; //;;## ...AMI_OVERRIDE... Aptio not support gEfiDebugMaskPpiGuid. + +VOID +PeiDebugAssert ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +/*++ + +Routine Description: + + Worker function for ASSERT(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded DEADLOOP (). + +Arguments: + + PeiServices - The PEI core services table. + + FileName - File name of failing routine. + + LineNumber - Line number of failing ASSERT(). + + Description - Description, usually the assertion, + +Returns: + + None + +--*/ +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + + EfiDebugAssertWorker (FileName, LineNumber, Description, sizeof (Buffer), Buffer); + + // + // We choose NOT to use PEI_REPORT_STATUS_CODE here, because when debug is enable, + // we want get enough information if assert. + // + (**PeiServices).PeiReportStatusCode ( + PeiServices, + (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), + (EFI_SOFTWARE_PEI_MODULE | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE), + 0, + &gEfiCallerIdGuid, + (EFI_STATUS_CODE_DATA *) Buffer + ); + + EFI_DEADLOOP (); +} + + +VOID +PeiDebugPrint ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + Worker function for DEBUG(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded do nothing. + +Arguments: + + PeiServices - The PEI core services table. + + ErrorLevel - If error level is set do the debug print. + + Format - String to use for the print, followed by Print arguments. + + ... - Print arguments + +Returns: + + None + +--*/ +{ + VA_LIST Marker; + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + EFI_DEBUG_MASK_PPI *DebugMaskPpi; + EFI_STATUS Status; + + // + // Locate the DebugMask Ppi. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiDebugMaskPpiGuid, + 0, + NULL, + &DebugMaskPpi + ); + + // + // Check driver debug mask value and global mask + // + if (!EFI_ERROR (Status)) { + if (!(ErrorLevel & DebugMaskPpi->ImageDebugMask)) { + return ; + } + } else if (!(gErrorLevel & ErrorLevel)) { + return ; + } + + VA_START (Marker, Format); + EfiDebugVPrintWorker (ErrorLevel, Format, Marker, sizeof (Buffer), Buffer); + + // + // We choose NOT to use PEI_REPORT_STATUS_CODE here, because when debug is enable, + // we want get enough information if assert. + // + (**PeiServices).PeiReportStatusCode ( + PeiServices, + EFI_DEBUG_CODE, + (EFI_SOFTWARE_PEI_MODULE | EFI_DC_UNSPECIFIED), + 0, + &gEfiCallerIdGuid, + (EFI_STATUS_CODE_DATA *) Buffer + ); + + return ; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Decompress.c b/EDK/Foundation/Library/Pei/PeiLib/Decompress.c new file mode 100644 index 0000000..2a8c80b --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Decompress.c @@ -0,0 +1,1140 @@ +/*++ + +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: + + Decompress.c + +Abstract: + + Decompressor. Algorithm Ported from OPSD code (Decomp.asm) + +--*/ + +#include "TianoCommon.h" +#include EFI_PROTOCOL_DEFINITION (Decompress) +#include EFI_PROTOCOL_DEFINITION (TianoDecompress) + +EFI_STATUS +EFIAPI +EfiGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +EfiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +EFI_STATUS +EFIAPI +TianoGetInfo ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +TianoDecompress ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +// +// The protocol instance +// + +EFI_DECOMPRESS_PROTOCOL mEfiDecompress = { + EfiGetInfo, + EfiDecompress +}; + +EFI_TIANO_DECOMPRESS_PROTOCOL mTianoDecompress = { + TianoGetInfo, + TianoDecompress +}; + +EFI_STATUS +InstallEfiDecompress ( + IN OUT EFI_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install EFI decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - EFI decompress protocol successfully installed. + +--*/ +{ + *This = &mEfiDecompress; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallTianoDecompress ( + EFI_TIANO_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install Tiano decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - Tiano decompress protocol successfully installed. + +--*/ +{ + *This = &mTianoDecompress; + return EFI_SUCCESS; +} +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define UINT8_MAX 0xff +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; +} SCRATCH_DATA; + +STATIC +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + +Arguments: + + Sd - The global scratch data + NumOfBits - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +STATIC +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + +Arguments: + + Sd - The global scratch data. + NumOfBits - The number of bits to pop and read. + +Returns: + + The bits that are popped out. + +--*/ +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +STATIC +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +/*++ + +Routine Description: + + Creates Huffman Code mapping table according to code length array. + +Arguments: + + Sd - The global scratch data + NumOfChar - Number of symbols in the symbol set + BitLen - Code length array + TableBits - The width of the mapping table + Table - The table + +Returns: + + 0 - OK. + BAD_TABLE - The table is corrupted. + +--*/ +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + + // + // TableBits should not be greater than 16. + // + if (TableBits >= (sizeof (Count)/sizeof (UINT16))) { + return (UINT16) BAD_TABLE; + } + + // + // Initialize Count array starting from Index 0, as there is a possibility of Count array being uninitialized. + // + for (Index = 0; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + // + // Count array index should not be greater than or equal to its size. + // + if (BitLen[Index] < (sizeof (Count)/sizeof (UINT16))) { + Count[BitLen[Index]]++; + } else { + return (UINT16) BAD_TABLE; + } + } + + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index++] = (UINT16) (1U << (16 - Index)); + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + // + // Avail should be lesser than size of mRight and mLeft to prevent buffer overflow. + // + if ((*Pointer == 0) && (Avail < sizeof (Sd->mRight)/sizeof (UINT16)) && (Avail < sizeof (Sd->mLeft)/sizeof (UINT16))) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + // + // *Pointer should be lesser than size of mRight and mLeft to prevent buffer overflow. + // + if ((Index3 & Mask) && (*Pointer < (sizeof (Sd->mRight)/sizeof (UINT16)))) { + Pointer = &Sd->mRight[*Pointer]; + } else if (*Pointer < (sizeof (Sd->mLeft)/sizeof (UINT16))) { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +STATIC +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decodes a position value. + +Arguments: + + Sd - the global scratch data + +Returns: + + The position value decoded. + +--*/ +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +STATIC +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +/*++ + +Routine Description: + + Reads code lengths for the Extra Set or the Position Set + +Arguments: + + Sd - The global scratch data + nn - Number of symbols + nbit - Number of bits needed to represent nn + Special - The special symbol that needs to be taken care of + +Returns: + + 0 - OK. + BAD_TABLE - Table is corrupted. + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, nbit); + + if ((Number > sizeof (Sd->mPTLen)) || (nn > sizeof (Sd->mPTLen))) { + // + // Fail if Number or nn is greater than size of mPTLen + // + return (UINT16) BAD_TABLE; + } + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + while ((INT16) (--CharC) >= 0) { + if (Index >= sizeof (Sd->mPTLen)) { + // + // Fail if Index is greater than or equal to mPTLen + // + return (UINT16) BAD_TABLE; + } + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +STATIC +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Reads code lengths for Char&Len Set. + +Arguments: + + Sd - the global scratch data + +Returns: (VOID) + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + while ((INT16) (--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +STATIC +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode a character/length value. + +Arguments: + + Sd - The global scratch data. + +Returns: + + The value decoded. + +--*/ +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +STATIC +VOID +Decode ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode the source data and put the resulting data into the destination buffer. + +Arguments: + + Sd - The global scratch data + +Returns: (VOID) + + --*/ +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return ; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + BytesRemain--; + } + } + } + + return ; +} + +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT8 *Src; + + *ScratchSize = sizeof (SCRATCH_DATA); + + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + return EFI_SUCCESS; +} + +EFI_STATUS +Decompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize, + IN UINT8 Version + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + Version - The version of de/compression algorithm. + Version 1 for EFI 1.1 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + UINT8 *Src; + UINT8 *Dst; + + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; + + if (ScratchSize < sizeof (SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } + + Sd = (SCRATCH_DATA *) Scratch; + + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return Status; + } + + if (SrcSize < CompSize + 8) { + return EFI_INVALID_PARAMETER; + } + + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1: + Sd->mPBit = 4; + break; + + case 2: + Sd->mPBit = 5; + break; + + default: + // + // Currently, only have 2 versions + // + return EFI_INVALID_PARAMETER; + } + + Sd->mSrcBase = Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} + +EFI_STATUS +EFIAPI +EfiGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo ( + Source, + SrcSize, + DstSize, + ScratchSize + ); +} + +EFI_STATUS +EFIAPI +EfiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + // + // For EFI 1.1 de/compression algorithm, the version is 1. + // + return Decompress ( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 1 + ); +} + +EFI_STATUS +EFIAPI +TianoGetInfo ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo ( + Source, + SrcSize, + DstSize, + ScratchSize + ); +} + +EFI_STATUS +EFIAPI +TianoDecompress ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + // + // For Tiano de/compression algorithm, the version is 2. + // + return Decompress ( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 2 + ); +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/FindFv.c b/EDK/Foundation/Library/Pei/PeiLib/FindFv.c new file mode 100644 index 0000000..c0149c2 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/FindFv.c @@ -0,0 +1,157 @@ +/*++ + +Copyright (c) 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: + + FindFv.c + +Abstract: + + Library function to find fv by hob. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiHobLib.h" + +static +VOID * +GetHob ( + IN UINT16 Type, + IN VOID *HobStart + ) +/*++ + +Routine Description: + + This function returns the first instance of a HOB type in a HOB list. + +Arguments: + + Type The HOB type to return. + HobStart The first HOB in the HOB list. + +Returns: + + HobStart There were no HOBs found with the requested type. + else Returns the first HOB with the matching type. + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = HobStart; + // + // Return input if not found + // + if (HobStart == NULL) { + return HobStart; + } + + // + // Parse the HOB list, stop if end of list or matching type found. + // + while (!END_OF_HOB_LIST (Hob)) { + + if (Hob.Header->HobType == Type) { + break; + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + // + // Return input if not found + // + if (END_OF_HOB_LIST (Hob)) { + return HobStart; + } + + return (VOID *) (Hob.Raw); +} + +EFI_STATUS +FindFv ( + IN EFI_FIND_FV_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT8 *FvNumber, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FvAddress + ) +/*++ + +Routine Description: + + Search Fv in Hob. + +Arguments: + + This - Interface pointer that implement the Find Fv PPI + + PeiServices - Pointer to the PEI Service Table + + FvNumber - The index of the fireware volume to locate + + FVAddress - The address of the volume to discover + +Returns: + + EFI_SUCCESS - An addtional fv found + EFI_OUT_OF_RESOURCES - There are no fireware volume for given fvnumber + EFI_INVALID_PARAMETER - *FvAddress is NULL + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS HobStart; + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_FIRMWARE_VOLUME *FvHob; + UINT8 FvIndex; + + if (*FvAddress == NULL){ + return EFI_INVALID_PARAMETER; + } + + Hob.Raw = NULL; + + // + // Get the Hob table pointer + // + Status = (*PeiServices)->GetHobList ( + PeiServices, + &HobStart.Raw + ); + + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Loop to search the wanted FirmwareVolume Hob + // + for (FvIndex = 0; FvIndex <= *FvNumber; FvIndex++) { + Hob.Raw = GetHob (EFI_HOB_TYPE_FV, HobStart.Raw); + if (Hob.Header->HobType != EFI_HOB_TYPE_FV) { + *FvNumber = 0; + return EFI_OUT_OF_RESOURCES; + } + + HobStart.Raw = Hob.Raw + Hob.Header->HobLength; + } + + FvHob = Hob.FirmwareVolume; + + *FvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvHob->BaseAddress); + (*FvNumber)++; + + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Hob/Hob.c b/EDK/Foundation/Library/Pei/PeiLib/Hob/Hob.c new file mode 100644 index 0000000..18f32cf --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Hob/Hob.c @@ -0,0 +1,517 @@ +/*++ + +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: + + PEI Library Functions + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "peilib.h" +#include EFI_GUID_DEFINITION (MemoryAllocationHob) + + +EFI_STATUS +PeiBuildHobModule ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +/*++ + +Routine Description: + + Builds a HOB for a loaded PE32 module + +Arguments: + + PeiServices - The PEI core services table. + ModuleName - The GUID File Name of the module + MemoryAllocationModule - The 64 bit physical address of the module + ModuleLength - The length of the module in bytes + EntryPoint - The 64 bit physical address of the entry point + to the module + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->MemoryAllocationHeader.Name = gEfiHobMemeryAllocModuleGuid; + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + (*PeiServices)->SetMem ( + Hob->MemoryAllocationHeader.Reserved, + sizeof (Hob->MemoryAllocationHeader.Reserved), + 0 + ); + + Hob->ModuleName = *ModuleName; + Hob->EntryPoint = EntryPoint; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobResourceDescriptor ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +/*++ + +Routine Description: + + Builds a HOB that describes a chunck of system memory + +Arguments: + + PeiServices - The PEI core services table. + + ResourceType - The type of resource described by this HOB + + ResourceAttribute - The resource attributes of the memory described by this HOB + + PhysicalStart - The 64 bit physical address of memory described by this HOB + + NumberOfBytes - The length of the memoty described by this HOB in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobGuid ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN DataLength, + 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 pointer to the created 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; +} + + +EFI_STATUS +PeiBuildHobGuidData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +/*++ + +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 + + Data - The data to be copied into the GUIDed HOB data field. + + DataLength - The data field length. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + + EFI_HOB_GUID_TYPE *Hob; + + Status = PeiBuildHobGuid ( + PeiServices, + Guid, + DataLength, + &Hob + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Hob++; + (*PeiServices)->CopyMem (Hob, Data, DataLength); + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobFv ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a Firmware Volume HOB + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The base address of the Firmware Volume + + Length - The size of the Firmware Volume in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_FV, + sizeof (EFI_HOB_FIRMWARE_VOLUME), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobCpu ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +/*++ + +Routine Description: + + Builds a HOB for the CPU + +Arguments: + + PeiServices - The PEI core services table. + + SizeOfMemorySpace - Identifies the maximum + physical memory addressibility of the processor. + + SizeOfIoSpace - Identifies the maximum physical I/O addressibility + of the processor. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_CPU *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_CPU, + sizeof (EFI_HOB_CPU), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + (*PeiServices)->SetMem ( + Hob->Reserved, + sizeof (Hob->Reserved), + 0 + ); + + return EFI_SUCCESS; +} + + + +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; + + 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 = EfiBootServicesData; + + (*PeiServices)->SetMem ( + Hob->AllocDescriptor.Reserved, + sizeof (Hob->AllocDescriptor.Reserved), + 0 + ); + + return EFI_SUCCESS; +} + + + +EFI_STATUS +PeiBuildHobBspStore ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the bsp store + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the bsp + + Length - The length of the bsp store in bytes + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION_BSP_STORE), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->AllocDescriptor.Name = gEfiHobMemeryAllocBspStoreGuid; + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + (*PeiServices)->SetMem ( + Hob->AllocDescriptor.Reserved, + sizeof (Hob->AllocDescriptor.Reserved), + 0 + ); + + 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; + (*PeiServices)->SetMem ( + Hob->AllocDescriptor.Reserved, + sizeof (Hob->AllocDescriptor.Reserved), + 0 + ); + + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeCoffLoaderEx.c b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeCoffLoaderEx.c new file mode 100644 index 0000000..60018ed --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeCoffLoaderEx.c @@ -0,0 +1,268 @@ +/*++ + +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: + + PeCoffLoaderEx.c + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#include "TianoCommon.h" +#include "EfiImage.h" + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +{ + UINT64 *F64; + UINT64 FixupVal; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_IA64_IMM64: + + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + + Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); + FixupVal = (UINT64)0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X, + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + // + // Update 64-bit address + // + FixupVal += Adjust; + + // + // Insert IMM64 into bundle + // + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X), + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X), + IMM64_IMM41b_SIZE_X, + IMM64_IMM41b_INST_WORD_POS_X, + IMM64_IMM41b_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X), + IMM64_IMM41c_SIZE_X, + IMM64_IMM41c_INST_WORD_POS_X, + IMM64_IMM41c_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), + IMM64_SIGN_SIZE_X, + IMM64_SIGN_INST_WORD_POS_X, + IMM64_SIGN_VAL_POS_X + ); + + F64 = (UINT64 *) Fixup; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IPF, EBC, + images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +{ + if ((Machine == EFI_IMAGE_MACHINE_IA64) || (Machine == EFI_IMAGE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeCoffLoaderEx.h b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeCoffLoaderEx.h new file mode 100644 index 0000000..fc14551 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeCoffLoaderEx.h @@ -0,0 +1,87 @@ +/*++ + +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: + + PeCoffLoaderEx.h + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +; + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IPF, EBC, + images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeiServicePointer.c b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeiServicePointer.c new file mode 100644 index 0000000..f4f1ae0 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PeiServicePointer.c @@ -0,0 +1,109 @@ +/*++ + +Copyright 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: + + PeiServicePointer.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" +#include "PeiLib.h" + +//;;## ...AMI_ADD FILE... Support PI1.x + +#if (PI_SPECIFICATION_VERSION >= 0x00010000) + +VOID +SetPeiServicesTablePointer ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Save PeiService pointer so that it can be retrieved anywhere. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + PhyscialAddress - The physcial address of variable PeiServices. + +Returns: + NONE + +--*/ + +{ + // + // For Itanium Processor Family processors, the EFI_PEI_SERVICES** + // is stored in kernel register7. + // + AsmWriteKr7((UINT64)(UINTN)PeiServices); +} + + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ) +/*++ + +Routine Description: + + Get PeiService pointer. + +Arguments: + + NONE. + +Returns: + The direct pointer to PeiServiceTable. + +--*/ + +{ + // + // For Itanium Processor Family processors, the EFI_PEI_SERVICES** + // is stored in kernel register7. + // + return (EFI_PEI_SERVICES **)(UINTN)AsmReadKr7(); +} + +VOID +MigrateIdtTable ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Migrate IDT from CAR to real memory where preceded with 4 bytes for + storing PeiService pointer. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + +Returns: + + NONE. + +--*/ +{ + return; +} + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/PerformancePrimitives.s b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PerformancePrimitives.s new file mode 100644 index 0000000..5aeb886 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/PerformancePrimitives.s @@ -0,0 +1,61 @@ +//++ +// 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: +// +// PerformancePrimitives.s +// +// Abstract: +// +// +// Revision History: +// +//-- + +.file "PerformancePrimitives.s" + +#include "IpfMacro.i" + +//----------------------------------------------------------------------------- +//++ +// GetTimerValue +// +// Implementation of CPU-based time service +// +// On Entry : +// EFI_STATUS +// GetTimerValue ( +// OUT UINT64 *TimerValue +// ) +// +// Return Value: +// r8 = Status +// r9 = 0 +// r10 = 0 +// r11 = 0 +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (GetTimerValue) + + NESTED_SETUP (1,8,0,0) + mov r8 = ar.itc;; + st8 [r32]= r8 + mov r8 = r0 + mov r9 = r0 + mov r10 = r0 + mov r11 = r0 + NESTED_RETURN + +PROCEDURE_EXIT (GetTimerValue) +//--------------------------------------------------------------------------- + diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/SwitchStack.s b/EDK/Foundation/Library/Pei/PeiLib/Ipf/SwitchStack.s new file mode 100644 index 0000000..5de7e18 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/SwitchStack.s @@ -0,0 +1,122 @@ +//++ +// 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: +// +// SwitchStack.s +// +// Abstract: +// +// Contains an implementation of a stack switch for the Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "SwitchStack.s" + +#include <asm.h> +#include <ia_64gen.h> + +// Define hardware RSE Configuration Register +// +// RS Configuration (RSC) bit field positions + +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +// RSC bits 5-15 reserved +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +// RSC bits 30-63 reserved +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffULL + +// RSC modes +// Lazy +#define RSC_MODE_LY (0x0) +// Store intensive +#define RSC_MODE_SI (0x1) +// Load intensive +#define RSC_MODE_LI (0x2) +// Eager +#define RSC_MODE_EA (0x3) + +// RSC Endian bit values +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// RSC while in kernel: enabled, little endian, pl = 0, eager mode +#define RSC_KERNEL ((RSC_MODE_EA<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) +// Lazy RSC in kernel: enabled, little endian, pl = 0, lazy mode +#define RSC_KERNEL_LAZ ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) +// RSE disabled: disabled, pl = 0, little endian, eager mode +#define RSC_KERNEL_DISABLED ((RSC_MODE_LY<<RSC_MODE) | (RSC_BE_LITTLE<<RSC_BE)) + + +//VOID +//SwitchStacks ( +// VOID *ContinuationFunction, +// UINTN Parameter, +// UINTN NewTopOfStack, +// UINTN NewBSPStore OPTIONAL +//) +///*++ +// +//Input Arguments +// +// ContinuationFunction - This is a pointer to the PLABEL of the function that should be called once the +// new stack has been created. +// Parameter - The parameter to pass to the continuation function +// NewTopOfStack - This is the new top of the memory stack for ensuing code. This is mandatory and +// should be non-zero +// NewBSPStore - This is the new BSP store for the ensuing code. It is optional on IA-32 and mandatory on Itanium-based platform. +// +//--*/ + +PROCEDURE_ENTRY(SwitchStacks) + + mov r16 = -0x10;; + and r16 = r34, r16;; // get new stack value in R16, 0 the last nibble. + mov r15 = r35;; // Get new BspStore into R15 + mov r13 = r32;; // this is a pointer to the PLABEL of the continuation function. + mov r17 = r33;; // this is the parameter to pass to the continuation function + + alloc r11=0,0,0,0 // Set 0-size frame + ;; + flushrs;; + + mov r21 = RSC_KERNEL_DISABLED // for rse disable + ;; + mov ar.rsc = r21 // turn off RSE + + add sp = r0, r16;; // transfer to the EFI stack + mov ar.bspstore = r15 // switch to EFI BSP + invala // change of ar.bspstore needs invala. + + mov r18 = RSC_KERNEL_LAZ // RSC enabled, Lazy mode + ;; + mov ar.rsc = r18 // turn rse on, in kernel mode + ;; + alloc r11=0,0,1,0;; // alloc 0 outs going to ensuing DXE IPL service + mov out0 = r17 + ld8 r16 = [r13],8;; // r16 = address of continuation function from the PLABEL + ld8 gp = [r13] // gp = gp of continuation function from the PLABEL + mov b6 = r16 + ;; + br.call.sptk.few b0=b6;; // Call the continuation function + ;; +PROCEDURE_EXIT(SwitchStacks) + + diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/asm.h b/EDK/Foundation/Library/Pei/PeiLib/Ipf/asm.h new file mode 100644 index 0000000..2db93d6 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/asm.h @@ -0,0 +1,35 @@ +// +// +// 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: +// +// asm.h +// +// Abstract: +// +// This module contains generic macros for an assembly writer. +// +// +// Revision History +// +#ifndef _ASM_H +#define _ASM_H + +#define TRUE 1 +#define FALSE 0 +#define PROCEDURE_ENTRY(name) .##text; \ + .##type name, @function; \ + .##proc name; \ + name:: + +#define PROCEDURE_EXIT(name) .##endp name + +#endif // _ASM_H diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/efijump.h b/EDK/Foundation/Library/Pei/PeiLib/Ipf/efijump.h new file mode 100644 index 0000000..4a078ce --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/efijump.h @@ -0,0 +1,112 @@ +/*++ + +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: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an IA32 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// NOTE:Set/LongJump needs to have this buffer start +// at 16 byte boundary. Either fix the structure +// which call this buffer or fix inside SetJump/LongJump +// Choosing 1K buffer storage for now +// +typedef struct { + CHAR8 Buffer[1024]; +} EFI_JUMP_BUFFER; + +EFI_STATUS +SetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ) +/*++ + +Routine Description: + + SetJump stores the current register set in the area pointed to +by "save". It returns zero. Subsequent calls to "LongJump" will +restore the registers and return non-zero to the same location. + On entry, r32 contains the pointer to the jmp_buffer + +Arguments: + + This - Calling context + Jump - Jump buffer + +Returns: + + Status code + +--*/ +; + +EFI_STATUS +LongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ) +/*++ + +Routine Description: + + LongJump initializes the register set to the values saved by a +previous 'SetJump' and jumps to the return location saved by that +'SetJump'. This has the effect of unwinding the stack and returning +for a second time to the 'SetJump'. + +Arguments: + + This - Calling context + Jump - Jump buffer + +Returns: + + Status code + +--*/ +; + +VOID +RtPioICacheFlush ( + IN VOID *StartAddress, + IN UINTN SizeInBytes + ) +/*++ + +Routine Description: + + Flushing the CPU instruction cache. + +Arguments: + + StartAddress - Start address to flush + SizeInBytes - Length in bytes to flush + +Returns: + + None + +--*/ +; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/ia_64gen.h b/EDK/Foundation/Library/Pei/PeiLib/Ipf/ia_64gen.h new file mode 100644 index 0000000..8e8d1a5 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/ia_64gen.h @@ -0,0 +1,214 @@ +// +// +// +// 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: ia_64gen.h +// +// +//Abstract: +// +// +// +// +//Revision History +// +// +#ifndef _IA64GEN_H +#define _IA64GEN_H + +#define TT_UNAT 0 +#define C_PSR 0 +#define J_UNAT 0 +#define T_TYPE 0 +#define T_IPSR 0x8 +#define T_ISR 0x10 +#define T_IIP 0x18 +#define T_IFA 0x20 +#define T_IIPA 0x28 +#define T_IFS 0x30 +#define T_IIM 0x38 +#define T_RSC 0x40 +#define T_BSP 0x48 +#define T_BSPSTORE 0x50 +#define T_RNAT 0x58 +#define T_PFS 0x60 +#define T_KBSPSTORE 0x68 +#define T_UNAT 0x70 +#define T_CCV 0x78 +#define T_DCR 0x80 +#define T_PREDS 0x88 +#define T_NATS 0x90 +#define T_R1 0x98 +#define T_GP 0x98 +#define T_R2 0xa0 +#define T_R3 0xa8 +#define T_R4 0xb0 +#define T_R5 0xb8 +#define T_R6 0xc0 +#define T_R7 0xc8 +#define T_R8 0xd0 +#define T_R9 0xd8 +#define T_R10 0xe0 +#define T_R11 0xe8 +#define T_R12 0xf0 +#define T_SP 0xf0 +#define T_R13 0xf8 +#define T_R14 0x100 +#define T_R15 0x108 +#define T_R16 0x110 +#define T_R17 0x118 +#define T_R18 0x120 +#define T_R19 0x128 +#define T_R20 0x130 +#define T_R21 0x138 +#define T_R22 0x140 +#define T_R23 0x148 +#define T_R24 0x150 +#define T_R25 0x158 +#define T_R26 0x160 +#define T_R27 0x168 +#define T_R28 0x170 +#define T_R29 0x178 +#define T_R30 0x180 +#define T_R31 0x188 +#define T_F2 0x1f0 +#define T_F3 0x200 +#define T_F4 0x210 +#define T_F5 0x220 +#define T_F6 0x230 +#define T_F7 0x240 +#define T_F8 0x250 +#define T_F9 0x260 +#define T_F10 0x270 +#define T_F11 0x280 +#define T_F12 0x290 +#define T_F13 0x2a0 +#define T_F14 0x2b0 +#define T_F15 0x2c0 +#define T_F16 0x2d0 +#define T_F17 0x2e0 +#define T_F18 0x2f0 +#define T_F19 0x300 +#define T_F20 0x310 +#define T_F21 0x320 +#define T_F22 0x330 +#define T_F23 0x340 +#define T_F24 0x350 +#define T_F25 0x360 +#define T_F26 0x370 +#define T_F27 0x380 +#define T_F28 0x390 +#define T_F29 0x3a0 +#define T_F30 0x3b0 +#define T_F31 0x3c0 +#define T_FPSR 0x1e0 +#define T_B0 0x190 +#define T_B1 0x198 +#define T_B2 0x1a0 +#define T_B3 0x1a8 +#define T_B4 0x1b0 +#define T_B5 0x1b8 +#define T_B6 0x1c0 +#define T_B7 0x1c8 +#define T_EC 0x1d0 +#define T_LC 0x1d8 +#define J_NATS 0x8 +#define J_PFS 0x10 +#define J_BSP 0x18 +#define J_RNAT 0x20 +#define J_PREDS 0x28 +#define J_LC 0x30 +#define J_R4 0x38 +#define J_R5 0x40 +#define J_R6 0x48 +#define J_R7 0x50 +#define J_SP 0x58 +#define J_F2 0x60 +#define J_F3 0x70 +#define J_F4 0x80 +#define J_F5 0x90 +#define J_F16 0xa0 +#define J_F17 0xb0 +#define J_F18 0xc0 +#define J_F19 0xd0 +#define J_F20 0xe0 +#define J_F21 0xf0 +#define J_F22 0x100 +#define J_F23 0x110 +#define J_F24 0x120 +#define J_F25 0x130 +#define J_F26 0x140 +#define J_F27 0x150 +#define J_F28 0x160 +#define J_F29 0x170 +#define J_F30 0x180 +#define J_F31 0x190 +#define J_FPSR 0x1a0 +#define J_B0 0x1a8 +#define J_B1 0x1b0 +#define J_B2 0x1b8 +#define J_B3 0x1c0 +#define J_B4 0x1c8 +#define J_B5 0x1d0 +#define TRAP_FRAME_LENGTH 0x3d0 +#define C_UNAT 0x28 +#define C_NATS 0x30 +#define C_PFS 0x8 +#define C_BSPSTORE 0x10 +#define C_RNAT 0x18 +#define C_RSC 0x20 +#define C_PREDS 0x38 +#define C_LC 0x40 +#define C_DCR 0x48 +#define C_R1 0x50 +#define C_GP 0x50 +#define C_R4 0x58 +#define C_R5 0x60 +#define C_R6 0x68 +#define C_R7 0x70 +#define C_SP 0x78 +#define C_R13 0x80 +#define C_F2 0x90 +#define C_F3 0xa0 +#define C_F4 0xb0 +#define C_F5 0xc0 +#define C_F16 0xd0 +#define C_F17 0xe0 +#define C_F18 0xf0 +#define C_F19 0x100 +#define C_F20 0x110 +#define C_F21 0x120 +#define C_F22 0x130 +#define C_F23 0x140 +#define C_F24 0x150 +#define C_F25 0x160 +#define C_F26 0x170 +#define C_F27 0x180 +#define C_F28 0x190 +#define C_F29 0x1a0 +#define C_F30 0x1b0 +#define C_F31 0x1c0 +#define C_FPSR 0x1d0 +#define C_B0 0x1d8 +#define C_B1 0x1e0 +#define C_B2 0x1e8 +#define C_B3 0x1f0 +#define C_B4 0x1f8 +#define C_B5 0x200 +#define TT_R2 0x8 +#define TT_R3 0x10 +#define TT_R8 0x18 +#define TT_R9 0x20 +#define TT_R10 0x28 +#define TT_R11 0x30 +#define TT_R14 0x38 + +#endif _IA64GEN_H diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/math.c b/EDK/Foundation/Library/Pei/PeiLib/Ipf/math.c new file mode 100644 index 0000000..9ce7613 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/math.c @@ -0,0 +1,139 @@ +/*++ + +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: + + math.c + +Abstract: + + 64-bit Math worker functions for Intel Itanium(TM) processors. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be left shifted by 32 bits and + returns the shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + Count - Number of times to shift left. + +Returns: + + Value shifted left identified by the Count. + +--*/ +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be right shifted by 32 bits and returns the + shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + Count - Number of times to shift right. + +Returns: + + Value shifted right identified by the Count. + +--*/ +{ + return Operand >> Count; +} + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be multiplied with a 32 bit + value returns 64bit result. + No checking if the result is greater than 64bits + +Arguments: + + Multiplicand - multiplicand + Multiplier - multiplier + +Returns: + + Multiplicand * Multiplier + +--*/ +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be divided with a 32 bit value returns + 64bit result and the Remainder. + N.B. only works for 31bit divisors!! + +Arguments: + + Dividend - dividend + Divisor - divisor + Remainder - buffer for remainder + +Returns: + + Dividend / Divisor + Remainder = Dividend mod Divisor + +--*/ +{ + if (Remainder) { + *Remainder = Dividend % Divisor; + } + + return Dividend / Divisor; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/pioflush.s b/EDK/Foundation/Library/Pei/PeiLib/Ipf/pioflush.s new file mode 100644 index 0000000..0f0d760 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/pioflush.s @@ -0,0 +1,106 @@ +//++ +// 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: +// +// pioflush.s +// +// Abstract: +// +// +// Revision History: +// +//-- + + .file "pioflush.c" + .radix D + .section .text, "ax", "progbits" + .align 32 + .section .pdata, "a", "progbits" + .align 4 + .section .xdata, "a", "progbits" + .align 8 + .section .data, "wa", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .bss, "wa", "nobits" + .align 16 + .section .tls$, "was", "progbits" + .align 16 + .section .sdata, "was", "progbits" + .align 16 + .section .sbss, "was", "nobits" + .align 16 + .section .srdata, "as", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .rtcode, "ax", "progbits" + .align 32 + .type RtPioICacheFlush# ,@function + .global RtPioICacheFlush# +// Function compile flags: /Ogsy + .section .rtcode + +// Begin code for function: RtPioICacheFlush: + .proc RtPioICacheFlush# + .align 32 +RtPioICacheFlush: +// File e:\tmp\pioflush.c + { .mii //R-Addr: 0X00 + alloc r3=2, 0, 0, 0 //11, 00000002H + cmp4.leu p0,p6=32, r33;; //15, 00000020H + (p6) mov r33=32;; //16, 00000020H + } + { .mii //R-Addr: 0X010 + nop.m 0 + zxt4 r29=r33;; //21 + dep.z r30=r29, 0, 5;; //21, 00000005H + } + { .mii //R-Addr: 0X020 + cmp4.eq p0,p7=r0, r30 //21 + shr.u r28=r29, 5;; //19, 00000005H + (p7) adds r28=1, r28;; //22, 00000001H + } + { .mii //R-Addr: 0X030 + nop.m 0 + shl r27=r28, 5;; //25, 00000005H + zxt4 r26=r27;; //25 + } + { .mfb //R-Addr: 0X040 + add r31=r26, r32 //25 + nop.f 0 + nop.b 0 + } +$L143: + { .mii //R-Addr: 0X050 + fc r32 //27 + adds r32=32, r32;; //28, 00000020H + cmp.ltu p14,p15=r32, r31 //29 + } + { .mfb //R-Addr: 0X060 + nop.m 0 + nop.f 0 + (p14) br.cond.dptk.few $L143#;; //29, 880000/120000 + } + { .mmi + sync.i;; + srlz.i + nop.i 0;; + } + { .mfb //R-Addr: 0X070 + nop.m 0 + nop.f 0 + br.ret.sptk.few b0;; //31 + } +// End code for function: + .endp RtPioICacheFlush# +// END diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/processor.c b/EDK/Foundation/Library/Pei/PeiLib/Ipf/processor.c new file mode 100644 index 0000000..9740948 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/processor.c @@ -0,0 +1,118 @@ +/*++ + +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: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include "PeiHob.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +EFI_STATUS +WinNtFlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + SetJump, + LongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + WinNtFlushInstructionCacheFlush +}; + +EFI_STATUS +InstallEfiPeiTransferControl ( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + +EFI_STATUS +WinNtFlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + Start - Start adddress in memory to flush + Length - Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + RtPioICacheFlush ((UINT8 *) Start, (UINTN) Length); + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Ipf/setjmp.s b/EDK/Foundation/Library/Pei/PeiLib/Ipf/setjmp.s new file mode 100644 index 0000000..ee27ca7 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Ipf/setjmp.s @@ -0,0 +1,325 @@ +//++ +// 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: +// +// setjmp.s +// +// Abstract: +// +// Contains an implementation of setjmp and longjmp for the +// Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "setjmp.s" + +#include <asm.h> +#include <ia_64gen.h> + +// int SetJump(struct jmp_buffer save) +// +// Setup a non-local goto. +// +// Description: +// +// SetJump stores the current register set in the area pointed to +// by "save". It returns zero. Subsequent calls to "LongJump" will +// restore the registers and return non-zero to the same location. +// +// On entry, r32 contains the pointer to the jmp_buffer +// + +PROCEDURE_ENTRY(SetJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + add r10 = J_PREDS, r32 // skip Unats & pfs save area + add r11 = J_BSP, r32 + // + // save immediate context + // + mov r2 = ar.bsp // save backing store pointer + mov r3 = pr // save predicates + ;; + // + // save user Unat register + // + mov r16 = ar.lc // save loop count register + mov r14 = ar.unat // save user Unat register + + st8 [r10] = r3, J_LC-J_PREDS + st8 [r11] = r2, J_R4-J_BSP + ;; + st8 [r10] = r16, J_R5-J_LC + st8 [r32] = r14, J_NATS // Note: Unat at the + // beginning of the save area + mov r15 = ar.pfs + ;; + // + // save preserved general registers & NaT's + // + st8.spill [r11] = r4, J_R6-J_R4 + ;; + st8.spill [r10] = r5, J_R7-J_R5 + ;; + st8.spill [r11] = r6, J_SP-J_R6 + ;; + st8.spill [r10] = r7, J_F3-J_R7 + ;; + st8.spill [r11] = sp, J_F2-J_SP + ;; + // + // save spilled Unat and pfs registers + // + mov r2 = ar.unat // save Unat register after spill + ;; + st8 [r32] = r2, J_PFS-J_NATS // save unat for spilled regs + ;; + st8 [r32] = r15 // save pfs + // + // save floating registers + // + stf.spill [r11] = f2, J_F4-J_F2 + stf.spill [r10] = f3, J_F5-J_F3 + ;; + stf.spill [r11] = f4, J_F16-J_F4 + stf.spill [r10] = f5, J_F17-J_F5 + ;; + stf.spill [r11] = f16, J_F18-J_F16 + stf.spill [r10] = f17, J_F19-J_F17 + ;; + stf.spill [r11] = f18, J_F20-J_F18 + stf.spill [r10] = f19, J_F21-J_F19 + ;; + stf.spill [r11] = f20, J_F22-J_F20 + stf.spill [r10] = f21, J_F23-J_F21 + ;; + stf.spill [r11] = f22, J_F24-J_F22 + stf.spill [r10] = f23, J_F25-J_F23 + ;; + stf.spill [r11] = f24, J_F26-J_F24 + stf.spill [r10] = f25, J_F27-J_F25 + ;; + stf.spill [r11] = f26, J_F28-J_F26 + stf.spill [r10] = f27, J_F29-J_F27 + ;; + stf.spill [r11] = f28, J_F30-J_F28 + stf.spill [r10] = f29, J_F31-J_F29 + ;; + stf.spill [r11] = f30, J_FPSR-J_F30 + stf.spill [r10] = f31, J_B0-J_F31 // size of f31 + fpsr + // + // save FPSR register & branch registers + // + mov r2 = ar.fpsr // save fpsr register + mov r3 = b0 + ;; + st8 [r11] = r2, J_B1-J_FPSR + st8 [r10] = r3, J_B2-J_B0 + mov r2 = b1 + mov r3 = b2 + ;; + st8 [r11] = r2, J_B3-J_B1 + st8 [r10] = r3, J_B4-J_B2 + mov r2 = b3 + mov r3 = b4 + ;; + st8 [r11] = r2, J_B5-J_B3 + st8 [r10] = r3 + mov r2 = b5 + ;; + st8 [r11] = r2 + ;; + // + // return + // + mov r8 = r0 // return 0 from setjmp + mov ar.unat = r14 // restore unat + br.ret.sptk b0 + +PROCEDURE_EXIT(SetJump) + + +// +// void LongJump(struct jmp_buffer *) +// +// Perform a non-local goto. +// +// Description: +// +// LongJump initializes the register set to the values saved by a +// previous 'SetJump' and jumps to the return location saved by that +// 'SetJump'. This has the effect of unwinding the stack and returning +// for a second time to the 'SetJump'. +// + +PROCEDURE_ENTRY(LongJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + // + // caching the return value as we do invala in the end + // +/// mov r8 = r33 // return value + mov r8 = 1 // For now return hard coded 1 + + // + // get immediate context + // + mov r14 = ar.rsc // get user RSC conf + add r10 = J_PFS, r32 // get address of pfs + add r11 = J_NATS, r32 + ;; + ld8 r15 = [r10], J_BSP-J_PFS // get pfs + ld8 r2 = [r11], J_LC-J_NATS // get unat for spilled regs + ;; + mov ar.unat = r2 + ;; + ld8 r16 = [r10], J_PREDS-J_BSP // get backing store pointer + mov ar.rsc = r0 // put RSE in enforced lazy + mov ar.pfs = r15 + ;; + + // + // while returning from longjmp the BSPSTORE and BSP needs to be + // same and discard all the registers allocated after we did + // setjmp. Also, we need to generate the RNAT register since we + // did not flushed the RSE on setjmp. + // + mov r17 = ar.bspstore // get current BSPSTORE + ;; + cmp.ltu p6,p7 = r17, r16 // is it less than BSP of +(p6) br.spnt.few .flush_rse + mov r19 = ar.rnat // get current RNAT + ;; + loadrs // invalidate dirty regs + br.sptk.many .restore_rnat // restore RNAT + +.flush_rse: + flushrs + ;; + mov r19 = ar.rnat // get current RNAT + mov r17 = r16 // current BSPSTORE + ;; +.restore_rnat: + // + // check if RNAT is saved between saved BSP and curr BSPSTORE + // + dep r18 = 1,r16,3,6 // get RNAT address + ;; + cmp.ltu p8,p9 = r18, r17 // RNAT saved on RSE + ;; +(p8) ld8 r19 = [r18] // get RNAT from RSE + ;; + mov ar.bspstore = r16 // set new BSPSTORE + ;; + mov ar.rnat = r19 // restore RNAT + mov ar.rsc = r14 // restore RSC conf + + + ld8 r3 = [r11], J_R4-J_LC // get lc register + ld8 r2 = [r10], J_R5-J_PREDS // get predicates + ;; + mov pr = r2, -1 + mov ar.lc = r3 + // + // restore preserved general registers & NaT's + // + ld8.fill r4 = [r11], J_R6-J_R4 + ;; + ld8.fill r5 = [r10], J_R7-J_R5 + ld8.fill r6 = [r11], J_SP-J_R6 + ;; + ld8.fill r7 = [r10], J_F2-J_R7 + ld8.fill sp = [r11], J_F3-J_SP + ;; + // + // restore floating registers + // + ldf.fill f2 = [r10], J_F4-J_F2 + ldf.fill f3 = [r11], J_F5-J_F3 + ;; + ldf.fill f4 = [r10], J_F16-J_F4 + ldf.fill f5 = [r11], J_F17-J_F5 + ;; + ldf.fill f16 = [r10], J_F18-J_F16 + ldf.fill f17 = [r11], J_F19-J_F17 + ;; + ldf.fill f18 = [r10], J_F20-J_F18 + ldf.fill f19 = [r11], J_F21-J_F19 + ;; + ldf.fill f20 = [r10], J_F22-J_F20 + ldf.fill f21 = [r11], J_F23-J_F21 + ;; + ldf.fill f22 = [r10], J_F24-J_F22 + ldf.fill f23 = [r11], J_F25-J_F23 + ;; + ldf.fill f24 = [r10], J_F26-J_F24 + ldf.fill f25 = [r11], J_F27-J_F25 + ;; + ldf.fill f26 = [r10], J_F28-J_F26 + ldf.fill f27 = [r11], J_F29-J_F27 + ;; + ldf.fill f28 = [r10], J_F30-J_F28 + ldf.fill f29 = [r11], J_F31-J_F29 + ;; + ldf.fill f30 = [r10], J_FPSR-J_F30 + ldf.fill f31 = [r11], J_B0-J_F31 ;; + + // + // restore branch registers and fpsr + // + ld8 r16 = [r10], J_B1-J_FPSR // get fpsr + ld8 r17 = [r11], J_B2-J_B0 // get return pointer + ;; + mov ar.fpsr = r16 + mov b0 = r17 + ld8 r2 = [r10], J_B3-J_B1 + ld8 r3 = [r11], J_B4-J_B2 + ;; + mov b1 = r2 + mov b2 = r3 + ld8 r2 = [r10], J_B5-J_B3 + ld8 r3 = [r11] + ;; + mov b3 = r2 + mov b4 = r3 + ld8 r2 = [r10] + ld8 r21 = [r32] // get user unat + ;; + mov b5 = r2 + mov ar.unat = r21 + + // + // invalidate ALAT + // + invala ;; + + br.ret.sptk b0 +PROCEDURE_EXIT(LongJump) + + diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeCoffLoader.c b/EDK/Foundation/Library/Pei/PeiLib/PeCoffLoader.c new file mode 100644 index 0000000..06ada63 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeCoffLoader.c @@ -0,0 +1,1491 @@ +/*++ + +Copyright (c) 2005 - 2011, 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: + + PeCoffLoader.c + +Abstract: + + Tiano PE/COFF loader + +Revision History + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeCoffLoaderEx.h" + +#ifdef EFI_NT_EMULATOR +#include "peilib.h" +#include "EfiHobLib.h" +#include EFI_PPI_DEFINITION (NtLoadAsDll) +#endif + +STATIC +EFI_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr + ); + +STATIC +VOID* +PeCoffLoaderImageAddress ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderUnloadImage ( + IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +#if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE) +VOID +AsmEfiSetBreakSupport ( + IN UINTN LoadAddr + ); +#endif + +EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader = { + PeCoffLoaderGetImageInfo, + PeCoffLoaderLoadImage, + PeCoffLoaderRelocateImage, + PeCoffLoaderUnloadImage +}; + +#ifdef EFI_NT_EMULATOR +EFI_NT_LOAD_AS_DLL_PPI *mPeCoffLoaderWinNtLoadAsDll = NULL; +#endif + +EFI_STATUS +InstallEfiPeiPeCoffLoader ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL **This, + IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi + ) +/*++ + +Routine Description: + + Install PE/COFF loader PPI + +Arguments: + + PeiServices - General purpose services available to every PEIM + + This - Pointer to get Pei PE coff loader protocol as output + + ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + +#ifdef EFI_NT_EMULATOR + // + // For use by PEI Core and Modules + // + if (NULL != PeiServices) { + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiNtLoadAsDllPpiGuid, + 0, + NULL, + &mPeCoffLoaderWinNtLoadAsDll + ); + } else { + // + // Now in SecMain or ERM usage, bind appropriately + // + PEI_ASSERT (PeiServices, (NULL != ThisPpi)); + + mPeCoffLoaderWinNtLoadAsDll = (EFI_NT_LOAD_AS_DLL_PPI *) ThisPpi; + PEI_ASSERT (PeiServices, (NULL != mPeCoffLoaderWinNtLoadAsDll)); + } +#endif + + if (NULL != This) { + *This = &mPeCoffLoader; + } + + return Status; +} + +STATIC +EFI_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr + ) +/*++ + +Routine Description: + + Retrieves the PE or TE Header from a PE/COFF or TE image + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE32, PE32+, or TE header + +Returns: + + EFI_SUCCESS if the PE or TE Header is read, + Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function. + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + UINT16 Magic; + + // + // Read the DOS image header to check for it's existance + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image + // header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + + // + // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much + // data, but that should not hurt anythine. Hdr.Pe32->OptionalHeader.Magic + // determins if this is a PE32 or PE32+ image. The magic is in the same + // location in both images. + // + Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + Hdr.Pe32 + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + // + // Use Signature to figure out if we understand the image format + // + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + ImageContext->IsTeImage = TRUE; + ImageContext->Machine = Hdr.Te->Machine; + ImageContext->ImageType = (UINT16)(Hdr.Te->Subsystem); + ImageContext->ImageSize = 0; + ImageContext->SectionAlignment = 4096; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize; + + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + ImageContext->IsTeImage = FALSE; + ImageContext->Machine = Hdr.Pe32->FileHeader.Machine; + + // + // NOTE: We use Machine to identify PE32/PE32+, instead of Magic. + // It is for backward-compatibility consideration, because + // some system will generate PE32+ image with PE32 Magic. + // + if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC || + Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // PE32 and PE32+ have the same offset for these fields. + // We use PE32 for both PE32 and PE32+ headers here. + // + ImageContext->ImageType = Hdr.Pe32->OptionalHeader.Subsystem; + ImageContext->ImageSize = (UINT64)Hdr.Pe32->OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + + } else { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE; + return EFI_UNSUPPORTED; + } + } else { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE; + return EFI_UNSUPPORTED; + } + + if (!PeCoffLoaderImageFormatSupported (ImageContext->Machine)) { + // + // If the PE/COFF loader does not support the image type return + // unsupported. This library can suport lots of types of images + // this does not mean the user of this library can call the entry + // point of the image. + // + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PeCoffLoaderCheckImageType ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Checks the PE or TE header of a PE/COFF or TE image to determine if it supported + +Arguments: + + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS if the PE/COFF or TE image is supported + EFI_UNSUPPORTED of the PE/COFF or TE image is not supported. + +--*/ +{ + switch (ImageContext->ImageType) { + + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + ImageContext->ImageCodeMemoryType = EfiLoaderCode; + ImageContext->ImageDataMemoryType = EfiLoaderData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + ImageContext->ImageCodeMemoryType = EfiBootServicesCode; + ImageContext->ImageDataMemoryType = EfiBootServicesData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode; + ImageContext->ImageDataMemoryType = EfiRuntimeServicesData; + break; + + default: + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM; + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Retrieves information on a PE/COFF image + +Arguments: + + This - Calling context + + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS if the information on the PE/COFF image was collected. + EFI_UNSUPPORTED of the PE/COFF image is not supported. + Otherwise, the error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + + EFI_INVALID_PARAMETER - ImageContext is NULL. + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; + + if (NULL == ImageContext) { + return EFI_INVALID_PARAMETER; + } + + // + // Assume success + // + ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS; + + Hdr.Union = &HdrData; + Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Verify machine type + // + Status = PeCoffLoaderCheckImageType (ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + + // + // NOTE: We use Machine to identify PE32/PE32+, instead of Magic. + // It is for backward-compatibility consideration, because + // some system will generate PE32+ image with PE32 Magic. + // + if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + ImageContext->ImageAddress = Hdr.Pe32->OptionalHeader.ImageBase; + } else { + // + // Use PE32+ offset + // + ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase; + } + } else { + ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); + } + + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the codeview pointer. + // + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if ((!(ImageContext->IsTeImage)) && ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + // + // Use PE32 to access fields that have same offset in PE32 and PE32+ + // + ImageContext->ImageSize = (UINT64) Hdr.Pe32->OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } + + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = (UINTN)( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + + return EFI_SUCCESS; + } + } + } + } + } else { + // + // Because Te image only extracts base relocations and debug directory entries from + // Pe image and in Te image header there is not a field to describe the imagesize, + // we use the largest VirtualAddress plus Size in each directory entry to describe the imagesize + // + ImageContext->ImageSize = (UINT64) (Hdr.Te->DataDirectory[0].VirtualAddress + Hdr.Te->DataDirectory[0].Size); + if(Hdr.Te->DataDirectory[1].VirtualAddress > Hdr.Te->DataDirectory[0].VirtualAddress) { + ImageContext->ImageSize = (UINT64) (Hdr.Te->DataDirectory[1].VirtualAddress + Hdr.Te->DataDirectory[1].Size); + } + ImageContext->SectionAlignment = 4096; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) Hdr.Te->BaseOfCode - (UINTN) Hdr.Te->StrippedSize; + + DebugDirectoryEntry = &Hdr.Te->DataDirectory[1]; + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER)); + + DebugDirectoryEntryFileOffset = 0; + + for (Index = 0; Index < Hdr.Te->NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - + SectionHeader.VirtualAddress + + SectionHeader.PointerToRawData + + sizeof (EFI_TE_IMAGE_HEADER) - + Hdr.Te->StrippedSize; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + return EFI_SUCCESS; + } + } + } + } + + return EFI_SUCCESS; +} + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ) +/*++ + +Routine Description: + + Converts an image address to the loaded address + +Arguments: + + ImageContext - The context of the image being loaded + + Address - The address to be converted to the loaded address + +Returns: + + NULL if the address can not be converted, otherwise, the converted address + +--*/ +{ + if (Address >= ImageContext->ImageSize) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + + return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address); +} + +EFI_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Relocates a PE/COFF image in memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on the loaded image to relocate + +Returns: + + EFI_SUCCESS if the PE/COFF image was relocated + EFI_LOAD_ERROR if the image is not a valid PE/COFF image + EFI_UNSUPPORTED not support + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + UINT64 *F64; + CHAR8 *FixupData; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; +#ifdef EFI_NT_EMULATOR + VOID *DllEntryPoint; + VOID *ModHandle; + + ModHandle = NULL; +#endif + + if (NULL == ImageContext) { + return EFI_INVALID_PARAMETER; + } + + // + // Assume success + // + ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + return EFI_SUCCESS; + } + + // + // If the destination address is not 0, use that rather than the + // image address as the relocation target. + // + if (ImageContext->DestinationAddress != 0) { + BaseAddress = ImageContext->DestinationAddress; + } else { + BaseAddress = ImageContext->ImageAddress; + } + + if (!(ImageContext->IsTeImage)) { + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + // + // NOTE: We use Machine to identify PE32/PE32+, instead of Magic. + // It is for backward-compatibility consideration, because + // some system will generate PE32+ image with PE32 Magic. + // + if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + Adjust = (UINT64)BaseAddress - Hdr.Pe32->OptionalHeader.ImageBase; + Hdr.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress; + + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + RelocDir = &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } else { + // + // Use PE32+ offset + // + Adjust = (UINT64) BaseAddress - Hdr.Pe32Plus->OptionalHeader.ImageBase; + Hdr.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress; + + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + RelocDir = &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } + + // + // Find the relocation block + // 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. + // + + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC && RelocDir->Size > 0) { + RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoaderImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); + if ((RelocBase == NULL) || (RelocBaseEnd == NULL)) { + // + // If the base start or end address resolved to 0, then fail. + // + return EFI_LOAD_ERROR; + } + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + + ImageContext->EntryPoint = BaseAddress + Hdr.Pe32->OptionalHeader.AddressOfEntryPoint; + } else { + Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress); + Adjust = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->ImageBase); + Hdr.Te->ImageBase = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER)); + + // + // Find the relocation block + // + RelocDir = &Hdr.Te->DataDirectory[0]; + if (RelocDir->Size > 0) { + RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)( + ImageContext->ImageAddress + + RelocDir->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + Hdr.Te->StrippedSize + ); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1); + ImageContext->EntryPoint = Hdr.Te->ImageBase + Hdr.Te->AddressOfEntryPoint; + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } + + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + if (!(ImageContext->IsTeImage)) { + FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress); + + if (FixupBase == NULL) { + // + // If the FixupBase address resolved to 0, then fail. + // + return EFI_LOAD_ERROR; + } + + } else { + FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress + + RelocBase->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + Hdr.Te->StrippedSize + ); + } + + if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) || + (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + + (UINTN)ImageContext->ImageSize)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION; + return EFI_LOAD_ERROR; + } + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16)); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof (UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_DIR64: + // + // For X64 and IPF + // + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64)); + *(UINT64 *)(FixupData) = *F64; + FixupData = FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + // + // Return the same EFI_UNSUPPORTED return code as + // PeCoffLoaderRelocateImageEx() returns if it does not recognize + // the relocation type. + // + ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION; + return EFI_UNSUPPORTED; + + default: + // + // The common code does not handle some of the stranger IPF relocations + // PeCoffLoaderRelocateImageEx () addes support for these complex fixups + // on IPF and is a No-Op on other archtiectures. + // + Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + +#ifdef EFI_NT_EMULATOR + DllEntryPoint = NULL; + ImageContext->ModHandle = NULL; + // + // Load the DLL if it's not an EBC image. + // + if ((ImageContext->PdbPointer != NULL) && + (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) { + Status = mPeCoffLoaderWinNtLoadAsDll->Entry ( + ImageContext->PdbPointer, + &DllEntryPoint, + &ModHandle + ); + + if (!EFI_ERROR (Status) && DllEntryPoint != NULL) { + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint; + ImageContext->ModHandle = ModHandle; + } + } +#endif + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Loads a PE/COFF image into memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on image to load into memory + +Returns: + + EFI_SUCCESS if the PE/COFF image was loaded + EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + EFI_LOAD_ERROR if the image is a runtime driver with no relocations + EFI_INVALID_PARAMETER if the image address is invalid + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN NumberOfSections; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + CHAR8 *MaxEnd; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; +#if (EFI_SPECIFICATION_VERSION >= 0x0002000A) + EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString; + EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; +#endif + + if (NULL == ImageContext) { + return EFI_INVALID_PARAMETER; + } + + // + // Assume success + // + ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context info into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem (&CheckContext, ImageContext, sizeof (EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT)); + + Status = PeCoffLoaderGetImageInfo (This, &CheckContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_SIZE; + return EFI_BUFFER_TOO_SMALL; + } + if (ImageContext->ImageAddress == 0) { + // + // Image cannot be loaded into 0 address. + // + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return EFI_INVALID_PARAMETER; + } + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM; + return EFI_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return EFI_INVALID_PARAMETER; + } + } + // + // Make sure the allocated space has the proper section alignment + // + if (!(ImageContext->IsTeImage)) { + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return EFI_INVALID_PARAMETER; + } + } + // + // Read the entire PE/COFF or TE header into memory + // + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *)(UINTN)ImageContext->ImageAddress + ); + + Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + sizeof(EFI_TE_IMAGE_HEADER) + ); + NumberOfSections = (UINTN) (Hdr.Te->NumberOfSections); + + } + + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + // + // Load each section of the image + // + Section = FirstSection; + for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) { + + // + // Compute sections address + // + Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress); + End = PeCoffLoaderImageAddress ( + ImageContext, + Section->VirtualAddress + Section->Misc.VirtualSize - 1 + ); + if (ImageContext->IsTeImage) { + Base = (CHAR8 *)((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize); + End = (CHAR8 *)((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize); + } + + if (End > MaxEnd) { + MaxEnd = End; + } + // + // If the base start or end address resolved to 0, then fail. + // + if ((Base == NULL) || (End == NULL)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_SECTION_NOT_LOADED; + return EFI_LOAD_ERROR; + } + + // + // Read the section + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + + if (Section->SizeOfRawData) { + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData, + &Size, + Base + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize, + &Size, + Base + ); + } + + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - Size); + } + + // + // Next Section + // + Section += 1; + } + + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + + // + // Get image's entry point + // + if (!(ImageContext->IsTeImage)) { + + // + // NOTE: We use Machine to identify PE32/PE32+, instead of Magic. + // It is for backward-compatibility consideration, because + // some system will generate PE32+ image with PE32 Magic. + // + if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else if (Hdr.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) { + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + // + // Sizes of AddressOfEntryPoint are different so we need to do this safely + // + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress ( + ImageContext, + (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint + ); + + } else { + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) ( + (UINTN)ImageContext->ImageAddress + + (UINTN)Hdr.Te->AddressOfEntryPoint + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN)Hdr.Te->StrippedSize + ); + } + + // + // Determine the size of the fixup data + // + // 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. + // + if (!(ImageContext->IsTeImage)) { + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + } + + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + DirectoryEntry = &Hdr.Te->DataDirectory[0]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview info if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + DebugEntry = PeCoffLoaderImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva + ); + } else { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)( + ImageContext->ImageAddress + + ImageContext->DebugDirectoryEntryRva + + sizeof(EFI_TE_IMAGE_HEADER) - + Hdr.Te->StrippedSize + ); + } + + if (DebugEntry != NULL) { + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + + if (TempDebugEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva); + } else { + ImageContext->CodeView = (VOID *)( + (UINTN)ImageContext->ImageAddress + + (UINTN)TempDebugEntryRva + + (UINTN)sizeof (EFI_TE_IMAGE_HEADER) - + (UINTN) Hdr.Te->StrippedSize + ); + } + + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = DebugEntry->SizeOfData; + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset, + &Size, + ImageContext->CodeView + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize, + &Size, + ImageContext->CodeView + ); + // + // Should we apply fix up to this field according to the size difference between PE and TE? + // Because now we maintain TE header fields unfixed, this field will also remain as they are + // in original PE image. + // + } + + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (*(UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + break; + } + } + } + } + +#if (EFI_SPECIFICATION_VERSION >= 0x0002000A) + // + // Get Image's HII resource section + // + if (!(ImageContext->IsTeImage)) { + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE]; + } else { + // + // Use PE32+ offset + // + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE]; + } + + if (DirectoryEntry->Size != 0) { + Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress); + + if (Base == NULL) { + return EFI_LOAD_ERROR; + } + + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) Base; + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + + for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) { + if (ResourceDirectoryEntry->u1.s.NameIsString) { + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset); + + if (ResourceDirectoryString->Length == 3 && + ResourceDirectoryString->String[0] == L'H' && + ResourceDirectoryString->String[1] == L'I' && + ResourceDirectoryString->String[2] == L'I') { + // + // Resource Type "HII" found + // + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Name + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Language + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + } + } + + // + // Now it ought to be resource Data + // + if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) { + ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (Base + ResourceDirectoryEntry->u2.OffsetToData); + ImageContext->HiiResourceData = (EFI_PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData); + break; + } + } + } + + ResourceDirectoryEntry++; + } + } + } +#endif + +#if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE) + AsmEfiSetBreakSupport ((UINTN)(ImageContext->ImageAddress)); +#endif + + return Status; +} + +EFI_STATUS +EFIAPI +PeCoffLoaderUnloadImage ( + IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Unload a PE/COFF image from memory + +Arguments: + + ImageContext - Contains information on image to load into memory + +Returns: + + EFI_SUCCESS + +--*/ +{ +#ifdef EFI_NT_EMULATOR + // + // Calling Win32 API free library + // + mPeCoffLoaderWinNtLoadAsDll->FreeLibrary (ImageContext->ModHandle); + +#endif + + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLib.c b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.c new file mode 100644 index 0000000..772319f --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.c @@ -0,0 +1,714 @@ +/*++ + +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: + + PeiLib.c + +Abstract: + + PEI Library Functions + +--*/ + +#include "TianoCommon.h" +#include "PeiHob.h" +#include "Pei.h" +#include "PeiLib.h" +#include "EfiCommonLib.h" + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + Set Buffer to zero for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + +Returns: + + None + +--*/ +{ + EfiCommonLibZeroMem (Buffer, Size); +} + +VOID +PeiCopyMem ( + 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 +CopyMem ( + 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); +} + + +BOOLEAN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares two GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = TRUE if Guid1 == Guid2 + = FALSE if Guid1 != Guid2 + +--*/ +{ + if ((((INT32 *) Guid1)[0] - ((INT32 *) Guid2)[0]) == 0) { + if ((((INT32 *) Guid1)[1] - ((INT32 *) Guid2)[1]) == 0) { + if ((((INT32 *) Guid1)[2] - ((INT32 *) Guid2)[2]) == 0) { + if ((((INT32 *) Guid1)[3] - ((INT32 *) Guid2)[3]) == 0) { + return TRUE; + } + } + } + } + + return FALSE; +} + + +EFI_STATUS +EFIAPI +PeiLibPciCfgModify ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PCI_CFG_PPI *PciCfg, + IN PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN SetBits, + IN UINTN ClearBits + ) +/*++ + +Routine Description: + + PCI read-modify-write operations. + + PIWG's PI specification replaces Inte's EFI Specification 1.10. + EFI_PEI_PCI_CFG_PPI defined in Inte's EFI Specification 1.10 is replaced by + EFI_PEI_PCI_CFG2_PPI in PI 1.0. "Modify" function in these two PPI are not + compatibile with each other. + + + For Framework code that make the following call: + + PciCfg->Modify ( + PeiServices, + PciCfg, + Width, + Address, + SetBits, + ClearBits + ); + it will be updated to the following code which call this library API: + PeiLibPciCfgModify ( + PeiServices, + PciCfg, + Width, + Address, + SetBits, + ClearBits + ); + + The + +Arguments: + + PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + PciCfg A pointer to the this pointer of EFI_PEI_PCI_CFG_PPI. + This parameter is unused as a place holder to make + the parameter list identical to PEI_PCI_CFG_PPI_RW. + Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + + Address The physical address of the access. + + SetBits Points to value to bitwise-OR with the read configuration value. + + The size of the value is determined by Width. + + ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + +Returns: + + EFI_SUCCESS The function completed successfully. + + EFI_DEVICE_ERROR There was a problem with the transaction. + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PCI_CFG2_PPI *PciCfg2; + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiPciCfg2PpiGuid, + 0, + NULL, + (VOID **) &PciCfg2 + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + Status = PciCfg2->Modify ( + (CONST EFI_PEI_SERVICES **) PeiServices, + PciCfg2, + (EFI_PEI_PCI_CFG_PPI_WIDTH) Width, + Address, + &SetBits, + &ClearBits + ); + + return Status; +} + +//;;## ...AMI_OVERRIDE... Support PI1.x +#if (PI_SPECIFICATION_VERSION >= 0x00010000) + +VOID * +EFIAPI +ScanGuid ( + IN VOID *Buffer, + IN UINTN Length, + IN EFI_GUID *Guid + ) +/*++ + +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. + +--*/ +{ + EFI_GUID *GuidPtr; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + PEI_ASSERT(PeiServices, (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0)); + PEI_ASSERT(PeiServices, (Length <= (EFI_MAX_ADDRESS - (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 (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} + + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +/*++ + +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 + +**/ +{ + PEI_ASSERT(GetPeiServicesTablePointer() , (Length <= EFI_MAX_ADDRESS - (UINTN)Address + 1)); + return Address; +} + + +EFI_STATUS +EFIAPI +PeiLibFfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindNextVolume. + +Arguments: + + Instance - The Fv Volume Instance. + VolumeHandle - Pointer to the current Fv Volume to search. + +Returns: + EFI_STATUS + +--*/ + +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + return (*PeiServices)->FfsFindNextVolume (PeiServices, Instance, VolumeHandle); +} + +EFI_STATUS +EFIAPI +PeiLibFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindNextFile. + +Arguments: + + 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_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + return (*PeiServices)->FfsFindNextFile (PeiServices, SearchType, FvHandle, FileHandle); +} + + +EFI_STATUS +EFIAPI +PeiLibFfsFindFileByName ( + IN EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindFileByName. + +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_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + return (*PeiServices)->FfsFindFileByName (FileName, VolumeHandle, FileHandle); +} + + + +EFI_STATUS +EFIAPI +PeiLibFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsFindSectionData. + +Arguments: + + 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_STATUS +--*/ +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + return (*PeiServices)->FfsFindSectionData (PeiServices, SectionType, (EFI_PEI_FILE_HANDLE)FfsFileHeader, SectionData); +} + +EFI_STATUS +EFIAPI +PeiLibFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function FfsGetVolumeInfo. + +Arguments: + + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS +--*/ +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + return (*PeiServices)->FfsGetVolumeInfo (VolumeHandle, VolumeInfo); +} + + + +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Build FvHob. + +Arguments: + + BaseAddress - Fv base address. + Length - Fv Length. + +Returns: + NONE. +--*/ +{ + + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME *Hob; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + + // + // Check FV Signature + // + PEI_ASSERT (PeiServices, ((EFI_FIRMWARE_VOLUME_HEADER*)((UINTN)BaseAddress))->Signature == EFI_FVH_SIGNATURE); + + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_FV, + sizeof (EFI_HOB_FIRMWARE_VOLUME), + &Hob + ); + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +VOID +EFIAPI +BuildFvHob2 ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *FvNameGuid, + IN EFI_GUID *FileNameGuid + ) +/*++ + +Routine Description: + + Build FvHob2. + +Arguments: + + BaseAddress - Fv base address. + Length - Fv length. + FvNameGuid - Fv name. + FileNameGuid - File name which contians encapsulated Fv. + +Returns: + NONE. +--*/ +{ + + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + + // + // Check FV Signature + // + PEI_ASSERT (PeiServices, ((EFI_FIRMWARE_VOLUME_HEADER*)((UINTN)BaseAddress))->Signature == EFI_FVH_SIGNATURE); + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_FV2, + sizeof (EFI_HOB_FIRMWARE_VOLUME2), + &Hob + ); + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + CopyMem ((VOID*)&Hob->FvName, FvNameGuid, sizeof(EFI_GUID)); + CopyMem ((VOID*)&Hob->FileName, FileNameGuid, sizeof(EFI_GUID)); +} + +EFI_STATUS +EFIAPI +PeiServicesLocatePpi ( + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + The wrapper of Pei Core Service function LocatePpi. + +Arguments: + + 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_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + return (*PeiServices)->LocatePpi (PeiServices, Guid, Instance, PpiDescriptor, Ppi); +} + + +VOID +EFIAPI +BuildGuidDataHob ( + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +/*++ + +Routine Description: + + Build Guid data Hob. + +Arguments: + + Guid - guid to build data hob. + Data - data to build data hob. + DataLength - the length of data. + +Returns: + NONE +--*/ +{ + VOID *HobData; + EFI_HOB_GUID_TYPE *Hob; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer(); + (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength), + &Hob + ); + CopyMem ((VOID*)&Hob->Name, (VOID*)Guid, sizeof(EFI_GUID)); + + HobData = Hob + 1; + + CopyMem (HobData, Data, DataLength); +} + + +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +/*++ + +Routine Description: + + Allocate Memory. + +Arguments: + + Pages - Pages to allocate. + +Returns: + = Address if successful to allocate memory. + = NULL if fail to allocate memory. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + EFI_PEI_SERVICES **PeiServices; + + if (Pages == 0) { + return NULL; + } + + PeiServices = GetPeiServicesTablePointer(); + Status = (*PeiServices)->AllocatePages (PeiServices, EfiBootServicesData, Pages, &Memory); + if (EFI_ERROR (Status)) { + Memory = 0; + } + return (VOID *) (UINTN) Memory; + +} + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLib.cif b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.cif new file mode 100644 index 0000000..c0d2d20 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.cif @@ -0,0 +1,23 @@ +<component> + name = "PeiLib" + category = ModulePart + LocalRoot = "EDK\Foundation\Library\Pei\PeiLib\" + RefName = "PeiLib" +[files] +"PeiLib.sdl" +"PeiLib.mak" +"Debug.c" +"Decompress.c" +"FindFv.c" +"PeCoffLoader.c" +"PeiLib.c" +"Perf.c" +"Hob\Hob.c" +"Print\Print.c" +"Print\Print.h" +"PeiLib.inf" +[parts] +"PeiLibIA32" +"PeiLibx64" +"PeiLibIPF" +<endComponent> diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLib.inf b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.inf new file mode 100644 index 0000000..d1ee5d5 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.inf @@ -0,0 +1,95 @@ +#/*++ +# +# 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: +# +# PeiLib.inf +# +# Abstract: +# +# Component description file for the PEI library. +# +#--*/ + +[defines] +BASE_NAME = PeiLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + PeiLib.c + PeCoffLoader.c + Decompress.c + Debug.c + Hob\Hob.c + perf.c + print\print.c + print\print.h + FindFv.c + +[sources.ia32] +# ia32\Math.c + ia32\PeCoffLoaderEx.c + ia32\PeCoffLoaderEx.h + ia32\PerformancePrimitives.c + ia32\Processor.c + ia32\ProcessorAsms.Asm + ia32\efijump.h + +[sources.x64] + x64\PeCoffLoaderEx.c + x64\PeCoffLoaderEx.h + x64\PerformancePrimitives.c + x64\Processor.c + x64\ProcessorAsms.Asm + x64\efijump.h + +[sources.ipf] +# ipf\Math.c + ipf\PeCoffLoaderEx.c + ipf\PeCoffLoaderEx.h + ipf\PerformancePrimitives.s + ipf\Processor.c + ipf\EfiJump.h + ipf\SetJmp.s + ipf\Asm.h + ipf\PioFlush.s + ipf\SwitchStack.s + ipf\Ia_64Gen.h + +[libraries.common] + EdkGuidLib + EfiCommonLib + EdkFrameworkPpiLib + +[libraries.ia32] + CpuIA32Lib + +[libraries.x64] + CpuIA32Lib +[includes.common] + $(EDK_SOURCE)\Sample\Platform\Nt32 + $(EDK_SOURCE)\Foundation + $(EDK_SOURCE)\Foundation\Framework + $(EDK_SOURCE)\Foundation\Efi + . + $(EDK_SOURCE)\Foundation\Core\Dxe + $(EDK_SOURCE)\Foundation\Include + $(EDK_SOURCE)\Foundation\Efi\Include + $(EDK_SOURCE)\Foundation\Framework\Include + $(EDK_SOURCE)\Foundation\Include\IndustryStandard + $(EDK_SOURCE)\Foundation\Include\Pei + $(EDK_SOURCE)\Foundation\Library\Pei\Include + $(EDK_SOURCE)\Foundation\Core\Pei\Include + $(EDK_SOURCE)\Foundation\Library\Dxe\Include + $(EDK_SOURCE)\Foundation\Cpu\Pentium\Include + +[nmake.common] + C_STD_INCLUDE= diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLib.mak b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.mak new file mode 100644 index 0000000..5561761 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.mak @@ -0,0 +1,141 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (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/Modules/SharkBayRefCodes/IntelEDK/PeiLib/PeiLib.mak 2 2/24/12 5:44a Jeffch $ +# +# $Revision: 2 $ +# +# $Date: 2/24/12 5:44a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/IntelEDK/PeiLib/PeiLib.mak $ +# +# 2 2/24/12 5:44a Jeffch +# +# 1 1/20/12 4:11a Jeffch +# Create Intel EDK 1117 Patch 7. +# +# 1 9/27/11 6:32a Wesleychen +# Intel EDK initially releases. +# +# 3 9/20/10 10:03p Iminglin +# Libary for IA32 and X64 +# +# 2 9/02/09 3:58a Iminglin +# EIP24919 +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: PeiLib.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +$(PEILIB) : PeiLib + +PEI_LIB_OBJECTS=\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Debug.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Decompress.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\FindFv.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\PeCoffLoader.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\PeiLib.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Perf.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Hob\Hob.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Print\Print.obj + +PEI_LIB_IA32_OBJECTS=\ +$$(BUILD_DIR)\$(PeiLib_DIR)\IA32\PeCoffLoaderEx.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\IA32\PerformancePrimitives.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\IA32\Processor.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\IA32\ProcessorAsms.obj + +PEI_LIB_x64_OBJECTS=\ +$$(BUILD_DIR)\$(PeiLib_DIR)\x64\PeCoffLoaderEx.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\x64\PerformancePrimitives.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\x64\Processor.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\x64\ProcessorAsms.obj + +PEI_LIB_IPF_OBJECTS=\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Ipf\PeCoffLoaderEx.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Ipf\processor.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Ipf\PerformancePrimitives.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Ipf\pioflush.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Ipf\setjmp.obj\ +$$(BUILD_DIR)\$(PeiLib_DIR)\Ipf\SwitchStack.obj + +!IF "$(PROCESSOR)"=="IA32" +PEI_LIB_OBJECTS =$(PEI_LIB_OBJECTS) $(PEI_LIB_IA32_OBJECTS) +!ELSEIF "$(PROCESSOR)"=="x64" +PEI_LIB_PEI_OBJECTS =$(PEI_LIB_OBJECTS) $(PEI_LIB_IA32_OBJECTS) +PEI_LIB_DXE_OBJECTS =$(PEI_LIB_OBJECTS) $(PEI_LIB_x64_OBJECTS) +!ELSEIF "$(PROCESSOR)"=="IPF" +PEI_LIB_OBJECTS =$(PEI_LIB_OBJECTS) $(PEI_LIB_IPF_OBJECTS) +!ENDIF + +!IF "$(PROCESSOR)"=="x64" +PEI_LIB_PORCESSOR_PEI_CIF=$(PeiLib_DIR)\$(@B)IA32.cif +PEI_LIB_PORCESSOR_DXE_CIF=$(PeiLib_DIR)\$(@B)$(PROCESSOR).cif +!ELSE +PEI_LIB_PORCESSOR_CIF=$(PeiLib_DIR)\$(@B)$(PROCESSOR).cif +!ENDIF + +$(BUILD_DIR)\PeiLib.lib : PeiLib + +PeiLib : $(BUILD_DIR)\PeiLib.mak PeiLibBin + +!IF "$(PROCESSOR)"=="x64" +$(BUILD_DIR)\PeiLib.mak : $(PeiLib_DIR)\$(@B).cif $(PeiLib_DIR)\$(@B).mak $(BUILD_RULES) $(PEI_LIB_PORCESSOR_PEI_CIF) $(PEI_LIB_PORCESSOR_DXE_CIF) + $(CIF2MAK) $(PeiLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(PEI_LIB_PORCESSOR_PEI_CIF) $(PEI_LIB_PORCESSOR_DXE_CIF) +!ELSE +$(BUILD_DIR)\PeiLib.mak : $(PeiLib_DIR)\$(@B).cif $(PeiLib_DIR)\$(@B).mak $(BUILD_RULES) $(PEI_LIB_PORCESSOR_CIF) + $(CIF2MAK) $(PeiLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(PEI_LIB_PORCESSOR_CIF) +!ENDIF + +!IF "$(PROCESSOR)"!="IPF" +PeiLibBin : $(CPUIA32LIB) +!ENDIF + +PeiLibBin : $(EDKGUIDLIB) $(EFICOMMONLIB) $(EDKFRAMEWORKPPILIB) +!IF "$(PROCESSOR)"=="x64" + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS)\ + /f $(BUILD_DIR)\PeiLib.mak all\ + "MY_INCLUDES=$(EDK_INCLUDES)"\ + TYPE=LIBRARY "OBJECTS=$(PEI_LIB_DXE_OBJECTS)" + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32\ + /f $(BUILD_DIR)\PeiLib.mak all\ + "MY_INCLUDES=$(EDK_INCLUDES)"\ + TYPE=PEI_LIBRARY "OBJECTS=$(PEI_LIB_PEI_OBJECTS)" +!ELSE + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS)\ + /f $(BUILD_DIR)\PeiLib.mak all\ + "MY_INCLUDES=$(EDK_INCLUDES)"\ + TYPE=PEI_LIBRARY "OBJECTS=$(PEI_LIB_OBJECTS)" +!ENDIF +#********************************************************************** +#********************************************************************** +#** ** +#** (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/EDK/Foundation/Library/Pei/PeiLib/PeiLib.sdl b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.sdl new file mode 100644 index 0000000..ce069ca --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLib.sdl @@ -0,0 +1,31 @@ +TOKEN + Name = "PeiLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PeiLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "PEILIB" + Value = "$$(LIB_BUILD_DIR)\PeiLib.lib" + TokenType = Expression + TargetMAK = Yes +End + +PATH + Name = "PeiLib_DIR" +End + +MODULE + Help = "Includes PeiLib.mak to Project" + File = "PeiLib.mak" +End + +ELINK + Name = "/I$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\$(PROCESSOR)" + Parent = "EDK_INCLUDES" + InvokeOrder = AfterParent +End diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLibIA32.cif b/EDK/Foundation/Library/Pei/PeiLib/PeiLibIA32.cif new file mode 100644 index 0000000..ab7d8c7 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLibIA32.cif @@ -0,0 +1,14 @@ +<component> + name = "PeiLibIA32" + category = ModulePart + LocalRoot = "EDK\Foundation\Library\Pei\PeiLib\" + RefName = "PeiLibIA32" +[files] +"ia32\PeCoffLoaderEx.c" +"ia32\PerformancePrimitives.c" +"ia32\Processor.c" +"ia32\efijump.h" +"ia32\PeCoffLoaderEx.h" +"ia32\ProcessorAsms.Asm" +"ia32\PeiServicePointer.c" +<endComponent> diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLibIPF.cif b/EDK/Foundation/Library/Pei/PeiLib/PeiLibIPF.cif new file mode 100644 index 0000000..d08a710 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLibIPF.cif @@ -0,0 +1,19 @@ +<component> + name = "PeiLibIPF" + category = ModulePart + LocalRoot = "EDK\Foundation\Library\Pei\PeiLib\" + RefName = "PeiLibIPF" +[files] +"Ipf\PeCoffLoaderEx.c" +"Ipf\processor.c" +"Ipf\asm.h" +"Ipf\efijump.h" +"Ipf\ia_64gen.h" +"Ipf\PeCoffLoaderEx.h" +"Ipf\PerformancePrimitives.s" +"Ipf\pioflush.s" +"Ipf\setjmp.s" +"Ipf\SwitchStack.s" +"Ipf\PeiServicePointer.c" +"Ipf\math.c" +<endComponent> diff --git a/EDK/Foundation/Library/Pei/PeiLib/PeiLibx64.cif b/EDK/Foundation/Library/Pei/PeiLib/PeiLibx64.cif new file mode 100644 index 0000000..259109f --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/PeiLibx64.cif @@ -0,0 +1,15 @@ +<component> + name = "PeiLibx64" + category = ModulePart + LocalRoot = "EDK\Foundation\Library\Pei\PeiLib\" + RefName = "PeiLibx64" +[files] +"x64\PeCoffLoaderEx.c" +"x64\PerformancePrimitives.c" +"x64\Processor.c" +"x64\EfiJump.h" +"x64\PeCoffLoaderEx.h" +"x64\ProcessorAsms.Asm" +"x64\PeiServicePointer.c" +"x64\Math.c" +<endComponent> diff --git a/EDK/Foundation/Library/Pei/PeiLib/Perf.c b/EDK/Foundation/Library/Pei/PeiLib/Perf.c new file mode 100644 index 0000000..86b8d62 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Perf.c @@ -0,0 +1,362 @@ +/*++ + +Copyright (c) 2004 - 2012, 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 FPDT performance structures. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiHob.h" +#include "CpuIA32.h" +#include "EfiCommonLib.h" + +#include EFI_GUID_DEFINITION (PeiPerformanceHob) + +#define MSR_PLATFORM_INFO 0xce +#define MAX_NON_TURBO_RATIO_OFFSET 8 +#define MAX_NON_TURBO_RATIO_MASK 0xff +#define LOCAL_APIC_BASE 0xfee00000 +#define APIC_ID_REGISTER 0x20 +#define MSR_EXT_XAPIC_LOGICAL_APIC_ID 0x802 +#define MSR_XAPIC_BASE 0x1b +#define MSR_XAPIC_BASE_MASK 0x0c00 + +#define MAX_FIRMWARE_PERFORMANCE_ENTRIES 80 + +// +// Prototype functions +// +UINT64 +IA32API +EfiReadMsr ( + IN UINT32 Index + ); + +UINT64 GetTimeInNanoSec ( + UINT64 Ticker + ) +/*++ + +Routine Description: + + Internal routine to convert TSC value into nano second value + +Arguments: + + Ticker - OPTIONAL. TSC value supplied by caller function + +Returns: + + UINT64 - returns calculated timer value + +--*/ +{ + UINT64 Tick, pi; + UINT8 Ratio; + + if(Ticker != 0){ + Tick = Ticker; + } else { + Tick = EfiReadTsc(); + } + + pi = EfiReadMsr(MSR_PLATFORM_INFO); + Ratio = (UINT8)( ((UINT32)(UINTN)RShiftU64(pi, MAX_NON_TURBO_RATIO_OFFSET)) & MAX_NON_TURBO_RATIO_MASK); + + return (UINT64)DivU64x32(MultU64x32(Tick, 10), (UINTN)(Ratio), NULL); +} + + +UINT32 GetApicId ( + VOID + ) +/*++ + +Routine Description: + + Internal routine to retrieve current APIC Id + +Arguments: + + None + +Returns: + + UINT32 - returns Apic Id value + +--*/ +{ + BOOLEAN x2ApicEnabled; + UINT32 ApicId; + + x2ApicEnabled = (BOOLEAN)(((EfiReadMsr (MSR_XAPIC_BASE)) & (MSR_XAPIC_BASE_MASK)) == MSR_XAPIC_BASE_MASK); + if (x2ApicEnabled) { + ApicId = (UINT32) EfiReadMsr (MSR_EXT_XAPIC_LOGICAL_APIC_ID); + } else { + ApicId = (UINT8) (*(volatile UINT32 *) (UINTN) (LOCAL_APIC_BASE + APIC_ID_REGISTER) >> 24); + } + + return ApicId; +} + +VOID +PeiPerfMeasureEx ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN UINT16 Identifier, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log an extended timestamp value. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + Identifier - Identifier of the record + + EntryExit - Indicates start or stop measurement + + Value - The TSC value + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor; + PEI_FIRMWARE_PERFORMANCE_HOB *FirmwarePerformanceHob; + PEI_GUID_EVENT_REC *PeiGuidRec; + // + // Locate the Pei Performance Log Hob. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiFirmwarePerformanceGuid, + 0, + &PerfHobDescriptor, + NULL + ); + if (!EFI_ERROR(Status)) { + FirmwarePerformanceHob = (PEI_FIRMWARE_PERFORMANCE_HOB *)(((UINT8 *)(PerfHobDescriptor)) - + ((sizeof(PEI_GUID_EVENT_REC) * (MAX_FIRMWARE_PERFORMANCE_ENTRIES-1)) + + sizeof(PEI_FIRMWARE_PERFORMANCE_HOB) + ) + ); + + // + // return if performance buffer has filled up + // + if (FirmwarePerformanceHob->NumberOfEntries >= MAX_FIRMWARE_PERFORMANCE_ENTRIES) { + return; + } + + PeiGuidRec = &(FirmwarePerformanceHob->GuidEventRecord[FirmwarePerformanceHob->NumberOfEntries]); + (*PeiServices)->SetMem (PeiGuidRec, sizeof(PEI_GUID_EVENT_REC), 0); + + // + // Get the GUID name + // + if (FileHeader != NULL) { + PeiGuidRec->Guid = FileHeader->Name; + } + + // + // Record the time stamp nanosec value. + // + PeiGuidRec->Timestamp = GetTimeInNanoSec(Value); + + // + // Copy the progress ID + // + PeiGuidRec->ProgressID = Identifier; + + // + // Record the APIC Id + // + PeiGuidRec->ApicID = GetApicId(); + + // + // Increment the number of valid log entries. + // + FirmwarePerformanceHob->NumberOfEntries++; + } + + return; +} + +VOID +PeiPerfMeasure ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log a timestamp count. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + EntryExit - Indicates start or stop measurement + + Value - The start time or the stop time + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *Hob; + PEI_FIRMWARE_PERFORMANCE_HOB *FirmwarePerformanceHob; + EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor; + PEI_GUID_EVENT_REC *PeiGuidRec; + // + // Locate the Pei Performance Log Hob. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiFirmwarePerformanceGuid, + 0, + &PerfHobDescriptor, + NULL + ); + + // + // If the Performance Hob was not found, build and install one. + // + if (EFI_ERROR(Status)) { + Status = PeiBuildHobGuid ( + PeiServices, + &gPeiFirmwarePerformanceGuid, + (sizeof(PEI_FIRMWARE_PERFORMANCE_HOB) + + ((MAX_FIRMWARE_PERFORMANCE_ENTRIES-1) * + sizeof(PEI_GUID_EVENT_REC)) + + sizeof(EFI_PEI_PPI_DESCRIPTOR) + ), + &Hob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + FirmwarePerformanceHob = (PEI_FIRMWARE_PERFORMANCE_HOB *)(Hob+1); + FirmwarePerformanceHob->NumberOfEntries = 0; + FirmwarePerformanceHob->Reserved = 0; + + PerfHobDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)((UINT8 *)(FirmwarePerformanceHob+1) + + (sizeof(PEI_GUID_EVENT_REC) * + (MAX_FIRMWARE_PERFORMANCE_ENTRIES-1) + ) + ); + PerfHobDescriptor->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + PerfHobDescriptor->Guid = &gPeiFirmwarePerformanceGuid; + PerfHobDescriptor->Ppi = NULL; + + (*PeiServices)->InstallPpi (PeiServices, PerfHobDescriptor); + ASSERT_PEI_ERROR(PeiServices, Status); + } + + FirmwarePerformanceHob = (PEI_FIRMWARE_PERFORMANCE_HOB *)(((UINT8 *)(PerfHobDescriptor)) - + ((sizeof(PEI_GUID_EVENT_REC) * + (MAX_FIRMWARE_PERFORMANCE_ENTRIES-1) + ) + + sizeof(PEI_FIRMWARE_PERFORMANCE_HOB) + ) + ); + + if (FirmwarePerformanceHob->NumberOfEntries >= MAX_FIRMWARE_PERFORMANCE_ENTRIES) { + return; + } + + PeiGuidRec = &(FirmwarePerformanceHob->GuidEventRecord[FirmwarePerformanceHob->NumberOfEntries]); + (*PeiServices)->SetMem (PeiGuidRec, sizeof(PEI_GUID_EVENT_REC), 0); + + // + // If not NULL pointer, copy the file name + // + if (FileHeader != NULL) { + PeiGuidRec->Guid = FileHeader->Name; + } + + // + // Record the time stamp nanosec value. + // + PeiGuidRec->Timestamp = GetTimeInNanoSec(Value); + + // + // Record the Progress Id based upon token field + // + if (!EfiStrCmp (Token, L"PEIM")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = PEIM_START_ID; + } else { + PeiGuidRec->ProgressID = PEIM_END_ID; + } + } else if (!EfiStrCmp (Token, L"PreMem")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = PREMEM_START_ID; + } else { + PeiGuidRec->ProgressID = PREMEM_END_ID; + } + } else if (!EfiStrCmp (Token, L"DisMem")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = DISMEM_START_ID; + } else { + PeiGuidRec->ProgressID = DISMEM_END_ID; + } + } else if (!EfiStrCmp (Token, L"PostMem")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = POSTMEM_START_ID; + } else { + PeiGuidRec->ProgressID = POSTMEM_END_ID; + } + } else { + return ; + } + // + // Record the APIC Id + // + PeiGuidRec->ApicID = GetApicId(); + + // + // Increment the number of valid log entries. + // + FirmwarePerformanceHob->NumberOfEntries++; + + return; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Print/Print.c b/EDK/Foundation/Library/Pei/PeiLib/Print/Print.c new file mode 100644 index 0000000..3151f2c --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Print/Print.c @@ -0,0 +1,739 @@ +/*++ + +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: + + Print.c + +Abstract: + + Basic Ascii AvSPrintf() function named AvSPrint(). AvSPrint() enables very + simple implemenation of debug prints. + + You can not Print more than PEI_LIB_MAX_PRINT_BUFFER characters at a + time. This makes the implementation very simple. + + AvSPrint format specification has the follwoing form + + %[flags][width]type + + flags: + '-' - Left justify + '+' - Prefix a sign + ' ' - Prefix a blank + ',' - Place commas in numberss + '0' - Prefix for width with zeros + 'l' - UINT64 + 'L' - UINT64 + + width: + '*' - Get width from a UINTN argumnet from the argument list + Decimal number that represents width of print + + type: + 'X' - argument is a UINTN hex number, prefix '0' + 'x' - argument is a hex number + 'd' - argument is a decimal number + 'a' - argument is an ascii string + 'S', 's' - argument is an Unicode string + 'g' - argument is a pointer to an EFI_GUID + 't' - argument is a pointer to an EFI_TIME structure + 'c' - argument is an ascii character + 'r' - argument is EFI_STATUS + '%' - Print a % + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "Print.h" + + +STATIC +CHAR8 * +GetFlagsAndWidth ( + IN CHAR8 *Format, + OUT UINTN *Flags, + OUT UINTN *Width, + IN OUT VA_LIST *Marker + ); + +STATIC +UINTN +ValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ); + +STATIC +UINTN +ValueTomHexStr ( + IN OUT CHAR8 *Buffer, + IN UINT64 Value, + IN UINTN Flags, + IN UINTN Width + ); + +STATIC +UINTN +GuidToString ( + IN EFI_GUID *Guid, + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize + ); + +STATIC +UINTN +TimeToString ( + IN EFI_TIME *Time, + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize + ); + +STATIC +UINTN +EfiStatusToString ( + IN EFI_STATUS Status, + OUT CHAR8 *Buffer, + IN UINTN BufferSize + ); + + +UINTN +ASPrint ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN CONST CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + ASPrint function to process format and place the results in Buffer. + +Arguments: + + Buffer - Ascii buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means no + limit. + + Format - Ascii format string see file header for more details. + + ... - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Return; + VA_LIST Marker; + + VA_START(Marker, Format); + Return = AvSPrint(Buffer, BufferSize, Format, Marker); + VA_END (Marker); + + return Return; +} + + +UINTN +AvSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + AvSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + +Arguments: + + StartOfBuffer - Ascii buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means + no limit. + + FormatString - Ascii format string see file header for more details. + + Marker - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + CHAR8 *Buffer; + CHAR8 *AsciiStr; + CHAR16 *UnicodeStr; + CHAR8 *Format; + UINTN Index; + UINTN Flags; + UINTN Width; + UINT64 Value; + + // + // Process the format string. Stop if Buffer is over run. + // + + Buffer = StartOfBuffer; + Format = (CHAR8 *)FormatString; + for (Index = 0; (*Format != '\0') && (Index < BufferSize); Format++) { + if (*Format != '%') { + if (*Format == '\n') { + // + // If carage return add line feed + // + Buffer[Index++] = '\r'; + } + Buffer[Index++] = *Format; + } else { + + // + // Now it's time to parse what follows after % + // + Format = GetFlagsAndWidth (Format, &Flags, &Width, &Marker); + switch (*Format) { + case 'X': + Flags |= PREFIX_ZERO; + Width = sizeof (UINT64) * 2; + // + // break skiped on purpose + // + case 'x': + if ((Flags & LONG_TYPE) == LONG_TYPE) { + Value = VA_ARG (Marker, UINT64); + } else { + Value = VA_ARG (Marker, UINTN); + Value &= 0xFFFFFFFF; + } + Index += ValueTomHexStr (&Buffer[Index], Value, Flags, Width); + break; + + case 'd': + if ((Flags & LONG_TYPE) == LONG_TYPE) { + Value = VA_ARG (Marker, UINT64); + } else { + Value = (UINTN)VA_ARG (Marker, UINTN); + Value &= 0xFFFFFFFF; + Value = (INT32)Value; + } + Index += ValueToString (&Buffer[Index], Value, Flags, Width); + break; + + case 's': + case 'S': + UnicodeStr = (CHAR16 *)VA_ARG (Marker, CHAR16 *); + if (UnicodeStr == NULL) { + UnicodeStr = L"<null string>"; + } + for ( ;*UnicodeStr != '\0'; UnicodeStr++) { + Buffer[Index++] = (CHAR8)*UnicodeStr; + } + break; + + case 'a': + AsciiStr = (CHAR8 *)VA_ARG (Marker, CHAR8 *); + if (AsciiStr == NULL) { + AsciiStr = "<null string>"; + } + while (*AsciiStr != '\0') { + Buffer[Index++] = *AsciiStr++; + } + break; + + case 'c': + Buffer[Index++] = (CHAR8)VA_ARG (Marker, UINTN); + break; + + case 'g': + Index += GuidToString ( + VA_ARG (Marker, EFI_GUID *), + &Buffer[Index], + BufferSize + ); + break; + + case 't': + Index += TimeToString ( + VA_ARG (Marker, EFI_TIME *), + &Buffer[Index], + BufferSize + ); + break; + + case 'r': + Index += EfiStatusToString ( + VA_ARG (Marker, EFI_STATUS), + &Buffer[Index], + BufferSize + ); + break; + + case '%': + Buffer[Index++] = *Format; + break; + + default: + // + // if the type is unknown print it to the screen + // + Buffer[Index++] = *Format; + } + + } + } + Buffer[Index++] = '\0'; + + return &Buffer[Index] - StartOfBuffer; +} + + + +STATIC +CHAR8 * +GetFlagsAndWidth ( + IN CHAR8 *Format, + OUT UINTN *Flags, + OUT UINTN *Width, + IN OUT VA_LIST *Marker + ) +/*++ + +Routine Description: + + AvSPrint worker function that parses flag and width information from the + Format string and returns the next index into the Format string that needs + to be parsed. See file headed for details of Flag and Width. + +Arguments: + + Format - Current location in the AvSPrint format string. + + Flags - Returns flags + + Width - Returns width of element + + Marker - Vararg list that may be paritally consumed and returned. + +Returns: + + Pointer indexed into the Format string for all the information parsed + by this routine. + +--*/ +{ + UINTN Count; + BOOLEAN Done; + + *Flags = 0; + *Width = 0; + for (Done = FALSE; !Done; ) { + Format++; + + switch (*Format) { + + case '-': *Flags |= LEFT_JUSTIFY; break; + case '+': *Flags |= PREFIX_SIGN; break; + case ' ': *Flags |= PREFIX_BLANK; break; + case ',': *Flags |= COMMA_TYPE; break; + case 'L': + case 'l': *Flags |= LONG_TYPE; break; + + case '*': + *Width = VA_ARG (*Marker, UINTN); + break; + + case '0': + *Flags |= PREFIX_ZERO; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + Count = 0; + do { + Count = (Count * 10) + *Format - '0'; + Format++; + } while ((*Format >= '0') && (*Format <= '9')); + Format--; + *Width = Count; + break; + + default: + Done = TRUE; + } + } + return Format; +} + +static CHAR8 mHexStr[] = { '0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F' }; + +STATIC +UINTN +ValueTomHexStr ( + IN OUT CHAR8 *Buffer, + IN UINT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints a Value as a hex number in Buffer + +Arguments: + + Buffer - Location to place ascii hex string of Value. + + Value - Hex value to convert to a string in Buffer. + + Flags - Flags to use in printing Hex string, see file header for details. + + Width - Width of hex value. + +Returns: + + Number of characters printed. + +--*/ +{ + CHAR8 TempBuffer[30]; + CHAR8 *TempStr; + CHAR8 Prefix; + CHAR8 *BufferPtr; + UINTN Count; + UINTN Index; + + TempStr = TempBuffer; + BufferPtr = Buffer; + + // + // Count starts at one since we will null terminate. Each iteration of the + // loop picks off one nibble. Oh yea TempStr ends up backwards + // + Count = 0; + do { + *(TempStr++) = mHexStr[Value & 0x0f]; + Value = RShiftU64 (Value, 4); + Count++; + } while (Value != 0); + + if (Flags & PREFIX_ZERO) { + Prefix = '0'; + } else if (!(Flags & LEFT_JUSTIFY)) { + Prefix = ' '; + } else { + Prefix = 0x00; + } + for (Index = Count; Index < Width; Index++) { + *(TempStr++) = Prefix; + } + + // + // Reverse temp string into Buffer. + // + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + } + + *BufferPtr = 0; + return Index; +} + +STATIC +UINTN +ValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints a Value as a decimal number in Buffer + +Arguments: + + Buffer - Location to place ascii decimal number string of Value. + + Value - Decimal value to convert to a string in Buffer. + + Flags - Flags to use in printing decimal string, see file header for details. + + Width - Width of hex value. + +Returns: + + Number of characters printed. + +--*/ +{ + CHAR8 TempBuffer[30]; + CHAR8 *TempStr; + CHAR8 *BufferPtr; + UINTN Count; + UINTN Remainder; + + TempStr = TempBuffer; + BufferPtr = Buffer; + Count = 0; + + if (Value < 0) { + *(BufferPtr++) = '-'; + Value = -Value; + Count++; + } + + do { + Value = (INT64)DivU64x32 ((UINT64)Value, 10, &Remainder); + *(TempStr++) = (CHAR8)(Remainder + '0'); + Count++; + if ((Flags & COMMA_TYPE) == COMMA_TYPE) { + if (Count % 3 == 0) { + *(TempStr++) = ','; + } + } + } while (Value != 0); + + // + // Reverse temp string into Buffer. + // + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + } + + *BufferPtr = 0; + return Count; +} + +STATIC +UINTN +GuidToString ( + IN EFI_GUID *Guid, + IN CHAR8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints an EFI_GUID. + +Arguments: + + Guid - Pointer to GUID to print. + + Buffer - Buffe to print Guid into. + + BufferSize - Size of Buffer. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Size; + + Size = ASPrint ( + Buffer, + BufferSize, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (UINTN)Guid->Data1, + (UINTN)Guid->Data2, + (UINTN)Guid->Data3, + (UINTN)Guid->Data4[0], + (UINTN)Guid->Data4[1], + (UINTN)Guid->Data4[2], + (UINTN)Guid->Data4[3], + (UINTN)Guid->Data4[4], + (UINTN)Guid->Data4[5], + (UINTN)Guid->Data4[6], + (UINTN)Guid->Data4[7] + ); + + // + // ASPrint will null terminate the string. The -1 skips the null + // + return Size - 1; +} + + +STATIC +UINTN +TimeToString ( + IN EFI_TIME *Time, + OUT CHAR8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints EFI_TIME. + +Arguments: + + Time - Pointer to EFI_TIME sturcture to print. + + Buffer - Buffer to print Time into. + + BufferSize - Size of Buffer. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Size; + + Size = ASPrint ( + Buffer, + BufferSize, + "%02d/%02d/%04d %02d:%02d", + (UINTN)Time->Month, + (UINTN)Time->Day, + (UINTN)Time->Year, + (UINTN)Time->Hour, + (UINTN)Time->Minute + ); + + // + // ASPrint will null terminate the string. The -1 skips the null + // + return Size - 1; +} + +STATIC +UINTN +EfiStatusToString ( + IN EFI_STATUS Status, + OUT CHAR8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints EFI_STATUS as a string. If string is + not known a hex value will be printed. + +Arguments: + + Status - EFI_STATUS sturcture to print. + + Buffer - Buffer to print EFI_STATUS message string into. + + BufferSize - Size of Buffer. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Size; + CHAR8 *Desc; + + if (Status == EFI_SUCCESS) { + Desc = "Success"; + } else if (Status == EFI_LOAD_ERROR) { + Desc = "Load Error"; + } else if (Status == EFI_INVALID_PARAMETER) { + Desc = "Invalid Parameter"; + } else if (Status == EFI_UNSUPPORTED) { + Desc = "Unsupported"; + } else if (Status == EFI_BAD_BUFFER_SIZE) { + Desc = "Bad Buffer Size"; + } else if (Status == EFI_BUFFER_TOO_SMALL) { + Desc = "Buffer Too Small"; + } else if (Status == EFI_NOT_READY) { + Desc = "Not Ready"; + } else if (Status == EFI_DEVICE_ERROR) { + Desc = "Device Error"; + } else if (Status == EFI_WRITE_PROTECTED) { + Desc = "Write Protected"; + } else if (Status == EFI_OUT_OF_RESOURCES) { + Desc = "Out of Resources"; + } else if (Status == EFI_VOLUME_CORRUPTED) { + Desc = "Volume Corrupt"; + } else if (Status == EFI_VOLUME_FULL) { + Desc = "Volume Full"; + } else if (Status == EFI_NO_MEDIA) { + Desc = "No Media"; + } else if (Status == EFI_MEDIA_CHANGED) { + Desc = "Media changed"; + } else if (Status == EFI_NOT_FOUND) { + Desc = "Not Found"; + } else if (Status == EFI_ACCESS_DENIED) { + Desc = "Access Denied"; + } else if (Status == EFI_NO_RESPONSE) { + Desc = "No Response"; + } else if (Status == EFI_NO_MAPPING) { + Desc = "No mapping"; + } else if (Status == EFI_TIMEOUT) { + Desc = "Time out"; + } else if (Status == EFI_NOT_STARTED) { + Desc = "Not started"; + } else if (Status == EFI_ALREADY_STARTED) { + Desc = "Already started"; + } else if (Status == EFI_ABORTED) { + Desc = "Aborted"; + } else if (Status == EFI_ICMP_ERROR) { + Desc = "ICMP Error"; + } else if (Status == EFI_TFTP_ERROR) { + Desc = "TFTP Error"; + } else if (Status == EFI_PROTOCOL_ERROR) { + Desc = "Protocol Error"; + } else if (Status == EFI_WARN_UNKNOWN_GLYPH) { + Desc = "Warning Unknown Glyph"; + } else if (Status == EFI_WARN_DELETE_FAILURE) { + Desc = "Warning Delete Failure"; + } else if (Status == EFI_WARN_WRITE_FAILURE) { + Desc = "Warning Write Failure"; + } else if (Status == EFI_WARN_BUFFER_TOO_SMALL) { + Desc = "Warning Buffer Too Small"; + } else { + Desc = NULL; + } + // + // If we found a match, copy the message to the user's buffer. Otherwise + // sprint the hex status code to their buffer. + // + if (Desc != NULL) { + Size = ASPrint (Buffer, BufferSize, "%a", Desc); + } else { + Size = ASPrint (Buffer, BufferSize, "%X", Status); + } + return Size - 1; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/Print/Print.h b/EDK/Foundation/Library/Pei/PeiLib/Print/Print.h new file mode 100644 index 0000000..4d8b8df --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Print/Print.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: + + Print.h + +Abstract: + + Private data for Print.c + +--*/ + +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#define LEFT_JUSTIFY 0x01 +#define PREFIX_SIGN 0x02 +#define PREFIX_BLANK 0x04 +#define COMMA_TYPE 0x08 +#define LONG_TYPE 0x10 +#define PREFIX_ZERO 0x20 + +// +// Largest number of characters that can be printed out. +// +#define PEI_LIB_MAX_PRINT_BUFFER (80 * 4) + +#include "EfiCommonLib.h" +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/PeCoffLoaderEx.c b/EDK/Foundation/Library/Pei/PeiLib/ia32/PeCoffLoaderEx.c new file mode 100644 index 0000000..4eee1c5 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/PeCoffLoaderEx.c @@ -0,0 +1,93 @@ +/*++ + +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: + + PeCoffLoaderEx.c + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + +#include "TianoCommon.h" +#include "EfiImage.h" + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - relocate unsupported + +--*/ +{ + return EFI_UNSUPPORTED; +} + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +{ + if ((Machine == EFI_IMAGE_MACHINE_IA32) || (Machine == EFI_IMAGE_MACHINE_X64) || + (Machine == EFI_IMAGE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} + diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/PeCoffLoaderEx.h b/EDK/Foundation/Library/Pei/PeiLib/ia32/PeCoffLoaderEx.h new file mode 100644 index 0000000..a83282d --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/PeCoffLoaderEx.h @@ -0,0 +1,85 @@ +/*++ + +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: + + PeCoffLoaderEx.h + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - relocate unsupported + +--*/ +; + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/PeiServicePointer.c b/EDK/Foundation/Library/Pei/PeiLib/ia32/PeiServicePointer.c new file mode 100644 index 0000000..162415c --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/PeiServicePointer.c @@ -0,0 +1,153 @@ +/*++ + +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: + + PeiServicePointer.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" +#include "PeiLib.h" + +//;;## ...AMI_ADD FILE... Support PI1.x +#if (PI_SPECIFICATION_VERSION >= 0x00010000) + +#ifdef EFI_NT_EMULATOR +EFI_PEI_SERVICES **gPeiServices; +#endif + + +VOID +SetPeiServicesTablePointer ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Save PeiService pointer so that it can be retrieved anywhere. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + PhyscialAddress - The physcial address of variable PeiServices. + +Returns: + NONE + +--*/ +{ + +#ifdef EFI_NT_EMULATOR + + // + // For NT32, set EFI_PEI_SERVICES** to global variable. + // + gPeiServices = PeiServices; +#else + + // + // For X86 processor,the EFI_PEI_SERVICES** is stored in the + // 4 bytes immediately preceding the Interrupt Descriptor Table. + // + UINTN IdtBaseAddress; + IdtBaseAddress = (UINTN)ReadIdtBase(); + *(UINTN*)(IdtBaseAddress - 4) = (UINTN)PeiServices; + +#endif +} + + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ) +/*++ + +Routine Description: + + Get PeiService pointer. + +Arguments: + + NONE. + +Returns: + The direct pointer to PeiServiceTable. + +--*/ +{ + EFI_PEI_SERVICES **PeiServices; + +#ifdef EFI_NT_EMULATOR + + // + // For NT32, set EFI_PEI_SERVICES** to global variable. + // + PeiServices = gPeiServices; +#else + + // + // For X86 processor,the EFI_PEI_SERVICES** is stored in the + // 4 bytes immediately preceding the Interrupt Descriptor Table. + // + UINTN IdtBaseAddress; + IdtBaseAddress = (UINTN)ReadIdtBase(); + PeiServices = (EFI_PEI_SERVICES **)(UINTN)(*(UINTN*)(IdtBaseAddress - 4)); +#endif + return PeiServices; +} + + +VOID +MigrateIdtTable ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Migrate IDT from CAR to real memory where preceded with 4 bytes for + storing PeiService pointer. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + +Returns: + + NONE. + +--*/ +{ +#ifndef EFI_NT_EMULATOR + UINT16 IdtEntrySize; + UINTN OldIdtBase; + UINTN Size; + VOID *NewIdtBase; + EFI_STATUS Status; + + IdtEntrySize = ReadIdtLimit(); + OldIdtBase = ReadIdtBase(); + Size = sizeof(PEI_IDT_TABLE) + (IdtEntrySize + 1); + Status = (*PeiServices)->AllocatePool (PeiServices, Size, &NewIdtBase); + ASSERT_PEI_ERROR (PeiServices, Status); + (*PeiServices)->CopyMem ((VOID*)((UINTN)NewIdtBase + sizeof(PEI_IDT_TABLE)), (VOID*)OldIdtBase, (IdtEntrySize + 1)); + SetIdtBase(((UINTN)NewIdtBase + sizeof(PEI_IDT_TABLE)), IdtEntrySize); + SetPeiServicesTablePointer(PeiServices); +#endif +} + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/PerformancePrimitives.c b/EDK/Foundation/Library/Pei/PeiLib/ia32/PerformancePrimitives.c new file mode 100644 index 0000000..992160a --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/PerformancePrimitives.c @@ -0,0 +1,47 @@ +/*++ + +Copyright 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: + + PerformancePrimitives.c + +Abstract: + + Support for Performance library + +--*/ + +#include "TianoCommon.h" +#include "CpuIA32.h" + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ) +/*++ + +Routine Description: + + Get timer value. + +Arguments: + + TimerValue - Pointer to the returned timer value + +Returns: + + EFI_SUCCESS - Successfully got timer value + +--*/ +{ + *TimerValue = EfiReadTsc (); + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/Processor.c b/EDK/Foundation/Library/Pei/PeiLib/ia32/Processor.c new file mode 100644 index 0000000..fcdd4bf --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/Processor.c @@ -0,0 +1,140 @@ +/*++ + +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: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// Prototypes +// +EFI_STATUS +EFIAPI +TransferControlSetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +TransferControlLongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +// +// Table declarations +// +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + TransferControlSetJump, + TransferControlLongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + FlushInstructionCacheFlush +}; + + +EFI_STATUS +InstallEfiPeiTransferControl ( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + In the case of IA32, this flushing is not necessary and is thus not implemented. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + Start - Start adddress in memory to flush + Length - Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/ProcessorAsms.Asm b/EDK/Foundation/Library/Pei/PeiLib/ia32/ProcessorAsms.Asm new file mode 100644 index 0000000..86f4606 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/ProcessorAsms.Asm @@ -0,0 +1,223 @@ +; +; 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: +; +; ProcessorAsms.Asm +; +; Abstract: +; This is separated from processor.c to allow this functions to be built with /O1 +; +; Notes: +; - Masm uses "This", "ebx", etc as a directive. +; - H2INC is still not embedded in our build process so I translated the struc manually. +; - Unreferenced variables/arguments (This, NewBsp, NewStack) were causing compile errors and +; did not know of "pragma" mechanism in MASM and I did not want to reduce the warning level. +; Instead, I did a dummy referenced. +; + + .686P + .MMX + .MODEL SMALL + .CODE + +EFI_SUCCESS equ 0 +EFI_WARN_RETURN_FROM_LONG_JUMP equ 5 + +; +; Generated by h2inc run manually +; +_EFI_JUMP_BUFFER STRUCT 2t +_ebx DWORD ? +_esi DWORD ? +_edi DWORD ? +_ebp DWORD ? +_esp DWORD ? +_eip DWORD ? +_EFI_JUMP_BUFFER ENDS + +EFI_JUMP_BUFFER TYPEDEF _EFI_JUMP_BUFFER + +TransferControlSetJump PROTO C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + +TransferControlLongJump PROTO C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + +SwitchStacks PROTO C \ + EntryPoint:PTR DWORD, \ + Parameter:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + +SwitchIplStacks PROTO C \ + EntryPoint:PTR DWORD, \ + Parameter1:DWORD, \ + Parameter2:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + +; +;Routine Description: +; +; This routine implements the IA32 variant of the SetJump call. Its +; responsibility is to store system state information for a possible +; subsequent LongJump. +; +;Arguments: +; +; Pointer to CPU context save buffer. +; +;Returns: +; +; EFI_SUCCESS +; +TransferControlSetJump PROC C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + + mov eax, _This + mov ecx, Jump + mov (EFI_JUMP_BUFFER PTR [ecx])._ebx, ebx + mov (EFI_JUMP_BUFFER PTR [ecx])._esi, esi + mov (EFI_JUMP_BUFFER PTR [ecx])._edi, edi + mov eax, [ebp] + mov (EFI_JUMP_BUFFER PTR [ecx])._ebp, eax + lea eax, [ebp+4] + mov (EFI_JUMP_BUFFER PTR [ecx])._esp, eax + mov eax, [ebp+4] + mov (EFI_JUMP_BUFFER PTR [ecx])._eip, eax + mov eax, EFI_SUCCESS + + ret + +TransferControlSetJump ENDP + +; +; Routine Description: +; +; This routine implements the IA32 variant of the LongJump call. Its +; responsibility is restore the system state to the Context Buffer and +; pass control back. +; +; Arguments: +; +; Pointer to CPU context save buffer. +; +; Returns: +; +; EFI_WARN_RETURN_FROM_LONG_JUMP +; + +TransferControlLongJump PROC C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + + push ebx + push esi + push edi + + mov eax, _This + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov eax, EFI_WARN_RETURN_FROM_LONG_JUMP + mov ecx, Jump + mov ebx, (EFI_JUMP_BUFFER PTR [ecx])._ebx + mov esi, (EFI_JUMP_BUFFER PTR [ecx])._esi + mov edi, (EFI_JUMP_BUFFER PTR [ecx])._edi + mov ebp, (EFI_JUMP_BUFFER PTR [ecx])._ebp + mov esp, (EFI_JUMP_BUFFER PTR [ecx])._esp + add esp, 4 ;pop the eip + jmp DWORD PTR (EFI_JUMP_BUFFER PTR [ecx])._eip + mov eax, EFI_WARN_RETURN_FROM_LONG_JUMP + + pop edi + pop esi + pop ebx + ret + +TransferControlLongJump ENDP + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter +; Parameter - Parameter to pass in +; NewStack - New Location of the stack +; NewBsp - New BSP +; +; Returns: +; +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchStacks PROC C \ + EntryPoint:PTR DWORD, \ + Parameter:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + + push ebx + mov eax, NewBsp + mov ebx, Parameter + mov ecx, EntryPoint + mov eax, NewStack + mov esp, eax + push ebx + push 0 + jmp ecx + + pop ebx + ret + +SwitchStacks ENDP + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter +; Parameter1/Parameter2 - Parameter to pass in +; NewStack - New Location of the stack +; NewBsp - New BSP +; +; Returns: +; +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchIplStacks PROC C \ + EntryPoint:PTR DWORD, \ + Parameter1:DWORD, \ + Parameter2:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + + push ebx + mov eax, NewBsp + mov ebx, Parameter1 + mov edx, Parameter2 + mov ecx, EntryPoint + mov eax, NewStack + mov esp, eax + + push edx + push ebx + call ecx + + pop ebx + ret + +SwitchIplStacks ENDP + + END + diff --git a/EDK/Foundation/Library/Pei/PeiLib/ia32/efijump.h b/EDK/Foundation/Library/Pei/PeiLib/ia32/efijump.h new file mode 100644 index 0000000..d676f88 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/ia32/efijump.h @@ -0,0 +1,34 @@ +/*++ + +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: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an IA32 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +typedef struct { + UINT32 ebx; + UINT32 esi; + UINT32 edi; + UINT32 ebp; + UINT32 esp; + UINT32 eip; +} EFI_JUMP_BUFFER; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/EfiJump.h b/EDK/Foundation/Library/Pei/PeiLib/x64/EfiJump.h new file mode 100644 index 0000000..61f371f --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/EfiJump.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 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: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an x64 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + UINT64 Rdi; + UINT64 Rsi; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT32 MxCsr; + UINT8 XmmBuffer[160]; // XMM6-XMM15 +} EFI_JUMP_BUFFER; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/Math.c b/EDK/Foundation/Library/Pei/PeiLib/x64/Math.c new file mode 100644 index 0000000..968bf26 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/Math.c @@ -0,0 +1,117 @@ +/*++ + +Copyright (c) 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: + + Math.c + +Abstract: + + 64-bit Math worker functions for x64 + +--*/ + +#include "Efi.h" +#include "Pei.h" +#include "PeiLib.h" + + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be left shifted by 32 bits and returns the + shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + + Count - Number of times to shift left. + +Returns: + + Value shifted left identified by the Count. + +--*/ +{ + return Operand << Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be multiplied with a 32 bit value returns + 64bit result. + No checking if the result is greater than 64bits + +Arguments: + + Multiplicand - + + Multiplier - + +Returns: + + Multiplicand * Multiplier + +--*/ +{ + return Multiplicand * Multiplier; +} +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be divided with a 32 bit value returns + 64bit result and the Remainder. + +Arguments: + + Dividend - + + Divisor - + + Remainder - + +Returns: + + Dividend / Divisor + Remainder = Dividend mod Divisor + +N.B. only works for 31bit divisors!! + +--*/ +{ + return Dividend/Divisor; +} + diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/PeCoffLoaderEx.c b/EDK/Foundation/Library/Pei/PeiLib/x64/PeCoffLoaderEx.c new file mode 100644 index 0000000..1036f43 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/PeCoffLoaderEx.c @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2005 - 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: + + PeCoffLoaderEx.c + +Abstract: + + x64 Specific relocation fixups + +Revision History + +--*/ + +#include "TianoCommon.h" +#include "EfiImage.h" + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + Performs an x64 specific relocation fixup + +Arguments: + Reloc - Pointer to the relocation record + Fixup - Pointer to the address to fix up + FixupData - Pointer to a buffer to log the fixups + Adjust - The offset to adjust the fixup + +Returns: + EFI_UNSUPPORTED - relocate unsupported + +--*/ +{ + return EFI_UNSUPPORTED; +} + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +{ + if ((Machine == EFI_IMAGE_MACHINE_IA32) || (Machine == EFI_IMAGE_MACHINE_X64) || + (Machine == EFI_IMAGE_MACHINE_EBC)) { + return TRUE; + } + + return FALSE; +} diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/PeCoffLoaderEx.h b/EDK/Foundation/Library/Pei/PeiLib/x64/PeCoffLoaderEx.h new file mode 100644 index 0000000..a3f78e0 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/PeCoffLoaderEx.h @@ -0,0 +1,85 @@ +/*++ + +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: + + PeCoffLoaderEx.h + +Abstract: + + x64 Specific relocation fixups + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an x64 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - relocate unsupported + +--*/ +; + +BOOLEAN +PeCoffLoaderImageFormatSupported ( + IN UINT16 Machine + ) +/*++ +Routine Description: + + Returns TRUE if the machine type of PE/COFF image is supported. Supported + does not mean the image can be executed it means the PE/COFF loader supports + loading and relocating of the image type. It's up to the caller to support + the entry point. + + This function implies the basic PE/COFF loader/relocator supports IA32, EBC, + & X64 images. Calling the entry point in a correct mannor is up to the + consumer of this library. + +Arguments: + + Machine - Machine type from the PE Header. + +Returns: + + TRUE - if this PE/COFF loader can load the image + FALSE - if this PE/COFF loader cannot load the image + +--*/ +; + +#endif diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/PeiServicePointer.c b/EDK/Foundation/Library/Pei/PeiLib/x64/PeiServicePointer.c new file mode 100644 index 0000000..8797fb0 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/PeiServicePointer.c @@ -0,0 +1,99 @@ +/*++ + +Copyright 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: + + PeiServicePointer.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "PeiApi.h" + +//;;## ...AMI_ADD FILE... Support PI1.x + +#if (PI_SPECIFICATION_VERSION >= 0x00010000) + +VOID +SetPeiServicesTablePointer ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Save PeiService pointer so that it can be retrieved anywhere. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + PhyscialAddress - The physcial address of variable PeiServices. + +Returns: + NONE + +--*/ +{ + return; +} + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ) +/*++ + +Routine Description: + + Get PeiService pointer. + +Arguments: + + NONE. + +Returns: + The direct pointer to PeiServiceTable. + +--*/ +{ + return NULL; +} + + +VOID +MigrateIdtTable ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Migrate IDT from CAR to real memory where preceded with 4 bytes for + storing PeiService pointer. + +Arguments: + + PeiServices - The direct pointer to PeiServiceTable. + +Returns: + + NONE. + +--*/ +{ + return; +} + +#endif + diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/PerformancePrimitives.c b/EDK/Foundation/Library/Pei/PeiLib/x64/PerformancePrimitives.c new file mode 100644 index 0000000..7517860 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/PerformancePrimitives.c @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 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: + + PerformancePrimitives.c + +Abstract: + + Support for Performance library + +--*/ + +#include "TianoCommon.h" +#include "CpuIA32.h" + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ) +{ + *TimerValue = EfiReadTsc (); + return EFI_SUCCESS; +} + diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/Processor.c b/EDK/Foundation/Library/Pei/PeiLib/x64/Processor.c new file mode 100644 index 0000000..749a3b4 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/Processor.c @@ -0,0 +1,149 @@ +/*++ + +Copyright 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: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// Prototypes +// +EFI_STATUS +EFIAPI +TransferControlSetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +TransferControlLongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +// +// Table declarations +// +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + TransferControlSetJump, + TransferControlLongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + FlushInstructionCacheFlush +}; + + +EFI_STATUS +EFIAPI +InstallEfiPeiTransferControl( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + This - Pointer to transfer control mechanism. + +--*/ +{ + *This = &mTransferControl; + mTransferControl.SetJump = TransferControlSetJump; + mTransferControl.LongJump = TransferControlLongJump; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + This - Pointer to flush instruction cache mechanism. + +--*/ +{ + *This = &mFlushInstructionCache; + mFlushInstructionCache.Flush = FlushInstructionCacheFlush; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + In the case of IA32, this flushing is not necessary and is thus not implemented. + +Arguments: + + Pointer to CPU Architectural Protocol interface + Start adddress in memory to flush + Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} + diff --git a/EDK/Foundation/Library/Pei/PeiLib/x64/ProcessorAsms.Asm b/EDK/Foundation/Library/Pei/PeiLib/x64/ProcessorAsms.Asm new file mode 100644 index 0000000..ebd8b03 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/x64/ProcessorAsms.Asm @@ -0,0 +1,186 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2005 - 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: +; ProcessorAsms.Asm +; +; Abstract: +; This is separated from processor.c to allow this functions to be built with /O1 +; +; +;------------------------------------------------------------------------------ + +text SEGMENT + + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter // rcx +; Parameter - Parameter to pass in // rdx +; NewStack - New Location of the stack // r8 +; NewBsp - New BSP // r9 - not used +; +; Returns: +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchStacks PROC PUBLIC + + ; Adjust stack for + ; 1) leave 4 registers space + ; 2) let it 16 bytes aligned after call + sub r8, 20h + and r8w, 0fff0h ; do not assume 16 bytes aligned + + mov rsp, r8 ; rsp = NewStack + mov r10, rcx ; save EntryPoint + mov rcx, rdx ; Arg1 = Parameter + call r10 ; r10 = copy of EntryPoint + ; + ; no ret as we have a new stack and we jumped to the new location + ; + ret + +SwitchStacks ENDP + + +EFI_SUCCESS equ 0 +EFI_WARN_RETURN_FROM_LONG_JUMP equ 5 + +; +; Generated by h2inc run manually +; +_EFI_JUMP_BUFFER STRUCT 2t +_rbx QWORD ? +_rsp QWORD ? +_rbp QWORD ? +_rdi QWORD ? +_rsi QWORD ? +_r10 QWORD ? +_r11 QWORD ? +_r12 QWORD ? +_r13 QWORD ? +_r14 QWORD ? +_r15 QWORD ? +_rip QWORD ? +_MxCsr DWORD ? +_XmmBuffer DB 160 DUP (?) +_EFI_JUMP_BUFFER ENDS + +EFI_JUMP_BUFFER TYPEDEF _EFI_JUMP_BUFFER + + +; +;Routine Description: +; +; This routine implements the x64 variant of the SetJump call. Its +; responsibility is to store system state information for a possible +; subsequent LongJump. +; +;Arguments: +; +; Pointer to CPU context save buffer. +; +;Returns: +; +; EFI_SUCCESS +; +; EFI_STATUS +; EFIAPI +; TransferControlLongJump ( +; IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, +; IN EFI_JUMP_BUFFER *Jump +; ); +; +; rcx - *This +; rdx - JumpBuffer +; +PUBLIC TransferControlSetJump +TransferControlSetJump PROC + mov (EFI_JUMP_BUFFER PTR [rdx])._rbx, rbx + mov (EFI_JUMP_BUFFER PTR [rdx])._rsp, rsp + mov (EFI_JUMP_BUFFER PTR [rdx])._rbp, rbp + mov (EFI_JUMP_BUFFER PTR [rdx])._rdi, rdi + mov (EFI_JUMP_BUFFER PTR [rdx])._rsi, rsi + mov (EFI_JUMP_BUFFER PTR [rdx])._r10, r10 + mov (EFI_JUMP_BUFFER PTR [rdx])._r11, r11 + mov (EFI_JUMP_BUFFER PTR [rdx])._r12, r12 + mov (EFI_JUMP_BUFFER PTR [rdx])._r13, r13 + mov (EFI_JUMP_BUFFER PTR [rdx])._r14, r14 + mov (EFI_JUMP_BUFFER PTR [rdx])._r15, r15 + ; save non-volatile fp registers + stmxcsr (EFI_JUMP_BUFFER PTR [rdx])._MxCsr + lea rax, (EFI_JUMP_BUFFER PTR [rdx])._XmmBuffer + movdqu [rax], xmm6 + movdqu [rax + 10h], xmm7 + movdqu [rax + 20h], xmm8 + movdqu [rax + 30h], xmm9 + movdqu [rax + 40h], xmm10 + movdqu [rax + 50h], xmm11 + movdqu [rax + 60h], xmm12 + movdqu [rax + 70h], xmm13 + movdqu [rax + 80h], xmm14 + movdqu [rax + 90h], xmm15 + mov rax, QWORD PTR [rsp+0] + mov (EFI_JUMP_BUFFER PTR [rdx])._rip, rax + mov rax, EFI_SUCCESS + ret + +TransferControlSetJump ENDP + +; +; EFI_STATUS +; EFIAPI +; TransferControlLongJump ( +; IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, // rcx +; IN EFI_JUMP_BUFFER *Jump // rdx +; ); +; +; +PUBLIC TransferControlLongJump +TransferControlLongJump PROC + ; load non-volatile fp registers + ldmxcsr (EFI_JUMP_BUFFER PTR [rdx])._MxCsr + lea rax, (EFI_JUMP_BUFFER PTR [rdx])._XmmBuffer + movdqu xmm6, [rax] + movdqu xmm7, [rax + 10h] + movdqu xmm8, [rax + 20h] + movdqu xmm9, [rax + 30h] + movdqu xmm10, [rax + 40h] + movdqu xmm11, [rax + 50h] + movdqu xmm12, [rax + 60h] + movdqu xmm13, [rax + 70h] + movdqu xmm14, [rax + 80h] + movdqu xmm15, [rax + 90h] + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov rax, EFI_WARN_RETURN_FROM_LONG_JUMP + mov rbx, (EFI_JUMP_BUFFER PTR [rdx])._rbx + mov rsp, (EFI_JUMP_BUFFER PTR [rdx])._rsp + mov rbp, (EFI_JUMP_BUFFER PTR [rdx])._rbp + mov rdi, (EFI_JUMP_BUFFER PTR [rdx])._rdi + mov rsi, (EFI_JUMP_BUFFER PTR [rdx])._rsi + mov r10, (EFI_JUMP_BUFFER PTR [rdx])._r10 + mov r11, (EFI_JUMP_BUFFER PTR [rdx])._r11 + mov r12, (EFI_JUMP_BUFFER PTR [rdx])._r12 + mov r13, (EFI_JUMP_BUFFER PTR [rdx])._r13 + mov r14, (EFI_JUMP_BUFFER PTR [rdx])._r14 + mov r15, (EFI_JUMP_BUFFER PTR [rdx])._r15 + add rsp, 8 ;pop the eip + jmp QWORD PTR (EFI_JUMP_BUFFER PTR [rdx])._rip + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov rax, EFI_WARN_RETURN_FROM_LONG_JUMP + ret +TransferControlLongJump ENDP + +text ENDS +END |