MdeModulePkg: PeiMain: Introduce implementation of delayed dispatch

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4496

This change adds the implementation that fits the needs and description
of PI spec defined Delayed Dispatch PPI in Pei Core.

The PPI would allow minimal delay for registered callbacks. As well as
allowing other functions to wait for GUIDed delayed dispatch callbacks.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Debkumar De <debkumar.de@intel.com>
Cc: Catharine West <catharine.west@intel.com>

Co-authored-by: Mike Turner <mikeyt@pobox.com>
Co-authored-by: Sachin Ganesh <sachinganesh@ami.com>
Signed-off-by: Kun Qin <kuqin12@gmail.com>
This commit is contained in:
Kun Qin 2024-09-19 14:11:37 -07:00 committed by mergify[bot]
parent b3f36e151d
commit d64d1e195c
6 changed files with 541 additions and 2 deletions

View File

@ -3,14 +3,382 @@
Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PeiMain.h"
/**
//
// Utility global variables
//
/**
DelayedDispatchDispatcher
Delayed Dispach cycle (ie one pass) through each entry, calling functions when their
time has expired. When DelayedGroupId is specified, if there are any of the specified entries
in the dispatch queue during dispatch, repeat the DelayedDispatch cycle.
@param DelayedDispatchTable Pointer to dispatch table
@param OPTIONAL DelayedGroupId used to insure particular time is met.
@return BOOLEAN
**/
BOOLEAN
DelayedDispatchDispatcher (
IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable,
IN EFI_GUID *DelayedGroupId OPTIONAL
);
/**
DelayedDispatch End of PEI callback function. Insure that all of the delayed dispatch
entries are complete before exiting PEI.
@param[in] PeiServices - Pointer to PEI Services Table.
@param[in] NotifyDesc - Pointer to the descriptor for the Notification event that
caused this function to execute.
@param[in] Ppi - Pointer to the PPI data associated with this function.
@retval EFI_STATUS - Always return EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
PeiDelayedDispatchOnEndOfPei (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
);
EFI_DELAYED_DISPATCH_PPI mDelayedDispatchPpi = { PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnEvent };
EFI_PEI_PPI_DESCRIPTOR mDelayedDispatchDesc = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiDelayedDispatchPpiGuid,
&mDelayedDispatchPpi
};
EFI_PEI_NOTIFY_DESCRIPTOR mDelayedDispatchNotifyDesc = {
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
&gEfiEndOfPeiSignalPpiGuid,
PeiDelayedDispatchOnEndOfPei
};
/**
Helper function to look up DELAYED_DISPATCH_TABLE published in HOB.
@return Pointer to DELAYED_DISPATCH_TABLE from HOB
**/
DELAYED_DISPATCH_TABLE *
GetDelayedDispatchTable (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid);
if (GuidHob == NULL) {
// There is something off about the build if this happens. We do want to
// assert here to catch it during development.
DEBUG ((DEBUG_ERROR, "%a - Delayed Dispatch Hob not available.\n", __func__));
ASSERT (FALSE);
return NULL;
}
return (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob);
}
/**
Register a callback to be called after a minimum delay has occurred.
This service is the single member function of the EFI_DELAYED_DISPATCH_PPI
@param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI instance
@param[in] Function Function to call back
@param[in] Context Context data
@param[in] DelayedGroupId GUID for this Delayed Dispatch request.
@param[in] Delay Delay interval
@retval EFI_SUCCESS Function successfully loaded
@retval EFI_INVALID_PARAMETER One of the Arguments is not supported
@retval EFI_OUT_OF_RESOURCES No more entries
**/
EFI_STATUS
EFIAPI
PeiDelayedDispatchRegister (
IN EFI_DELAYED_DISPATCH_PPI *This,
IN EFI_DELAYED_DISPATCH_FUNCTION Function,
IN UINT64 Context,
IN EFI_GUID *DelayedGroupId OPTIONAL,
IN UINT32 Delay
)
{
DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
DELAYED_DISPATCH_ENTRY *Entry;
EFI_STATUS Status;
// Check input parameters
if ((Function == NULL) || (Delay > FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs)) || (This == NULL)) {
DEBUG ((DEBUG_ERROR, "%a Invalid parameter. Function: %Lx, Delay: %u, This: %p\n", __func__, (UINT64)(UINTN)Function, Delay, This));
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
// Get delayed dispatch table
DelayedDispatchTable = GetDelayedDispatchTable ();
if (DelayedDispatchTable == NULL) {
DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__));
Status = EFI_UNSUPPORTED;
goto Exit;
}
// Check for available entry slots
ASSERT (DelayedDispatchTable->Count <= DELAYED_DISPATCH_MAX_ENTRIES);
if (DelayedDispatchTable->Count == DELAYED_DISPATCH_MAX_ENTRIES) {
DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n", __func__));
Status = EFI_OUT_OF_RESOURCES;
goto Exit;
}
Entry = &DelayedDispatchTable->Entry[DelayedDispatchTable->Count];
Entry->Function = Function;
Entry->Context = Context;
Status = SafeUint64Add (GET_TIME_IN_US (), Delay, &Entry->DispatchTime);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Delay overflow\n", __func__));
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
if (DelayedGroupId == NULL) {
ZeroMem (&Entry->DelayedGroupId, sizeof (EFI_GUID));
} else {
CopyGuid (&Entry->DelayedGroupId, DelayedGroupId);
}
Entry->MicrosecondDelay = Delay;
DelayedDispatchTable->Count++;
DEBUG ((DEBUG_INFO, "%a Adding dispatch Entry\n", __func__));
DEBUG ((DEBUG_INFO, " Requested Delay = %d\n", Delay));
DEBUG ((DEBUG_INFO, " Trigger Time = %d\n", Entry->DispatchTime));
DEBUG ((DEBUG_INFO, " Context = 0x%016lx\n", Entry->Context));
DEBUG ((DEBUG_INFO, " Function = %Lx\n", (UINT64)(UINTN)Entry->Function));
DEBUG ((DEBUG_INFO, " DelayedGroupId = %g\n", &Entry->DelayedGroupId));
if (Delay == 0) {
// Force early dispatch point
DelayedDispatchDispatcher (DelayedDispatchTable, NULL);
}
Status = EFI_SUCCESS;
Exit:
return Status;
}
/**
DelayedDispatchDispatcher
Delayed Dispach cycle (ie one pass) through each entry, calling functions when their
time has expired. When DelayedGroupId is specified, if there are any of the specified entries
in the dispatch queue during dispatch, repeat the DelayedDispatch cycle.
@param DelayedDispatchTable Pointer to dispatch table
@param OPTIONAL DelayedGroupId used to insure particular time is met.
@return BOOLEAN
**/
BOOLEAN
DelayedDispatchDispatcher (
IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable,
IN EFI_GUID *DelayedGroupId OPTIONAL
)
{
BOOLEAN Dispatched;
UINT64 TimeCurrent;
UINT64 MaxDispatchTime;
UINTN Index1;
BOOLEAN DelayedGroupIdPresent;
DELAYED_DISPATCH_ENTRY *Entry;
EFI_STATUS Status;
Dispatched = FALSE;
DelayedGroupIdPresent = TRUE;
Status = SafeUint64Add (GET_TIME_IN_US (), FixedPcdGet32 (PcdDelayedDispatchCompletionTimeoutUs), &MaxDispatchTime);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Delay overflow\n", __func__));
return FALSE;
}
while ((DelayedDispatchTable->Count > 0) && (DelayedGroupIdPresent)) {
DelayedGroupIdPresent = FALSE;
DelayedDispatchTable->DispCount++;
// If dispatching is messed up, clear DelayedDispatchTable and exit.
TimeCurrent = GET_TIME_IN_US ();
if (TimeCurrent > MaxDispatchTime) {
DEBUG ((DEBUG_ERROR, "%a - DelayedDispatch Completion timeout!\n", __func__));
ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE), (EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABORTED));
ASSERT (FALSE);
DelayedDispatchTable->Count = 0;
break;
}
// Check each entry in the table for possible dispatch
for (Index1 = 0; Index1 < DelayedDispatchTable->Count;) {
Entry = &DelayedDispatchTable->Entry[Index1];
// If DelayedGroupId is present, insure there is an additional check of the table.
if (DelayedGroupId != NULL) {
if (CompareGuid (DelayedGroupId, &Entry->DelayedGroupId)) {
DelayedGroupIdPresent = TRUE;
}
}
TimeCurrent = GET_TIME_IN_US ();
if (TimeCurrent >= Entry->DispatchTime) {
// Time expired, invoked the function
DEBUG ((
DEBUG_ERROR,
"Delayed dispatch entry %d @ %p, Target=%d, Act=%d Disp=%d\n",
Index1,
Entry->Function,
Entry->DispatchTime,
TimeCurrent,
DelayedDispatchTable->DispCount
));
Dispatched = TRUE;
Entry->MicrosecondDelay = 0;
Entry->Function (
&Entry->Context,
&Entry->MicrosecondDelay
);
DEBUG ((DEBUG_ERROR, "Delayed dispatch Function returned delay=%d\n", Entry->MicrosecondDelay));
if (Entry->MicrosecondDelay == 0) {
// NewTime = 0 = delete this entry from the table
DelayedDispatchTable->Count--;
CopyMem (Entry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY) * (DelayedDispatchTable->Count - Index1));
} else {
if (Entry->MicrosecondDelay > FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs)) {
DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d requested\n", __func__, Entry->MicrosecondDelay));
ASSERT (FALSE);
Entry->MicrosecondDelay = FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs);
}
// NewTime != 0 - update the time from us to Dispatch time
Status = SafeUint64Add (GET_TIME_IN_US (), Entry->MicrosecondDelay, &Entry->DispatchTime);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Delay overflow, this event will likely never be fired...\n", __func__));
Entry->DispatchTime = MAX_UINT64;
}
Index1++;
}
} else {
Index1++;
}
}
}
return Dispatched;
}
/**
Wait on a registered Delayed Dispatch unit that has a DelayedGroupId. Continue
to dispatch all registered delayed dispatch entries until *ALL* entries with
DelayedGroupId have completed.
Example usage:
1. Register a Delayed Dispatch entry with a DelayedGroupId.
2. Call this function with the DelayedGroupId
3. The registered function in #1 will be called after the specified delay.
4. This function will wait until all entries with the DelayedGroupId have completed.
@param[in] This The Delayed Dispatch PPI pointer.
@param[in] DelayedGroupId Delayed dispatch request ID the caller will wait on
@retval EFI_SUCCESS The operation succeeds.
@retval EFI_INVALID_PARAMETER The parameters are invalid.
**/
EFI_STATUS
EFIAPI
PeiDelayedDispatchWaitOnEvent (
IN EFI_DELAYED_DISPATCH_PPI *This,
IN EFI_GUID DelayedGroupId
)
{
PERF_FUNCTION_BEGIN ();
EFI_STATUS Status;
DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
// Get delayed dispatch table
DelayedDispatchTable = GetDelayedDispatchTable ();
if (DelayedDispatchTable == NULL) {
DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__));
Status = EFI_UNSUPPORTED;
goto Exit;
}
if (IsZeroGuid (&DelayedGroupId)) {
DEBUG ((DEBUG_ERROR, "%a Delayed Group ID is a null GUID\n", __func__));
Status = EFI_UNSUPPORTED;
goto Exit;
}
DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=%d, DispatchCount=%d\n", &DelayedGroupId, DelayedDispatchTable->Count, DelayedDispatchTable->DispCount));
PERF_EVENT_SIGNAL_BEGIN (&DelayedGroupId);
DelayedDispatchDispatcher (DelayedDispatchTable, &DelayedGroupId);
PERF_EVENT_SIGNAL_END (&DelayedGroupId);
Status = EFI_SUCCESS;
Exit:
PERF_FUNCTION_END ();
return Status;
}
/**
DelayedDispatch End of PEI callback function. Insure that all of the delayed dispatch
entries are complete before exiting PEI.
@param[in] PeiServices - Pointer to PEI Services Table.
@param[in] NotifyDesc - Pointer to the descriptor for the Notification event that
caused this function to execute.
@param[in] Ppi - Pointer to the PPI data associated with this function.
@retval EFI_STATUS - Always return EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
PeiDelayedDispatchOnEndOfPei (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
)
{
DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
// Get delayed dispatch table
DelayedDispatchTable = GetDelayedDispatchTable ();
if (DelayedDispatchTable == NULL) {
DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__));
return EFI_UNSUPPORTED;
}
PERF_INMODULE_BEGIN ("PerfDelayedDispatchEndOfPei");
while (DelayedDispatchTable->Count > 0) {
DelayedDispatchDispatcher (DelayedDispatchTable, NULL);
}
DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n", __func__, DelayedDispatchTable->DispCount));
PERF_INMODULE_END ("PerfDelayedDispatchEndOfPei");
return EFI_SUCCESS;
}
/**
Discover all PEIMs and optional Apriori file in one FV. There is at most one
Apriori file in one FV.
@ -347,7 +715,7 @@ PeiLoadFixAddressHook (
// Note: Here is a assumption that system memory should always be healthy even without test.
//
if ((NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
(((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0))
(((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute) & (~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0))
{
//
// See if the memory range described in ResourceHob and NextResourceHob is adjacent
@ -1426,12 +1794,38 @@ PeiDispatcher (
EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
EFI_FV_FILE_INFO FvFileInfo;
PEI_CORE_FV_HANDLE *CoreFvHandle;
EFI_HOB_GUID_TYPE *GuidHob;
UINT32 TableSize;
PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps;
PeimEntryPoint = NULL;
PeimFileHandle = NULL;
EntryPoint = 0;
if (Private->DelayedDispatchTable == NULL) {
GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid);
if (GuidHob != NULL) {
Private->DelayedDispatchTable = (DELAYED_DISPATCH_TABLE *)(GET_GUID_HOB_DATA (GuidHob));
} else {
TableSize = sizeof (DELAYED_DISPATCH_TABLE) + ((DELAYED_DISPATCH_MAX_ENTRIES - 1) * sizeof (DELAYED_DISPATCH_ENTRY));
Private->DelayedDispatchTable = BuildGuidHob (&gEfiDelayedDispatchTableGuid, TableSize);
if (Private->DelayedDispatchTable != NULL) {
ZeroMem (Private->DelayedDispatchTable, TableSize);
Status = PeiServicesInstallPpi (&mDelayedDispatchDesc);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Failed to install Delayed Dispatch PPI: %r!\n", __func__, Status));
ASSERT_EFI_ERROR (Status);
} else {
Status = PeiServicesNotifyPpi (&mDelayedDispatchNotifyDesc);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Failed to notify Delayed Dispatch on End of Pei: %r!\n", __func__, Status));
ASSERT_EFI_ERROR (Status);
}
}
}
}
}
if ((Private->PeiMemoryInstalled) &&
(PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
(Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
@ -1682,6 +2076,13 @@ PeiDispatcher (
}
}
}
// Dispatch pending delalyed dispatch requests
if (Private->DelayedDispatchTable != NULL) {
if (DelayedDispatchDispatcher (Private->DelayedDispatchTable, NULL)) {
ProcessDispatchNotifyList (Private);
}
}
}
//

View File

@ -11,6 +11,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <PiPei.h>
#include <Ppi/DxeIpl.h>
#include <Ppi/DelayedDispatch.h>
#include <Ppi/EndOfPeiPhase.h>
#include <Ppi/MemoryDiscovered.h>
#include <Ppi/StatusCode.h>
#include <Ppi/Reset.h>
@ -42,10 +44,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <IndustryStandard/PeImage.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/TimerLib.h>
#include <Library/SafeIntLib.h>
#include <Guid/FirmwareFileSystem2.h>
#include <Guid/FirmwareFileSystem3.h>
#include <Guid/AprioriFileName.h>
#include <Guid/MigratedFvInfo.h>
#include <Guid/DelayedDispatch.h>
///
/// It is an FFS type extension used for PeiFindFileEx. It indicates current
@ -208,6 +213,23 @@ EFI_STATUS
#define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C')
//
// Converts elapsed ticks of performance counter to time in microseconds.
// This macro converts the elapsed ticks of running performance counter to
// time value in unit of microseconds.
//
// NOTE: To support Delayed Dispatch functionality, the timer ticks are required
// to be:
// 1. A 64bit register;
// 2. Guaranteed to be monotonically increasing from 0;
// 3. Not wrapped throughout the duration of a boot;
//
// The requirement above is set to avoid the timer overflow issue to keep the
// Delayed Dispatch meet the PI specification with minimal change (instead of
// implementing a control-yielding multi-threaded PEI core).
//
#define GET_TIME_IN_US() ((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter ()), 1000))
///
/// Pei Core private data structure instance
///
@ -308,6 +330,11 @@ struct _PEI_CORE_INSTANCE {
// Those Memory Range will be migrated into physical memory.
//
HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER];
//
// Table of delayed dispatch requests
//
DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
};
///
@ -2028,4 +2055,47 @@ PeiReinitializeFv (
IN PEI_CORE_INSTANCE *PrivateData
);
/**
Register a callback to be called after a minimum delay has occurred.
@param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI instance
@param[in] Function Function to call back
@param[in] Context Context data
@param[in] DelayedGroupId Delayed dispatch request ID the caller will wait on
@param[in] Delay Delay interval
@retval EFI_SUCCESS Function successfully loaded
@retval EFI_INVALID_PARAMETER One of the Arguments is not supported
@retval EFI_OUT_OF_RESOURCES No more entries
**/
EFI_STATUS
EFIAPI
PeiDelayedDispatchRegister (
IN EFI_DELAYED_DISPATCH_PPI *This,
IN EFI_DELAYED_DISPATCH_FUNCTION Function,
IN UINT64 Context,
IN EFI_GUID *DelayedGroupId OPTIONAL,
IN UINT32 Delay
);
/**
Wait on a registered Delayed Dispatch unit that has a DelayedGroupId. Continue
to dispatch all registered delayed dispatch entries until *ALL* entries with
DelayedGroupId have completed.
@param[in] This The Delayed Dispatch PPI pointer.
@param[in] DelayedGroupId Delayed dispatch request ID the caller will wait on
@retval EFI_SUCCESS Function successfully invoked
@retval EFI_INVALID_PARAMETER One of the Arguments is not supported
**/
EFI_STATUS
EFIAPI
PeiDelayedDispatchWaitOnEvent (
IN EFI_DELAYED_DISPATCH_PPI *This,
IN EFI_GUID DelayedGroupId
);
#endif

