From: "Ni, Ray" <ray.ni@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"Liu, Zhiguang" <zhiguang.liu@intel.com>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>,
Michael Kubacki <mikuback@linux.microsoft.com>,
Sean Brogan <sean.brogan@microsoft.com>
Subject: Re: [edk2-devel] [PATCH v2] UnitTestFrameworkPkg: Add UnitTestPeiServicesTablePointerLib
Date: Tue, 6 Jun 2023 05:47:45 +0000 [thread overview]
Message-ID: <MN6PR11MB8244589789C5C6BFF1F9463C8C52A@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20230606054001.1289-1-zhiguang.liu@intel.com>
Reviewed-by: Ray Ni <ray.ni@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.liu@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Michael Kubacki
> <mikuback@linux.microsoft.com>; Sean Brogan <sean.brogan@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.kinney@intel.com>
> Cc: Michael Kubacki <mikuback@linux.microsoft.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Signed-off-by: Zhiguang Liu <zhiguang.liu@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
>
>
>
>
>
next prev parent reply other threads:[~2023-06-06 5:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-06 5:40 [PATCH v2] UnitTestFrameworkPkg: Add UnitTestPeiServicesTablePointerLib Zhiguang Liu
2023-06-06 5:47 ` Ni, Ray [this message]
2023-06-06 15:28 ` [edk2-devel] " Michael Kubacki
2023-06-12 5:07 ` Zhiguang Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN6PR11MB8244589789C5C6BFF1F9463C8C52A@MN6PR11MB8244.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox