diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.c b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.c new file mode 100644 index 0000000000..a1b982fbae --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.c @@ -0,0 +1,187 @@ +/** @file + This library supports a PEI Service table Pointer library implementation that + allows code dependent upon PEI Service to operate in an isolated execution environment + such as within the context of a host-based unit test framework. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UnitTestPeiServicesTablePointerLib.h" + +/// +/// Pei service instance +/// +EFI_PEI_SERVICES mPeiServices = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + UnitTestInstallPpi, // InstallPpi + UnitTestReInstallPpi, // ReInstallPpi + UnitTestLocatePpi, // LocatePpi + UnitTestNotifyPpi, // NotifyPpi + + UnitTestGetBootMode, // GetBootMode + UnitTestSetBootMode, // SetBootMode + + UnitTestGetHobList, // GetHobList + UnitTestCreateHob, // CreateHob + + UnitTestFfsFindNextVolume, // FfsFindNextVolume + UnitTestFfsFindNextFile, // FfsFindNextFile + UnitTestFfsFindSectionData, // FfsFindSectionData + + UnitTestInstallPeiMemory, // InstallPeiMemory + UnitTestAllocatePages, // AllocatePages + UnitTestAllocatePool, // AllocatePool + (EFI_PEI_COPY_MEM)CopyMem, + (EFI_PEI_SET_MEM)SetMem, + + UnitTestReportStatusCode, // ReportStatusCode + UnitTestResetSystem, // ResetSystem + + NULL, // CpuIo + NULL, // PciCfg + + UnitTestFfsFindFileByName, // FfsFindFileByName + UnitTestFfsGetFileInfo, // FfsGetFileInfo + UnitTestFfsGetVolumeInfo, // FfsGetVolumeInfo + UnitTestRegisterForShadow, // RegisterForShadow + UnitTestFfsFindSectionData3, // FfsFindSectionData3 + UnitTestFfsGetFileInfo2, // FfsGetFileInfo2 + UnitTestResetSystem2, // ResetSystem2 + UnitTestFreePages, // FreePages +}; + +PEI_CORE_INSTANCE mPrivateData; +UINT8 mHobBuffer[MAX_HOB_SIZE]; +VOID *mPeiServicesPointer; + +/** + Clear Buffer For Global Data. +**/ +VOID +ClearGlobalData ( + VOID + ) +{ + ZeroMem (&mPrivateData, sizeof (mPrivateData)); + mPrivateData.PpiData.PpiList.MaxCount = MAX_PPI_COUNT; + mPrivateData.PpiData.CallbackNotifyList.MaxCount = MAX_PPI_COUNT; + mPrivateData.PpiData.DispatchNotifyList.MaxCount = MAX_PPI_COUNT; + + ZeroMem (mHobBuffer, MAX_HOB_SIZE); + mPrivateData.HobList.Raw = mHobBuffer; + UnitTestCoreBuildHobHandoffInfoTable (0, (EFI_PHYSICAL_ADDRESS)(UINTN)mHobBuffer, MAX_HOB_SIZE); +} + +/** + Resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. + +**/ +VOID +EFIAPI +UnitTestResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + ClearGlobalData (); +} + +/** + Retrieves the cached value of the PEI Services Table pointer. + + Returns the cached value of the PEI Services Table pointer in a CPU specific manner + as specified in the CPU binding section of the Platform Initialization Pre-EFI + Initialization Core Interface Specification. + + If the cached PEI Services Table pointer is NULL, then ASSERT(). + + @return The pointer to PeiServices. + +**/ +CONST EFI_PEI_SERVICES ** +EFIAPI +GetPeiServicesTablePointer ( + VOID + ) +{ + mPeiServicesPointer = &mPeiServices; + return (CONST EFI_PEI_SERVICES **)&mPeiServicesPointer; +} + +/** + Caches a pointer PEI Services Table. + + Caches the pointer to the PEI Services Table specified by PeiServicesTablePointer + in a CPU specific manner as specified in the CPU binding section of the Platform Initialization + Pre-EFI Initialization Core Interface Specification. + + If PeiServicesTablePointer is NULL, then ASSERT(). + + @param PeiServicesTablePointer The address of PeiServices pointer. +**/ +VOID +EFIAPI +SetPeiServicesTablePointer ( + IN CONST EFI_PEI_SERVICES **PeiServicesTablePointer + ) +{ + ASSERT (FALSE); +} + +/** + Perform CPU specific actions required to migrate the PEI Services Table + pointer from temporary RAM to permanent RAM. + + For IA32 CPUs, the PEI Services Table pointer is stored in the 4 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For X64 CPUs, the PEI Services Table pointer is stored in the 8 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For Itanium and ARM CPUs, a the PEI Services Table Pointer is stored in + a dedicated CPU register. This means that there is no memory storage + associated with storing the PEI Services Table pointer, so no additional + migration actions are required for Itanium or ARM CPUs. + +**/ +VOID +EFIAPI +MigratePeiServicesTablePointer ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + The constructor function init PeiServicesTable with clean buffer. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +UnitTestPeiServicesTablePointerLibConstructor ( + VOID + ) +{ + ClearGlobalData (); + return EFI_SUCCESS; +} diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.h b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.h new file mode 100644 index 0000000000..e411d08a86 --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.h @@ -0,0 +1,653 @@ +/** @file + An internal header file for the Unit Test instance of the PEI services Table Pointer Library. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PEI_SERVICES_TABLE_POINTER_LIB_UNIT_TEST_H_ +#define PEI_SERVICES_TABLE_POINTER_LIB_UNIT_TEST_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PPI_COUNT 100 +#define MAX_HOB_SIZE SIZE_32MB + +/// +/// Forward declaration for PEI_CORE_INSTANCE +/// +typedef struct _PEI_CORE_INSTANCE PEI_CORE_INSTANCE; + +/// +/// Pei Core private data structures +/// +typedef union { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + UINTN LastDispatchedCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS PpiPtrs[MAX_PPI_COUNT]; +} PEI_PPI_LIST; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS NotifyPtrs[MAX_PPI_COUNT]; +} PEI_CALLBACK_NOTIFY_LIST; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + UINTN LastDispatchedCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS NotifyPtrs[MAX_PPI_COUNT]; +} PEI_DISPATCH_NOTIFY_LIST; + +/// +/// PPI database structure which contains three links: +/// PpiList, CallbackNotifyList and DispatchNotifyList. +/// +typedef struct { + /// + /// PPI List. + /// + PEI_PPI_LIST PpiList; + /// + /// Notify List at dispatch level. + /// + PEI_CALLBACK_NOTIFY_LIST CallbackNotifyList; + /// + /// Notify List at callback level. + /// + PEI_DISPATCH_NOTIFY_LIST DispatchNotifyList; +} PEI_PPI_DATABASE; + +/// +/// Pei Core private data structure instance +/// +struct _PEI_CORE_INSTANCE { + PEI_PPI_DATABASE PpiData; + EFI_PEI_HOB_POINTERS HobList; +}; + +extern PEI_CORE_INSTANCE mPrivateData; +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) &mPrivateData + +VOID +ProcessNotify ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ); + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +EFIAPI +UnitTestInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +/** + + This function reinstalls an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties can + use to replace an interface of the same name in the protocol database with a + different interface. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS if the operation was successful + @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL + @retval EFI_INVALID_PARAMETER if NewPpi is not valid + @retval EFI_NOT_FOUND if the PPI was not in the database + +**/ +EFI_STATUS +EFIAPI +UnitTestReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ); + +/** + + Locate a given named PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Guid Pointer to GUID of the PPI. + @param Instance Instance Number to discover. + @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + @param Ppi Pointer to reference the found PPI + + @retval EFI_SUCCESS if the PPI is in the database + @retval EFI_NOT_FOUND if the PPI is not in the database + +**/ +EFI_STATUS +EFIAPI +UnitTestLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ); + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +EFIAPI +UnitTestNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ); + +/** + Gets the pointer to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param HobList Pointer to the HOB List. + + @retval EFI_SUCCESS Get the pointer of HOB List + @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published + @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode) + +**/ +EFI_STATUS +EFIAPI +UnitTestGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ); + +/** + Add a new HOB to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + @param Hob Pointer to the new HOB. + + @return EFI_SUCCESS Success to create HOB. + @retval EFI_INVALID_PARAMETER if Hob is NULL + @retval EFI_NOT_AVAILABLE_YET if HobList is still not available. + @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +EFIAPI +UnitTestCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ); + +/** + + Builds a Handoff Information Table HOB + + @param BootMode - Current Bootmode + @param MemoryBegin - Start Memory Address. + @param MemoryLength - Length of Memory. + + @return EFI_SUCCESS Always success to initialize HOB. + +**/ +EFI_STATUS +UnitTestCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + Resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. + +**/ +VOID +EFIAPI +UnitTestResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +UnitTestGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ); + +/** + This service enables PEIMs to update the boot mode variable. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode The value of the boot mode to set. + + @return EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +UnitTestSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +/** + Search the firmware volumes by index + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware + Volume (BFV). + @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist. + + @retval EFI_INVALID_PARAMETER VolumeHandle is NULL + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_SUCCESS The volume was found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ); + +/** + Searches for the next matching file in the firmware volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FvHandle Handle of firmware volume in which to search. + @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start + at the beginning of the firmware volume. On exit, points the file handle of the next file + in the volume or NULL if there are no more files. + + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + @retval EFI_SUCCESS The file was found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param SectionType Filter to find only sections of this type. + @param FileHandle Pointer to the current file to search. + @param SectionData A pointer to the discovered section, if successful. + NULL if section not found + + @retval EFI_NOT_FOUND The section was not found. + @retval EFI_SUCCESS The section was found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + +/** + + This function registers the found memory configuration with the PEI Foundation. + + The usage model is that the PEIM that discovers the permanent memory shall invoke this service. + This routine will hold discoveried memory information into PeiCore's private data, + and set SwitchStackSignal flag. After PEIM who discovery memory is dispatched, + PeiDispatcher will migrate temporary memory to permanent memory. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryBegin Start of memory address. + @param MemoryLength Length of memory. + + @return EFI_SUCCESS Always success. + +**/ +EFI_STATUS +EFIAPI +UnitTestInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap. + After InstallPeiMemory() is called, PEI will allocate pages within the region + of memory provided by InstallPeiMemory() service in a best-effort fashion. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + +**/ +EFI_STATUS +EFIAPI +UnitTestAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + + Pool allocation service. Before permanent memory is discovered, the pool will + be allocated in the heap in temporary memory. Generally, the size of the heap in temporary + memory does not exceed 64K, so the biggest pool size could be allocated is + 64K. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Size Amount of memory required + @param Buffer Address of pointer to the buffer + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +UnitTestAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + + Core version of the Status Code reporter + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Type of Status Code. + @param Value Value to output for Status Code. + @param Instance Instance Number of this status code. + @param CallerId ID of the caller of this status code. + @param Data Optional data associated with this status code. + + @retval EFI_SUCCESS if status code is successfully reported + @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +**/ +EFI_STATUS +EFIAPI +UnitTestReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + +Core version of the Reset System + + +@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + +@retval EFI_NOT_AVAILABLE_YET PPI not available yet. +@retval EFI_DEVICE_ERROR Did not reset system. + Otherwise, resets the system. + +**/ +EFI_STATUS +EFIAPI +UnitTestResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + Find a file within a volume by its name. + + @param FileName A pointer to the name of the file to find within the firmware volume. + @param VolumeHandle The firmware volume to search + @param FileHandle Upon exit, points to the found file's handle + or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + @retval EFI_NOT_FOUND File was not found. + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + +/** + Returns information about the specified volume. + + This function returns information about a specific firmware + volume, including its name, type, attributes, starting address + and size. + + @param VolumeHandle Handle of the volume. + @param VolumeInfo Upon exit, points to the volume's information. + + @retval EFI_SUCCESS Volume information returned. + @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume. + @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL. + @retval EFI_SUCCESS Information successfully returned. + @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + +/** +This routine enables a PEIM to register itself for shadow when the PEI Foundation +discovers permanent memory. + +@param FileHandle File handle of a PEIM. + +@retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself. +@retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself. +@retval EFI_SUCCESS Successfully to register itself. + +**/ +EFI_STATUS +EFIAPI +UnitTestRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ); + +/** +Searches for the next matching section within the specified file. + +@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. +@param SectionType The value of the section type to find. +@param SectionInstance Section instance to find. +@param FileHandle Handle of the firmware file to search. +@param SectionData A pointer to the discovered section, if successful. +@param AuthenticationStatus A pointer to the authentication status for this section. + +@retval EFI_SUCCESS The section was found. +@retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindSectionData3 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ); + +/** +Returns information about a specific file. + +@param FileHandle Handle of the file. +@param FileInfo Upon exit, points to the file's information. + +@retval EFI_INVALID_PARAMETER If FileInfo is NULL. +@retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. +@retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsGetFileInfo2 ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ); + +/** +Frees memory pages. + +@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. +@param[in] Memory The base physical address of the pages to be freed. +@param[in] Pages The number of contiguous 4 KB pages to free. + +@retval EFI_SUCCESS The requested pages were freed. +@retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. +@retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +UnitTestFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +#endif diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf new file mode 100644 index 0000000000..59d86c9db8 --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf @@ -0,0 +1,37 @@ +## @file +# Pei Services Table Pointer Lib for unit tests implementation. +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UnitTestPeiServicesTablePointerLib + MODULE_UNI_FILE = UnitTestPeiServicesTablePointerLib.uni + FILE_GUID = 55F23CD2-9BB1-41EE-AB10-550B638210E1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiServicesTablePointerLib + + CONSTRUCTOR = UnitTestPeiServicesTablePointerLibConstructor +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UnitTestPeiServicesTablePointerLib.h + UnitTestPeiServicesTablePointerLib.c + UnitTestPeiServicesTablePointerLibMisc.c + UnitTestPeiServicesTablePointerLibPpi.c + UnitTestPeiServicesTablePointerLibHob.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UnitTestLib diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.uni b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.uni new file mode 100644 index 0000000000..ca2118533a --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.uni @@ -0,0 +1,12 @@ +// /** @file +// Pei Services Table Pointer Lib for unit tests implementation. +// +// Copyright (c) 2023, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Pei Services Table Pointer Lib for unit tests." + +#string STR_MODULE_DESCRIPTION #language en-US "Pei Services Table Pointer Lib for unit tests." diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibHob.c b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibHob.c new file mode 100644 index 0000000000..1a5a1bef1f --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibHob.c @@ -0,0 +1,155 @@ +/** @file + This file implements some PEI services about Hob. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UnitTestPeiServicesTablePointerLib.h" + +/** + + Gets the pointer to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param HobList Pointer to the HOB List. + + @retval EFI_SUCCESS Get the pointer of HOB List + @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published + @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode) + +**/ +EFI_STATUS +EFIAPI +UnitTestGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +{ + PEI_CORE_INSTANCE *PrivateData; + + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + *HobList = PrivateData->HobList.Raw; + + return EFI_SUCCESS; +} + +/** + Add a new HOB to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + @param Hob Pointer to the new HOB. + + @return EFI_SUCCESS Success to create HOB. + @retval EFI_INVALID_PARAMETER if Hob is NULL + @retval EFI_NOT_AVAILABLE_YET if HobList is still not available. + @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +EFIAPI +UnitTestCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + Status = UnitTestGetHobList (PeiServices, Hob); + if (EFI_ERROR (Status)) { + return Status; + } + + HandOffHob = *Hob; + + // + // Check Length to avoid data overflow. + // + if (0x10000 - Length <= 0x7) { + return EFI_INVALID_PARAMETER; + } + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + DEBUG ((DEBUG_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length)); + DEBUG ((DEBUG_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + DEBUG ((DEBUG_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID *)(UINTN)HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER *)*Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER *)*Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER *)*Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)*Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + return EFI_SUCCESS; +} + +/** + + Builds a Handoff Information Table HOB + + @param BootMode - Current Bootmode + @param MemoryBegin - Start Memory Address. + @param MemoryLength - Length of Memory. + + @return EFI_SUCCESS Always success to initialize HOB. + +**/ +EFI_STATUS +UnitTestCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = (UINT16)sizeof (EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd + 1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + return EFI_SUCCESS; +} diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibMisc.c b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibMisc.c new file mode 100644 index 0000000000..90955bf482 --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibMisc.c @@ -0,0 +1,430 @@ +/** @file + This file implements some PEI services. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UnitTestPeiServicesTablePointerLib.h" + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +UnitTestGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + This service enables PEIMs to update the boot mode variable. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode The value of the boot mode to set. + + @return EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +UnitTestSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Search the firmware volumes by index + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware + Volume (BFV). + @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist. + + @retval EFI_INVALID_PARAMETER VolumeHandle is NULL + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_SUCCESS The volume was found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Searches for the next matching file in the firmware volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FvHandle Handle of firmware volume in which to search. + @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start + at the beginning of the firmware volume. On exit, points the file handle of the next file + in the volume or NULL if there are no more files. + + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + @retval EFI_SUCCESS The file was found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param SectionType Filter to find only sections of this type. + @param FileHandle Pointer to the current file to search. + @param SectionData A pointer to the discovered section, if successful. + NULL if section not found + + @retval EFI_NOT_FOUND The section was not found. + @retval EFI_SUCCESS The section was found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This function registers the found memory configuration with the PEI Foundation. + + The usage model is that the PEIM that discovers the permanent memory shall invoke this service. + This routine will hold discoveried memory information into PeiCore's private data, + and set SwitchStackSignal flag. After PEIM who discovery memory is dispatched, + PeiDispatcher will migrate temporary memory to permanent memory. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryBegin Start of memory address. + @param MemoryLength Length of memory. + + @return EFI_SUCCESS Always success. + +**/ +EFI_STATUS +EFIAPI +UnitTestInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap. + After InstallPeiMemory() is called, PEI will allocate pages within the region + of memory provided by InstallPeiMemory() service in a best-effort fashion. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + +**/ +EFI_STATUS +EFIAPI +UnitTestAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + + Pool allocation service. Before permanent memory is discovered, the pool will + be allocated in the heap in temporary memory. Generally, the size of the heap in temporary + memory does not exceed 64K, so the biggest pool size could be allocated is + 64K. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Size Amount of memory required + @param Buffer Address of pointer to the buffer + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +UnitTestAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + + Core version of the Status Code reporter + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Type of Status Code. + @param Value Value to output for Status Code. + @param Instance Instance Number of this status code. + @param CallerId ID of the caller of this status code. + @param Data Optional data associated with this status code. + + @retval EFI_SUCCESS if status code is successfully reported + @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +**/ +EFI_STATUS +EFIAPI +UnitTestReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + +Core version of the Reset System + + +@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + +@retval EFI_NOT_AVAILABLE_YET PPI not available yet. +@retval EFI_DEVICE_ERROR Did not reset system. + Otherwise, resets the system. + +**/ +EFI_STATUS +EFIAPI +UnitTestResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Find a file within a volume by its name. + + @param FileName A pointer to the name of the file to find within the firmware volume. + @param VolumeHandle The firmware volume to search + @param FileHandle Upon exit, points to the found file's handle + or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + @retval EFI_NOT_FOUND File was not found. + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Returns information about the specified volume. + + This function returns information about a specific firmware + volume, including its name, type, attributes, starting address + and size. + + @param VolumeHandle Handle of the volume. + @param VolumeInfo Upon exit, points to the volume's information. + + @retval EFI_SUCCESS Volume information returned. + @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume. + @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL. + @retval EFI_SUCCESS Information successfully returned. + @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** +This routine enables a PEIM to register itself for shadow when the PEI Foundation +discovers permanent memory. + +@param FileHandle File handle of a PEIM. + +@retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself. +@retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself. +@retval EFI_SUCCESS Successfully to register itself. + +**/ +EFI_STATUS +EFIAPI +UnitTestRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** +Searches for the next matching section within the specified file. + +@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. +@param SectionType The value of the section type to find. +@param SectionInstance Section instance to find. +@param FileHandle Handle of the firmware file to search. +@param SectionData A pointer to the discovered section, if successful. +@param AuthenticationStatus A pointer to the authentication status for this section. + +@retval EFI_SUCCESS The section was found. +@retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsFindSectionData3 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** +Returns information about a specific file. + +@param FileHandle Handle of the file. +@param FileInfo Upon exit, points to the file's information. + +@retval EFI_INVALID_PARAMETER If FileInfo is NULL. +@retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. +@retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +UnitTestFfsGetFileInfo2 ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** +Frees memory pages. + +@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. +@param[in] Memory The base physical address of the pages to be freed. +@param[in] Pages The number of contiguous 4 KB pages to free. + +@retval EFI_SUCCESS The requested pages were freed. +@retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. +@retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +UnitTestFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ) +{ + return EFI_NOT_AVAILABLE_YET; +} diff --git a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibPpi.c b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibPpi.c new file mode 100644 index 0000000000..09f4094dad --- /dev/null +++ b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLibPpi.c @@ -0,0 +1,485 @@ +/** @file + This file implements some PEI services about PPI. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UnitTestPeiServicesTablePointerLib.h" + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + @param Single TRUE if only single entry in the PpiList. + FALSE if the PpiList is ended with an entry which has the + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +InternalPeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN BOOLEAN Single + ) +{ + PEI_CORE_INSTANCE *PrivateData; + PEI_PPI_LIST *PpiListPointer; + UINTN Index; + UINTN LastCount; + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + PpiListPointer = &PrivateData->PpiData.PpiList; + Index = PpiListPointer->CurrentCount; + LastCount = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for ( ; ;) { + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PpiListPointer->CurrentCount = LastCount; + DEBUG ((DEBUG_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + + if (Index >= PpiListPointer->MaxCount) { + // + // Run out of room, assert. + // + ASSERT (Index < PpiListPointer->MaxCount); + } + + DEBUG ((DEBUG_INFO, "Install PPI: %g\n", PpiList->Guid)); + PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)PpiList; + Index++; + PpiListPointer->CurrentCount++; + + if (Single) { + // + // Only single entry in the PpiList. + // + break; + } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) + { + // + // Continue until the end of the PPI List. + // + break; + } + + // + // Go to the next descriptor. + // + PpiList++; + } + + // + // Process any callback level notifies for newly installed PPIs. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCount, + PpiListPointer->CurrentCount, + 0, + PrivateData->PpiData.CallbackNotifyList.CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +EFIAPI +UnitTestInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + return InternalPeiInstallPpi (PeiServices, PpiList, FALSE); +} + +/** + + This function reinstalls an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties can + use to replace an interface of the same name in the protocol database with a + different interface. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS if the operation was successful + @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL + @retval EFI_INVALID_PARAMETER if NewPpi is not valid + @retval EFI_NOT_FOUND if the PPI was not in the database + +**/ +EFI_STATUS +EFIAPI +UnitTestReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) { + break; + } + } + + if (Index == PrivateData->PpiData.PpiList.CurrentCount) { + return EFI_NOT_FOUND; + } + + // + // Replace the old PPI with the new one. + // + DEBUG ((DEBUG_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); + PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)NewPpi; + + // + // Process any callback level notifies for the newly installed PPI. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + 0, + PrivateData->PpiData.CallbackNotifyList.CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + Locate a given named PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Guid Pointer to GUID of the PPI. + @param Instance Instance Number to discover. + @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + @param Ppi Pointer to reference the found PPI + + @retval EFI_SUCCESS if the PPI is in the database + @retval EFI_NOT_FOUND if the PPI is not in the database + +**/ +EFI_STATUS +EFIAPI +UnitTestLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) + { + if (Instance == 0) { + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + return EFI_SUCCESS; + } + + Instance--; + } + } + + return EFI_NOT_FOUND; +} + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + @param Single TRUE if only single entry in the NotifyList. + FALSE if the NotifyList is ended with an entry which has the + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +InternalPeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList, + IN BOOLEAN Single + ) +{ + PEI_CORE_INSTANCE *PrivateData; + PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer; + UINTN CallbackNotifyIndex; + UINTN LastCallbackNotifyCount; + PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer; + UINTN DispatchNotifyIndex; + UINTN LastDispatchNotifyCount; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList; + CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount; + LastCallbackNotifyCount = CallbackNotifyIndex; + + DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList; + DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount; + LastDispatchNotifyCount = DispatchNotifyIndex; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for ( ; ;) { + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount; + DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount; + DEBUG ((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) { + if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) { + // + // Run out of room, assert. + // + ASSERT (CallbackNotifyIndex < CallbackNotifyListPointer->MaxCount); + } + + CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList; + CallbackNotifyIndex++; + CallbackNotifyListPointer->CurrentCount++; + } else { + ASSERT ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0); + } + + DEBUG ((DEBUG_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + + if (Single) { + // + // Only single entry in the NotifyList. + // + break; + } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) + { + // + // Continue until the end of the Notify List. + // + break; + } + + // + // Go to the next descriptor. + // + NotifyList++; + } + + // + // Process any callback level notifies for all previously installed PPIs. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiList.CurrentCount, + LastCallbackNotifyCount, + CallbackNotifyListPointer->CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +EFIAPI +UnitTestNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +{ + return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE); +} + +/** + + Process notifications. + + @param PrivateData PeiCore's private data structure + @param NotifyType Type of notify to fire. + @param InstallStartIndex Install Beginning index. + @param InstallStopIndex Install Ending index. + @param NotifyStartIndex Notify Beginning index. + @param NotifyStopIndex Notify Ending index. + +**/ +VOID +ProcessNotify ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +{ + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) { + if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) { + NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify; + } else { + NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify; + } + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) + { + DEBUG (( + DEBUG_INFO, + "Notify: PPI Guid: %g, Peim notify entry point: %p\n", + SearchGuid, + NotifyDescriptor->Notify + )); + NotifyDescriptor->Notify ( + (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), + NotifyDescriptor, + (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi + ); + } + } + } +} diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc index a76e31d97d..872d9c0d8c 100644 --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc @@ -35,6 +35,7 @@ UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.inf UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTestUefiBootServicesTableLib.inf + UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc index 7866c36e66..5217de31e4 100644 --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc @@ -21,6 +21,7 @@ DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf UefiBootServicesTableLib|UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTestUefiBootServicesTableLib.inf + PeiServicesTablePointerLib|UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf [BuildOptions] GCC:*_*_*_CC_FLAGS = -fno-pie