View File

@ -66,6 +66,8 @@
PeCoffLib
PeiServicesTablePointerLib
PcdLib
TimerLib
SafeIntLib
[Guids]
gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File
@ -79,6 +81,7 @@
gStatusCodeCallbackGuid
gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB
gEdkiiMigrationInfoGuid ## SOMETIMES_CONSUMES ## HOB
gEfiDelayedDispatchTableGuid ## SOMETIMES_PRODUCES ## HOB
[Ppis]
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
@ -102,6 +105,8 @@
gEfiSecHobDataPpiGuid ## SOMETIMES_CONSUMES
gEfiPeiCoreFvLocationPpiGuid ## SOMETIMES_CONSUMES
gEdkiiPeiMigrateTempRamPpiGuid ## PRODUCES
gEfiPeiDelayedDispatchPpiGuid ## PRODUCES
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES
@ -114,6 +119,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs ## CONSUMES
# [BootMode]
# S3_RESUME ## SOMETIMES_CONSUMES

View File

@ -282,6 +282,9 @@ PeiCore (
OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset);
}
// Force relocating the dispatch table
OldCoreData->DelayedDispatchTable = NULL;
//
// Fixup for PeiService's address
//

View File

@ -0,0 +1,47 @@
/** @file
Definition for structure & defines exported by Delayed Dispatch PPI
Copyright (c), Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef DELAYED_DISPATCH_H_
#define DELAYED_DISPATCH_H_
// Delayed Dispatch table GUID
#define EFI_DELAYED_DISPATCH_TABLE_GUID {\
0x4b733449, 0x8eff, 0x488c, { 0x92, 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07 } \
}
//
// Maximal number of Delayed Dispatch entries supported
//
#define DELAYED_DISPATCH_MAX_ENTRIES 8
//
// Internal structure for delayed dispatch entries.
// Packing the structures here to save space as they will be stored as HOBs.
//
#pragma pack (push, 1)
typedef struct {
EFI_GUID DelayedGroupId;
UINT64 Context;
EFI_DELAYED_DISPATCH_FUNCTION Function;
UINT64 DispatchTime;
UINT32 MicrosecondDelay;
} DELAYED_DISPATCH_ENTRY;
typedef struct {
UINT32 Count;
UINT32 DispCount;
DELAYED_DISPATCH_ENTRY Entry[DELAYED_DISPATCH_MAX_ENTRIES];
} DELAYED_DISPATCH_TABLE;
#pragma pack (pop)
extern EFI_GUID gEfiDelayedDispatchTableGuid;
#endif

View File

@ -488,6 +488,9 @@
## Include/Guid/MmCommBuffer.h
gMmCommBufferHobGuid = { 0x6c2a2520, 0x0131, 0x4aee, { 0xa7, 0x50, 0xcc, 0x38, 0x4a, 0xac, 0xe8, 0xc6 }}
## Include/Guid/DelayedDispatch.h
gEfiDelayedDispatchTableGuid = { 0x4b733449, 0x8eff, 0x488c, { 0x92, 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07 }}
[Ppis]
## Include/Ppi/FirmwareVolumeShadowPpi.h
gEdkiiPeiFirmwareVolumeShadowPpiGuid = { 0x7dfe756c, 0xed8d, 0x4d77, {0x9e, 0xc4, 0x39, 0x9a, 0x8a, 0x81, 0x51, 0x16 } }
@ -1041,6 +1044,14 @@
# @ValidList 0x80000006 | 0x03058002
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
## Delayed Dispatch Maximum Delay in us (microseconds)
# Maximum delay for any particular delay request - 5 seconds
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|5000000|UINT32|0x3000104A
## Delayed Dispatch timeout in us (microseconds)
# Maximum delay when waiting for completion (ie EndOfPei) - 10 seconds
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs|10000000|UINT32|0x3000104B
## Mask to control the NULL address detection in code for different phases.
# If enabled, accessing NULL address in UEFI or SMM code can be caught.<BR><BR>
# BIT0 - Enable NULL pointer detection for UEFI.<BR>