Hi Liming, I updated this patch to use macro definition and incorporated other changes as you suggested in v2. Could you please review when you have a chance? Any input is appreciated. Regards, Kun On 10/6/2023 10:13 PM, gaoliming via groups.io wrote: > > Kun: > >  For this usage, this PCD is not required. We can update the code > logic to avoid new PCD. You can set the default PPI number for current > usage. If so, PPI number will not be increased. > > Thanks > > Liming > > *发件人:*devel@edk2.groups.io *代表 *Kun Qin > *发送时间:*2023年10月4日22:54 > *收件人:*devel@edk2.groups.io; gaoliming@byosoft.com.cn > *抄送:*'Jian J Wang' ; 'Dandan Bi' > ; 'Debkumar De' ; > 'Catharine West' ; 'Mike Turner' > > *主题:*Re: 回复: [edk2-devel] 回复: [PATCH v1 3/4] MdeModulePkg: PeiMain: > Introduce implementation of delayed dispatch > > Hi Liming, > > Sorry for the delayed response on this patch. I went on leave while > collecting opinions regarding your feedback. > > The concern we have for increasing the entry number during boot time > is that this PPI is designed to be available at pre-mem phase. The > practical usage would be a small number of platforms just needing an > additional one or two slots, which we think this is ideal for a build > time PCD. Could you please let us know how you think? > > Thanks, > Kun > > On 8/1/2023 10:15 PM, gaoliming via groups.io wrote: > > Kun: > > PcdDelayedDispatchMaxEntries is not required. The required Entry > number can be increased at boot time. You can see MaxFvCount in > PrivateData that is increased by FV_GROWTH_STEP > > Thanks > > Liming > > *发件人:*devel@edk2.groups.io > *代表 *Kun Qin > *发送时间:*2023年8月1日12:16 > *收件人:*devel@edk2.groups.io; gaoliming@byosoft.com.cn > *抄送:*'Jian J Wang' > ; 'Dandan Bi' > ; 'Debkumar De' > ; 'Catharine > West' > ; 'Mike Turner' > > *主题:*Re: [edk2-devel] 回复: [PATCH v1 3/4] MdeModulePkg: PeiMain: > Introduce implementation of delayed dispatch > > Hi Liming, > > Thanks for the feedback. > > Per your feedback (I suggest to define MACRO in PeiCore for them. > If there is real usage model, new PCD can be introduced later.) on > the following new PCDs: > > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries > > Given this feature has been used internally at Project MU for a > while, I > collected some feedback from the consumer platforms: > > - Delayed dispatch is a feature that can be used for power up > sequence, and > thus the value of maximum entries in this case can depend on the > number of PCI > devices on the platform, and thus hardcoding the value as a macro > definition will > limit the usage and we might come to update it very soon. > > - There is already usage on our platforms that would override the > timeout PCDs > to based on the firmware builds. For example, on a test build, we > might register extra > entries to the PPI and thus extend the completion timeout. > > I agree with your comments on other fronts. Please let me know if > you have further > concerns regarding the PCDs above. I can send out an updated > version after your input > on those. > > Thanks, > Kun > > On 7/24/2023 7:17 PM, gaoliming via groups.io wrote: > > Kun: > >   I add my comments below. > > -----邮件原件----- > > 发件人: Kun Qin > > 发送时间: 2023年7月21日5:07 > > 收件人: devel@edk2.groups.io > > 抄送: Jian J Wang > ; Dandan Bi > > ; Liming > Gao > ; > > Debkumar De > ; Catharine West > > > ; Mike Turner > > > 主题: [PATCH v1 3/4] 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 > > > Cc: Dandan Bi > > > Cc: Liming Gao > > > Cc: Debkumar De > > > Cc: Catharine West > > > Co-authored-by: Mike Turner > > > Signed-off-by: Kun Qin > > > --- > > MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 353 > > ++++++++++++++++++++ > > MdeModulePkg/Core/Pei/PeiMain/PeiMain.c       |   3 + > > MdeModulePkg/Core/Pei/PeiMain.h               |  76 +++++ > > MdeModulePkg/Core/Pei/PeiMain.inf             |   7 + > > MdeModulePkg/MdeModulePkg.dec                 |  15 + > > 5 files changed, 454 insertions(+) > > diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > > b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > > index 5f32ebb560ae..50e59bdbe732 100644 > > --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > > +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > > @@ -3,12 +3,339 @@ > > Copyright (c) 2006 - 2019, Intel Corporation. All rights > reserved.
> > (C) Copyright 2016 Hewlett Packard Enterprise Development > LP
> > +Copyright (c) Microsoft Corporation. > > SPDX-License-Identifier: BSD-2-Clause-Patent > > **/ > > #include "PeiMain.h" > > +/** > > +  DelayedDispatchDispatcher > > + > > +  ayed Dispach cycle (ie one pass) through each entry, > calling functions > > when their > > +  e has expired.  When UniqueId is specified, if there > are any of the > > specified entries > > +  the dispatch queue during dispatch, repeat the > DelayedDispatch cycle. > > + > > [Liming] Above comments are incomplete. Please update. > > +  @param DelayedDispatchTable  Pointer to dispatch table > > +  @param OPTIONAL              UniqueId used to insure > particular > > time is met. > > + > > +  @return BOOLEAN > > +**/ > > +BOOLEAN > > +DelayedDispatchDispatcher ( > > +  IN DELAYED_DISPATCH_TABLE  *DelayedDispatchTable, > > +  IN EFI_GUID                *UniqueId           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, > PeiDelayedDispatchWaitOnUniqueId }; > > +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 (NULL == GuidHob) { > > +    DEBUG ((DEBUG_ERROR, "Delayed Dispatch PPI ERROR - > Delayed > > Dispatch Hob not available.\n")); > > +    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] UniqueId       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                       *UniqueId   OPTIONAL, > > +  IN  UINT32                         Delay > > +  ) > > +{ > > +  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable; > > +  DELAYED_DISPATCH_ENTRY  *Entry; > > + > > +  // Check input parameters > > +  if ((NULL == Function) || (Delay > FixedPcdGet32 > > (PcdDelayedDispatchMaxDelayUs)) || (NULL == This)) { > > +    DEBUG ((DEBUG_ERROR, "%a Invalid parameter\n", > __func__)); > > +    return EFI_INVALID_PARAMETER; > > +  } > > + > > +  // Get delayed dispatch table > > +  DelayedDispatchTable = GetDelayedDispatchTable (); > > +  if (NULL == DelayedDispatchTable) { > > +    DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch > table\n", > > __func__)); > > +    return EFI_UNSUPPORTED; > > +  } > > + > > +  // Check for available entry slots > > +  if (DelayedDispatchTable->Count >= FixedPcdGet32 > > (PcdDelayedDispatchMaxEntries)) { > > +    ASSERT (DelayedDispatchTable->Count < FixedPcdGet32 > > (PcdDelayedDispatchMaxEntries)); > > +    DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n", > > __func__)); > > +    return EFI_OUT_OF_RESOURCES; > > +  } > > + > > +  Entry               = > > &(DelayedDispatchTable->Entry[DelayedDispatchTable->Count]); > > +  Entry->Function     = Function; > > +  Entry->Context      = Context; > > +  Entry->DispatchTime = GET_TIME_IN_US () + Delay; > > +  if (NULL != UniqueId) { > > +    CopyGuid (&Entry->UniqueId, UniqueId); > > +  } else { > > +    ZeroMem (&Entry->UniqueId, sizeof (EFI_GUID)); > > +  } > > + > > +  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%08lx\n", > Entry->Context)); > > +  DEBUG ((DEBUG_INFO, "    Function = %p\n", > Entry->Function)); > > +  DEBUG ((DEBUG_INFO, "    GuidHandle = %g\n", > &(Entry->UniqueId))); > > + > > +  if (0 == Delay) { > > +    // Force early dispatch point > > +    DelayedDispatchDispatcher (DelayedDispatchTable, NULL); > > +  } > > + > > +  return EFI_SUCCESS; > > +} > > + > > +/** > > +  DelayedDispatchDispatcher > > + > > +  ayed Dispach cycle (ie one pass) through each entry, > calling functions > > when their > > +  e has expired.  When UniqueId is specified, if there > are any of the > > specified entries > > +  the dispatch queue during dispatch, repeat the > DelayedDispatch cycle. > > + > > +  @param DelayedDispatchTable  Pointer to dispatch table > > +  @param OPTIONAL              UniqueId used to insure > particular > > time is met. > > + > > +  @return BOOLEAN > > +**/ > > +BOOLEAN > > +DelayedDispatchDispatcher ( > > +  IN DELAYED_DISPATCH_TABLE  *DelayedDispatchTable, > > +  IN EFI_GUID                *UniqueId           OPTIONAL > > +  ) > > +{ > > +  BOOLEAN                 Dispatched; > > +  UINT32                  TimeCurrent; > > +  UINT32                  MaxDispatchTime; > > +  UINTN                   Index1; > > +  BOOLEAN                 UniqueIdPresent; > > +  DELAYED_DISPATCH_ENTRY  *Entry; > > + > > +  Dispatched      = FALSE; > > +  UniqueIdPresent = TRUE; > > +  MaxDispatchTime = GET_TIME_IN_US () + FixedPcdGet32 > > (PcdDelayedDispatchCompletionTimeoutUs); > > +  while ((DelayedDispatchTable->Count > 0) && > (UniqueIdPresent)) { > > +    UniqueIdPresent = 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 UniqueId is present, insure there is an > additional check of > > the > > table. > > +      if (NULL != UniqueId) { > > +        if (CompareGuid (UniqueId, &Entry->UniqueId)) { > > +          UniqueIdPresent = 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 (0 == Entry->MicrosecondDelay) { > > +          // 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 > > +          Entry->DispatchTime =  GET_TIME_IN_US () + > > Entry->MicrosecondDelay; > > +          Index1++; > > +        } > > +      } else { > > +        Index1++; > > +      } > > +    } > > +  } > > + > > +  return Dispatched; > > +} > > + > > +/** > > +  Wait on a registered Delayed Dispatch unit that has a > UniqueId. > > Continue > > +  to dispatch all registered delayed dispatch entries > until *ALL* entries > > with > > +  UniqueId have completed. > > + > > +  @param[in]     This            The Delayed Dispatch PPI > pointer. > > +  @param[in]     UniqueId        UniqueId of delayed > dispatch entry. > > + > > +  @retval EFI_SUCCESS            The operation succeeds. > > +  @retval EFI_INVALID_PARAMETER  The parameters are invalid. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiDelayedDispatchWaitOnUniqueId ( > > +  IN EFI_DELAYED_DISPATCH_PPI  *This, > > +  IN EFI_GUID                  *UniqueId > > +  ) > > +{ > > +  PERF_FUNCTION_BEGIN (); > > +  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable; > > + > > +  // Get delayed dispatch table > > +  DelayedDispatchTable = GetDelayedDispatchTable (); > > +  if (NULL == DelayedDispatchTable) { > > +    PERF_FUNCTION_END (); > > +    return EFI_UNSUPPORTED; > > +  } > > + > > +  if ((NULL == UniqueId) || (IsZeroGuid (UniqueId))) { > > +    ASSERT (FALSE); > > +    PERF_FUNCTION_END (); > > +    return EFI_UNSUPPORTED; > > +  } > > + > > +  DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=%d, > > DispatchCount=%d\n", UniqueId, DelayedDispatchTable->Count, > > DelayedDispatchTable->DispCount)); > > +  PERF_EVENT_SIGNAL_BEGIN (UniqueId); > > +  DelayedDispatchDispatcher (DelayedDispatchTable, UniqueId); > > +  PERF_EVENT_SIGNAL_END (UniqueId); > > + > > +  PERF_FUNCTION_END (); > > +  return EFI_SUCCESS; > > +} > > + > > +/** > > +  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 (NULL == DelayedDispatchTable) { > > +    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 > > @@ -1365,12 +1692,31 @@ 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 (NULL == Private->DelayedDispatchTable) { > > +    GuidHob = GetFirstGuidHob > (&gEfiDelayedDispatchTableGuid); > > +    if (NULL != GuidHob) { > > +      Private->DelayedDispatchTable = (DELAYED_DISPATCH_TABLE > > *)(GET_GUID_HOB_DATA (GuidHob)); > > +    } else { > > +      TableSize                     = sizeof > > (DELAYED_DISPATCH_TABLE) + ((FixedPcdGet32 > > (PcdDelayedDispatchMaxEntries) - 1) * sizeof > (DELAYED_DISPATCH_ENTRY)); > > +      Private->DelayedDispatchTable = BuildGuidHob > > (&gEfiDelayedDispatchTableGuid, TableSize); > > +      if (NULL != Private->DelayedDispatchTable) { > > +        ZeroMem (Private->DelayedDispatchTable, TableSize); > > +        Status = PeiServicesInstallPpi > (&mDelayedDispatchDesc); > > +        ASSERT_EFI_ERROR (Status); > > +        Status = PeiServicesNotifyPpi > (&mDelayedDispatchNotifyDesc); > > +        ASSERT_EFI_ERROR (Status); > > +      } > > +    } > > +  } > > + > >    if ((Private->PeiMemoryInstalled) && > >        (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || > >         (Private->HobList.HandoffInformationTable->BootMode != > > BOOT_ON_S3_RESUME) || > > @@ -1621,6 +1967,13 @@ PeiDispatcher ( > >              } > >            } > >          } > > + > > +        // Dispatch pending delalyed dispatch requests > > +        if (NULL != Private->DelayedDispatchTable) { > > +          if (DelayedDispatchDispatcher > (Private->DelayedDispatchTable, > > NULL)) { > > +            ProcessDispatchNotifyList (Private); > > +          } > > +        } > >        } > >        // > > diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > > b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > > index bf1719d7941a..e5643adf7027 100644 > > --- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > > +++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > > @@ -277,6 +277,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 > >        // > > diff --git a/MdeModulePkg/Core/Pei/PeiMain.h > > b/MdeModulePkg/Core/Pei/PeiMain.h > > index 556beddad533..3b8bbe7f25a1 100644 > > --- a/MdeModulePkg/Core/Pei/PeiMain.h > > +++ b/MdeModulePkg/Core/Pei/PeiMain.h > > @@ -11,6 +11,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > #include > > #include > > +#include > > +#include > > #include > > #include > > #include > > @@ -41,6 +43,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -207,6 +210,29 @@ EFI_STATUS > > #define PEI_CORE_HANDLE_SIGNATURE  > SIGNATURE_32('P','e','i','C') > > +#define GET_TIME_IN_US() > > ((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter > ()), > > 1000)) > > + > > +// > > +// Internal structure for delayed dispatch entries. > > +// > > +#pragma pack (push, 1) > > + > > +typedef struct { > > +  EFI_GUID                         UniqueId; > > +  UINT64                           Context; > > +  EFI_DELAYED_DISPATCH_FUNCTION    Function; > > +  UINT32                           DispatchTime; > > +  UINT32                           MicrosecondDelay; > > +} DELAYED_DISPATCH_ENTRY; > > + > > +typedef struct { > > +  UINT32                    Count; > > +  UINT32                    DispCount; > > +  DELAYED_DISPATCH_ENTRY    Entry[1];     // Actual size > based on > > PCD PcdDelayedDispatchMaxEntries; > > +} DELAYED_DISPATCH_TABLE; > > + > > +#pragma pack (pop) > > + > > /// > > /// Pei Core private data structure instance > > /// > > @@ -307,6 +333,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; > > }; > > /// > > @@ -2038,4 +2069,49 @@ PeiReinitializeFv ( > >    IN  PEI_CORE_INSTANCE  *PrivateData > >    ); > > +/** > > +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] UniqueId       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                       *UniqueId   OPTIONAL, > > +  IN  UINT32                         Delay > > +  ); > > + > > +/** > > +  Wait on a registered Delayed Dispatch unit that has a > UniqueId. > > Continue > > +  to dispatch all registered delayed dispatch entries > until *ALL* entries > > with > > +  UniqueId have completed. > > + > > +  @param[in]     This            The Delayed Dispatch PPI > pointer. > > +  @param[in]     UniqueId        UniqueId of delayed > dispatch entry. > > + > > +  @retval EFI_SUCCESS            The operation succeeds. > > +  @retval EFI_INVALID_PARAMETER  The parameters are invalid. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiDelayedDispatchWaitOnUniqueId ( > > +  IN EFI_DELAYED_DISPATCH_PPI  *This, > > +  IN EFI_GUID                  *UniqueId > > +  ); > > + > > #endif > > diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf > > b/MdeModulePkg/Core/Pei/PeiMain.inf > > index 0cf357371a16..73738c939ac7 100644 > > --- a/MdeModulePkg/Core/Pei/PeiMain.inf > > +++ b/MdeModulePkg/Core/Pei/PeiMain.inf > > @@ -66,6 +66,7 @@ [LibraryClasses] > >    PeCoffLib > >    PeiServicesTablePointerLib > >    PcdLib > > +  TimerLib > > [Guids] > >    gPeiAprioriFileNameGuid       ## SOMETIMES_CONSUMES   > ## File > > @@ -78,6 +79,7 @@ [Guids] > >    gEfiFirmwareFileSystem3Guid > >    gStatusCodeCallbackGuid > >    gEdkiiMigratedFvInfoGuid                      ## > > SOMETIMES_PRODUCES     ## HOB > > +  gEfiDelayedDispatchTableGuid                  ## > > SOMETIMES_PRODUCES     ## HOB > > [Ppis] > >    gEfiPeiStatusCodePpiGuid                      ## > > SOMETIMES_CONSUMES # PeiReportStatusService is not ready > if this PPI > > doesn't exist > > @@ -100,6 +102,8 @@ [Ppis] > >    gEfiPeiReset2PpiGuid                          ## > > SOMETIMES_CONSUMES > >    gEfiSecHobDataPpiGuid                         ## > > SOMETIMES_CONSUMES > >    gEfiPeiCoreFvLocationPpiGuid                  ## > > SOMETIMES_CONSUMES > > +  gEfiPeiDelayedDispatchPpiGuid                 ## > > SOMETIMES_CONSUMES > > [Liming] Here should PRODUCES. > > +  gEfiEndOfPeiSignalPpiGuid                     ## CONSUMES > > [Pcd] > >    gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize > > ## CONSUMES > > @@ -112,6 +116,9 @@ [Pcd] > >    gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot > > ## CONSUMES > >    gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack > > ## CONSUMES > > gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolu > > mes      ## CONSUMES > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs > > ## CONSUMES > > + > > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout > > Us      ## CONSUMES > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries > > ## CONSUMES > > # [BootMode] > > # S3_RESUME             ## SOMETIMES_CONSUMES > > diff --git a/MdeModulePkg/MdeModulePkg.dec > > b/MdeModulePkg/MdeModulePkg.dec > > index 0ff058b0a9da..2f4bd2f2b773 100644 > > --- a/MdeModulePkg/MdeModulePkg.dec > > +++ b/MdeModulePkg/MdeModulePkg.dec > > @@ -418,6 +418,9 @@ [Guids] > >    ## Include/Guid/MigratedFvInfo.h > >    gEdkiiMigratedFvInfoGuid = { 0xc1ab12f7, 0x74aa, > 0x408d, { 0xa2, 0xf4, > > 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } } > > +  ## Delayed Dispatch table GUID > > +  gEfiDelayedDispatchTableGuid = { 0x4b733449, 0x8eff, > 0x488c, {0x92, > > 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07}} > > + > > [Liming] This GUID is only used in PeiMain. I suggest to > define the global > > GUID variable in PeiCore for this usage. > >    # > >    # GUID defined in UniversalPayload > >    # > > @@ -991,6 +994,18 @@ [PcdsFixedAtBuild] > >    # @ValidList  0x80000006 | 0x03058002 > > gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|U > > INT32|0x30001040 > > +  ## Delayed Dispatch Maximum Delay in us (microseconds) > > +  # Maximum delay for any particular delay request - 5 > seconds > > + > > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|500000 > > 0|UINT32|0x3000104A > > + > > +  ## Delayed Dispatch timeout in us (microseconds) > > +  # Maximum delay when waiting for completion (ie > EndOfPei) - 10 seconds > > + > > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout > > Us|10000000|UINT32|0x3000104B > > + > > +  ## Delayed Dispatch Max Entries > > +  # Maximum number of delayed dispatch entries > > + > > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries|8|UINT3 > > 2|0x3000104C > > + > > [Liming] I suggest to define MACRO in PeiCore for them. If > there is real > > usage model, new PCD can be introduced later. > > Thanks > > Liming > >    ## 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.

> >    #    BIT0    - Enable NULL pointer detection for UEFI.
> > -- > > 2.41.0.windows.2 > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#109471): https://edk2.groups.io/g/devel/message/109471 Mute This Topic: https://groups.io/mt/101812406/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-