Reviewed-by: Ray Ni <ray...@intel.com> > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Zhiguang Liu > Sent: Tuesday, June 6, 2023 1:40 PM > To: devel@edk2.groups.io > Cc: Liu, Zhiguang <zhiguang....@intel.com>; Kinney, Michael D > <michael.d.kin...@intel.com>; Michael Kubacki > <mikub...@linux.microsoft.com>; Sean Brogan <sean.bro...@microsoft.com> > Subject: [edk2-devel] [PATCH v2] UnitTestFrameworkPkg: Add > UnitTestPeiServicesTablePointerLib > > This library supports a PeiServicesTablePointerLib implementation > that allows code dependent upon PeiServicesTable to operate in an > isolated execution environment such as within the context of a > host-based unit test framework. > > The unit test should initialize the PeiServicesTable database with > any required elements (e.g. PPIs, Hob etc.) prior to the services > being invoked by code under test. > > It is strongly recommended to clean any global databases by using > EFI_PEI_SERVICES.ResetSystem2 after every unit test so the tests > execute in a predictable manner from a clean state. > > Cc: Michael D Kinney <michael.d.kin...@intel.com> > Cc: Michael Kubacki <mikub...@linux.microsoft.com> > Cc: Sean Brogan <sean.bro...@microsoft.com> > Signed-off-by: Zhiguang Liu <zhiguang....@intel.com> > --- > .../UnitTestPeiServicesTablePointerLib.c | 187 +++++ > .../UnitTestPeiServicesTablePointerLib.h | 653 ++++++++++++++++++ > .../UnitTestPeiServicesTablePointerLib.inf | 37 + > .../UnitTestPeiServicesTablePointerLib.uni | 12 + > .../UnitTestPeiServicesTablePointerLibHob.c | 162 +++++ > .../UnitTestPeiServicesTablePointerLibMisc.c | 430 ++++++++++++ > .../UnitTestPeiServicesTablePointerLibPpi.c | 485 +++++++++++++ > UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc | 1 + > .../UnitTestFrameworkPkgHost.dsc.inc | 1 + > 9 files changed, 1968 insertions(+) > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLib.c > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLib.h > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLib.inf > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLib.uni > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLibHob.c > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLibMisc.c > create mode 100644 > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLibPpi.c > > diff --git > a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.c > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.c > new file mode 100644 > index 0000000000..a1b982fbae > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.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.<BR> > + 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/UnitTestPe > iServicesTablePointerLib.h > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.h > new file mode 100644 > index 0000000000..e411d08a86 > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.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.<BR> > + 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 <Base.h> > +#include <PiPei.h> > +#include <Pi/PiMultiPhase.h> > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/UnitTestLib.h> > +#include <Library/PeiServicesTablePointerLib.h> > +#include <Uefi.h> > + > +#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/UnitTestPe > iServicesTablePointerLib.inf > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.inf > new file mode 100644 > index 0000000000..59d86c9db8 > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.inf > @@ -0,0 +1,37 @@ > +## @file > +# Pei Services Table Pointer Lib for unit tests implementation. > +# > +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > +# 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/UnitTestPe > iServicesTablePointerLib.uni > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.uni > new file mode 100644 > index 0000000000..ca2118533a > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLib.uni > @@ -0,0 +1,12 @@ > +// /** @file > +// Pei Services Table Pointer Lib for unit tests implementation. > +// > +// Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > +// > +// 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/UnitTestPe > iServicesTablePointerLibHob.c > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLibHob.c > new file mode 100644 > index 0000000000..2d4ffe8c59 > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLibHob.c > @@ -0,0 +1,162 @@ > +/** @file > + This file implements some PEI services about Hob. > + > + Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > + 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; > + > + // > + // Only check this parameter in debug mode > + // > + > + DEBUG_CODE_BEGIN (); > + if (HobList == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + DEBUG_CODE_END (); > + > + 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/UnitTestPe > iServicesTablePointerLibMisc.c > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLibMisc.c > new file mode 100644 > index 0000000000..90955bf482 > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLibMisc.c > @@ -0,0 +1,430 @@ > +/** @file > + This file implements some PEI services. > + > + Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > + 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/UnitTestPe > iServicesTablePointerLibPpi.c > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLibPpi.c > new file mode 100644 > index 0000000000..09f4094dad > --- /dev/null > +++ > b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPe > iServicesTablePointerLibPpi.c > @@ -0,0 +1,485 @@ > +/** @file > + This file implements some PEI services about PPI. > + > + Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > + 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/UnitTest > PersistenceLibSimpleFileSystem.inf > > UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib. > inf > > UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTestUefiB > ootServicesTableLib.inf > + > UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTestPeiS > ervicesTablePointerLib.inf > > > UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestD > xe.inf > > UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestP > ei.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.in > f > > MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLib > Posix/MemoryAllocationLibPosix.inf > > UefiBootServicesTableLib|UnitTestFrameworkPkg/Library/UnitTestUefiBootServi > cesTableLib/UnitTestUefiBootServicesTableLib.inf > + > PeiServicesTablePointerLib|UnitTestFrameworkPkg/Library/UnitTestPeiServicesT > ablePointerLib/UnitTestPeiServicesTablePointerLib.inf > > [BuildOptions] > GCC:*_*_*_CC_FLAGS = -fno-pie > -- > 2.31.1.windows.1 > > > > >
-=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#105756): https://edk2.groups.io/g/devel/message/105756 Mute This Topic: https://groups.io/mt/99357915/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-