From: "Zhiguang Liu" <zhiguang.liu@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"mikuback@linux.microsoft.com" <mikuback@linux.microsoft.com>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>,
Sean Brogan <sean.brogan@microsoft.com>
Subject: Re: [edk2-devel] [PATCH v2] UnitTestFrameworkPkg: Add UnitTestPeiServicesTablePointerLib
Date: Mon, 12 Jun 2023 05:07:12 +0000 [thread overview]
Message-ID: <PH0PR11MB504847A9DA301A30D1F70D7A9054A@PH0PR11MB5048.namprd11.prod.outlook.com> (raw)
In-Reply-To: <f9efec52-740e-938e-9fde-9c805cc046de@linux.microsoft.com>
Hi, Michael
Thanks for the comments.
Yes, I am following the similar pattern of UnitTestUefiBootServicesTableLib. I agree we can explain these types in the readme in the future patch.
In the newer version of patch, I remove the debug code markers as you suggested.
Because this is the only change, I will keep your Reviewed-by.
Thanks
Zhiguang
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael
> Kubacki
> Sent: Tuesday, June 6, 2023 11:28 PM
> To: devel@edk2.groups.io; Liu, Zhiguang <zhiguang.liu@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Sean Brogan
> <sean.brogan@microsoft.com>
> Subject: Re: [edk2-devel] [PATCH v2] UnitTestFrameworkPkg: Add
> UnitTestPeiServicesTablePointerLib
>
> It looks like you're following a similar pattern to a library instance
> already in UnitTestFrameworkPkg/Library like
> UnitTestUefiBootServicesTableLib. I can't find where these types of
> libraries are explicitly called out in the
> UnitTestFrameworkPkg/ReadMe.md file [1]. You don't need to add it in
> this patch, but we might want to explain these in the readme (unless I
> just missed it).
>
> They are not really a pure mock since they have a self-contained
> functional implementation of some structures typically in core modules
> like the PPI and HOB lists. They might also have more code outside the
> unit being tested than is ideal in a unit test, but they are useful for
> code that has dependencies in global databases.
>
> [1] -
> https://github.com/tianocore/edk2/blob/master/UnitTestFrameworkPkg/R
> eadMe.md#unit-test-locationlayout-rules
>
> There's some code I think is unnecessary in a unit test implementation
> like surrounding this NULL pointer check with debug code markers in
> UnitTestGetHobList():
>
> DEBUG_CODE_BEGIN ();
> if (HobList == NULL) {
> return EFI_INVALID_PARAMETER;
> }
>
> DEBUG_CODE_END ();
>
> Can you please simply check if the pointer is NULL?
>
> Reviewed-by: Michael Kubacki <michael.kubacki@microsoft.com>
>
> On 6/6/2023 1:40 AM, Zhiguang Liu wrote:
> > 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/UnitTes
> tPeiServicesTablePointerLib.c
> > create mode 100644
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLib.h
> > create mode 100644
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLib.inf
> > create mode 100644
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLib.uni
> > create mode 100644
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLibHob.c
> > create mode 100644
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLibMisc.c
> > create mode 100644
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLibPpi.c
> >
> > diff --git
> a/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.c
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.c
> > new file mode 100644
> > index 0000000000..a1b982fbae
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.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/UnitT
> estPeiServicesTablePointerLib.h
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.h
> > new file mode 100644
> > index 0000000000..e411d08a86
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.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/UnitT
> estPeiServicesTablePointerLib.inf
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.inf
> > new file mode 100644
> > index 0000000000..59d86c9db8
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.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/UnitT
> estPeiServicesTablePointerLib.uni
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.uni
> > new file mode 100644
> > index 0000000000..ca2118533a
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLib.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/UnitT
> estPeiServicesTablePointerLibHob.c
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLibHob.c
> > new file mode 100644
> > index 0000000000..2d4ffe8c59
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLibHob.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/UnitT
> estPeiServicesTablePointerLibMisc.c
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLibMisc.c
> > new file mode 100644
> > index 0000000000..90955bf482
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLibMisc.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/UnitT
> estPeiServicesTablePointerLibPpi.c
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLibPpi.c
> > new file mode 100644
> > index 0000000000..09f4094dad
> > --- /dev/null
> > +++
> b/UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitT
> estPeiServicesTablePointerLibPpi.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/Un
> itTestPersistenceLibSimpleFileSystem.inf
> >
> UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAss
> ertLib.inf
> >
> UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTest
> UefiBootServicesTableLib.inf
> > +
> UnitTestFrameworkPkg/Library/UnitTestPeiServicesTablePointerLib/UnitTes
> tPeiServicesTablePointerLib.inf
> >
> >
> UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnit
> TestDxe.inf
> >
> UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnit
> TestPei.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/DebugLibPo
> six.inf
> >
> MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocati
> onLibPosix/MemoryAllocationLibPosix.inf
> >
> UefiBootServicesTableLib|UnitTestFrameworkPkg/Library/UnitTestUefiBoot
> ServicesTableLib/UnitTestUefiBootServicesTableLib.inf
> > +
> PeiServicesTablePointerLib|UnitTestFrameworkPkg/Library/UnitTestPeiServi
> cesTablePointerLib/UnitTestPeiServicesTablePointerLib.inf
> >
> > [BuildOptions]
> > GCC:*_*_*_CC_FLAGS = -fno-pie
>
>
>
>
prev parent reply other threads:[~2023-06-12 5:07 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 ` [edk2-devel] " Ni, Ray
2023-06-06 15:28 ` Michael Kubacki
2023-06-12 5:07 ` Zhiguang Liu [this message]
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=PH0PR11MB504847A9DA301A30D1F70D7A9054A@PH0PR11MB5048.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