From nobody Sat May 18 10:07:50 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+109379+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+109379+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1696655649; cv=none; d=zohomail.com; s=zohoarc; b=Kg5CI27yNDzhkfmlijbwWUfF4/YHS/BqfNV63rU803+FJAqZsrCYJvvcf57HjQIW3wukVSCdpgkmftpolcweG75g6htRelGFN7vxVIiy7NuXIThncneDIdxf2QWjQQyy3MSiWji7wpkUl2inEYxRJLIEuiHk2Im1+H/pOnrob7M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1696655649; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=ivxR0K84dSI2cml61xx0FFITwPzTQpVzI+0JkWWRRtc=; b=A+dSa9eG2NbkbWw6RKtFt6lhwYNOUKpI5rJ4zCm1TCqpAopuQEzJRdIC+2yKnUt7Mfl+p0V84dWeuQX7nVwZT/1FtOGkVE2enpCUUK8WnK2rSwSHJ0dFH8q8VlXZL52KvIRY9T/74Cb1ut/JMlEqcEkiBmZQ2EUB8UGXoIrTXQE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+109379+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1696655649557711.4077301244578; Fri, 6 Oct 2023 22:14:09 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=qLBhusEYYq6ch8IdUrtCsiTdGdSakyMYoZ4ZCt2acYc=; c=relaxed/simple; d=groups.io; h=From:To:Cc:References:In-Reply-To:Subject:Date:Message-ID:MIME-Version:Thread-Index:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type:Content-Language; s=20140610; t=1696655649; v=1; b=gsuQ1ikjBubIdlCPDiZWFFs+Cd0f25MY+cruJBl1M5oMkd+LlLof2/jcKHFw0FYP5P+wC9dX RO5zdrW2BvKjZVZaZ3CXSa77YvzRLzW/PF9HQffykwKquBmaU+JdLVSNwoYa6XIhlEOSMkqeD8h FzA2DU0OL9bbBXX0meGR5JJI= X-Received: by 127.0.0.2 with SMTP id QaQ7YY1788612xQJdPaDhq4R; Fri, 06 Oct 2023 22:14:09 -0700 X-Received: from cxsh.intel-email.com (cxsh.intel-email.com [121.46.250.151]) by mx.groups.io with SMTP id smtpd.web10.12808.1696655643997276257 for ; Fri, 06 Oct 2023 22:14:08 -0700 X-Received: from cxsh.intel-email.com (localhost [127.0.0.1]) by cxsh.intel-email.com (Postfix) with ESMTP id CCD4DDDA7B4 for ; Sat, 7 Oct 2023 13:14:00 +0800 (CST) X-Received: from localhost (localhost [127.0.0.1]) by cxsh.intel-email.com (Postfix) with ESMTP id C6BFBDDA7F0 for ; Sat, 7 Oct 2023 13:14:00 +0800 (CST) X-Received: from mail.byosoft.com.cn (mail.byosoft.com.cn [58.240.74.242]) by cxsh.intel-email.com (Postfix) with SMTP id 5F8AEDDA7F5 for ; Sat, 7 Oct 2023 13:13:57 +0800 (CST) X-Received: from DESKTOPS6D0PVI ([58.246.60.130]) (envelope-sender ) by 192.168.6.13 with ESMTP(SSL) for ; Sat, 07 Oct 2023 13:13:40 +0800 X-WM-Sender: gaoliming@byosoft.com.cn X-Originating-IP: 58.246.60.130 X-WM-AuthFlag: YES X-WM-AuthUser: gaoliming@byosoft.com.cn From: "gaoliming via groups.io" To: , Cc: "'Jian J Wang'" , "'Dandan Bi'" , "'Debkumar De'" , "'Catharine West'" , "'Mike Turner'" References: <20230720210729.774-1-kuqin12@gmail.com> <20230720210729.774-4-kuqin12@gmail.com> <01b901d9be9e$21a964c0$64fc2e40$@byosoft.com.cn> <003c01d9c500$5dcf2a30$196d7e90$@byosoft.com.cn> In-Reply-To: Subject: =?UTF-8?B?5Zue5aSNOiDlm57lpI06IFtlZGsyLWRldmVsXSDlm57lpI06IFtQQVRDSCB2MSAzLzRdIE1kZU1vZHVsZVBrZzogUGVpTWFpbjogSW50cm9kdWNlIGltcGxlbWVudGF0aW9uIG9mIGRlbGF5ZWQgZGlzcGF0Y2g=?= Date: Sat, 7 Oct 2023 13:13:37 +0800 Message-ID: <080201d9f8dd$09132210$1b396630$@byosoft.com.cn> MIME-Version: 1.0 Thread-Index: AQHmQqk72a+h6fM/RhcnPsN27NW3TwNcSvR8AbusGHUBstOTygGeRpATAtS6huevy0S1gA== Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,gaoliming@byosoft.com.cn List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: eSfJy4jusgUi8yoPizbqsaR8x1787277AA= Content-Type: multipart/alternative; boundary="----=_NextPart_000_0803_01D9F920.17433350" Content-Language: zh-cn X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1696655651099100001 ------=_NextPart_000_0803_01D9F920.17433350 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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.=20 =20 Thanks Liming =E5=8F=91=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io = =E4=BB=A3=E8=A1=A8 Kun Qin =E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2023=E5=B9=B410=E6=9C=884=E6=97=A5 22= :54 =E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io; gaoliming@byosoft.com.cn =E6=8A=84=E9=80=81: 'Jian J Wang' ; 'Dandan Bi' ; 'Debkumar De' ; 'Catharine West' = ; 'Mike Turner' =E4=B8=BB=E9=A2=98: Re: =E5=9B=9E=E5=A4=8D: [edk2-devel] =E5=9B=9E=E5=A4=8D= : [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce implementation of delayed= dispatch =20 Hi Liming, Sorry for the delayed response on this patch. I went on leave while collect= ing opinions regarding your feedback. The concern we have for increasing the entry number during boot time is tha= t this PPI is designed to be available at pre-mem phase. The practical usag= e would be a small number of platforms just needing an additional one or tw= o slots, which we think this is ideal for a build time PCD. Could you pleas= e 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 ca= n be increased at boot time. You can see MaxFvCount in PrivateData that is = increased by FV_GROWTH_STEP =20 Thanks Liming =E5=8F=91=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io =E4=BB=A3=E8=A1= =A8 Kun Qin =E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2023=E5=B9=B48=E6=9C=881=E6=97=A5 12:= 16 =E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io ; gaoliming@byosoft.com.cn =20 =E6=8A=84=E9=80=81: 'Jian J Wang' ; 'Dandan Bi' ; 'Debkumar De' = ; 'Catharine West' ; 'Mike Turner' =E4=B8=BB=E9=A2=98: Re: [edk2-devel] =E5=9B=9E=E5=A4=8D: [PATCH v1 3/4] Mde= ModulePkg: PeiMain: Introduce implementation of delayed dispatch =20 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:=20 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 definitio= n 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 P= CDs to based on the firmware builds. For example, on a test build, we might reg= ister 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:=20 I add my comments below.=20 =20 -----=E9=82=AE=E4=BB=B6=E5=8E=9F=E4=BB=B6----- =E5=8F=91=E4=BB=B6=E4=BA=BA: Kun Qin =E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2023=E5=B9=B47=E6=9C=8821=E6=97=A5 5:= 07 =E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io =20 =E6=8A=84=E9=80=81: Jian J Wang ; Dandan Bi ; Liming Gao ; Debkumar De ; Cathar= ine West ; Mike Turner = =E4=B8=BB=E9=A2=98: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce impleme= ntation of delayed dispatch =20 REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4496 =20 This change adds the implementation that fits the needs and description of PI spec defined Delayed Dispatch PPI in Pei Core. =20 The PPI would allow minimal delay for registered callbacks. As well as allowing other functions to wait for GUIDed delayed dispatch callbacks. =20 Cc: Jian J Wang Cc: Dandan Bi Cc: Liming Gao Cc: Debkumar De Cc: Catharine West =20 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(+) =20 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 @@ =20 =20 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
=20 (C) Copyright 2016 Hewlett Packard Enterprise Development LP
=20 +Copyright (c) Microsoft Corporation. =20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 =20 =20 **/ =20 =20 =20 #include "PeiMain.h" =20 =20 =20 +/** =20 + DelayedDispatchDispatcher =20 + =20 + ayed Dispach cycle (ie one pass) through each entry, calling functions when their =20 + e has expired. When UniqueId is specified, if there are any of the specified entries =20 + the dispatch queue during dispatch, repeat the DelayedDispatch cycle. =20 + =20 [Liming] Above comments are incomplete. Please update.=20 =20 + @param DelayedDispatchTable Pointer to dispatch table =20 + @param OPTIONAL UniqueId used to insure particular time is met. =20 + =20 + @return BOOLEAN =20 +**/ =20 +BOOLEAN =20 +DelayedDispatchDispatcher ( =20 + IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable, =20 + IN EFI_GUID *UniqueId OPTIONAL =20 + ); =20 + =20 +/** =20 + DelayedDispatch End of PEI callback function. Insure that all of the delayed dispatch =20 + entries are complete before exiting PEI. =20 + =20 + @param[in] PeiServices - Pointer to PEI Services Table. =20 + @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that =20 + caused this function to execute. =20 + @param[in] Ppi - Pointer to the PPI data associated with this function. =20 + =20 + @retval EFI_STATUS - Always return EFI_SUCCESS =20 +**/ =20 +EFI_STATUS =20 +EFIAPI =20 +PeiDelayedDispatchOnEndOfPei ( =20 + IN EFI_PEI_SERVICES **PeiServices, =20 + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, =20 + IN VOID *Ppi =20 + ); =20 + =20 +EFI_DELAYED_DISPATCH_PPI mDelayedDispatchPpi =3D { PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnUniqueId }; =20 +EFI_PEI_PPI_DESCRIPTOR mDelayedDispatchDesc =3D { =20 + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), =20 + &gEfiPeiDelayedDispatchPpiGuid, =20 + &mDelayedDispatchPpi =20 +}; =20 + =20 +EFI_PEI_NOTIFY_DESCRIPTOR mDelayedDispatchNotifyDesc =3D { =20 + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, =20 + &gEfiEndOfPeiSignalPpiGuid, =20 + PeiDelayedDispatchOnEndOfPei =20 +}; =20 + =20 +/** =20 + Helper function to look up DELAYED_DISPATCH_TABLE published in HOB. =20 + =20 + @return Pointer to DELAYED_DISPATCH_TABLE from HOB =20 +**/ =20 +DELAYED_DISPATCH_TABLE * =20 +GetDelayedDispatchTable ( =20 + VOID =20 + ) =20 +{ =20 + EFI_HOB_GUID_TYPE *GuidHob; =20 + =20 + GuidHob =3D GetFirstGuidHob (&gEfiDelayedDispatchTableGuid); =20 + if (NULL =3D=3D GuidHob) { =20 + DEBUG ((DEBUG_ERROR, "Delayed Dispatch PPI ERROR - Delayed Dispatch Hob not available.\n")); =20 + ASSERT (FALSE); =20 + return NULL; =20 + } =20 + =20 + return (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob); =20 +} =20 + =20 +/** =20 +Register a callback to be called after a minimum delay has occurred. =20 + =20 +This service is the single member function of the EFI_DELAYED_DISPATCH_PPI =20 + =20 + @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI instance =20 + @param[in] Function Function to call back =20 + @param[in] Context Context data =20 + @param[in] UniqueId GUID for this Delayed Dispatch request. =20 + @param[in] Delay Delay interval =20 + =20 + @retval EFI_SUCCESS Function successfully loaded =20 + @retval EFI_INVALID_PARAMETER One of the Arguments is not supported =20 + @retval EFI_OUT_OF_RESOURCES No more entries =20 + =20 +**/ =20 +EFI_STATUS =20 +EFIAPI =20 +PeiDelayedDispatchRegister ( =20 + IN EFI_DELAYED_DISPATCH_PPI *This, =20 + IN EFI_DELAYED_DISPATCH_FUNCTION Function, =20 + IN UINT64 Context, =20 + IN EFI_GUID *UniqueId OPTIONAL, =20 + IN UINT32 Delay =20 + ) =20 +{ =20 + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; =20 + DELAYED_DISPATCH_ENTRY *Entry; =20 + =20 + // Check input parameters =20 + if ((NULL =3D=3D Function) || (Delay > FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs)) || (NULL =3D=3D This)) { =20 + DEBUG ((DEBUG_ERROR, "%a Invalid parameter\n", __func__)); =20 + return EFI_INVALID_PARAMETER; =20 + } =20 + =20 + // Get delayed dispatch table =20 + DelayedDispatchTable =3D GetDelayedDispatchTable (); =20 + if (NULL =3D=3D DelayedDispatchTable) { =20 + DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__)); =20 + return EFI_UNSUPPORTED; =20 + } =20 + =20 + // Check for available entry slots =20 + if (DelayedDispatchTable->Count >=3D FixedPcdGet32 (PcdDelayedDispatchMaxEntries)) { =20 + ASSERT (DelayedDispatchTable->Count < FixedPcdGet32 (PcdDelayedDispatchMaxEntries)); =20 + DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n", __func__)); =20 + return EFI_OUT_OF_RESOURCES; =20 + } =20 + =20 + Entry =3D &(DelayedDispatchTable->Entry[DelayedDispatchTable->Count]); =20 + Entry->Function =3D Function; =20 + Entry->Context =3D Context; =20 + Entry->DispatchTime =3D GET_TIME_IN_US () + Delay; =20 + if (NULL !=3D UniqueId) { =20 + CopyGuid (&Entry->UniqueId, UniqueId); =20 + } else { =20 + ZeroMem (&Entry->UniqueId, sizeof (EFI_GUID)); =20 + } =20 + =20 + Entry->MicrosecondDelay =3D Delay; =20 + DelayedDispatchTable->Count++; =20 + =20 + DEBUG ((DEBUG_INFO, "%a Adding dispatch Entry\n", __func__)); =20 + DEBUG ((DEBUG_INFO, " Requested Delay =3D %d\n", Delay)); =20 + DEBUG ((DEBUG_INFO, " Trigger Time =3D %d\n", Entry->DispatchTime)); =20 + DEBUG ((DEBUG_INFO, " Context =3D 0x%08lx\n", Entry->Context)); =20 + DEBUG ((DEBUG_INFO, " Function =3D %p\n", Entry->Function)); =20 + DEBUG ((DEBUG_INFO, " GuidHandle =3D %g\n", &(Entry->UniqueId))); =20 + =20 + if (0 =3D=3D Delay) { =20 + // Force early dispatch point =20 + DelayedDispatchDispatcher (DelayedDispatchTable, NULL); =20 + } =20 + =20 + return EFI_SUCCESS; =20 +} =20 + =20 +/** =20 + DelayedDispatchDispatcher =20 + =20 + ayed Dispach cycle (ie one pass) through each entry, calling functions when their =20 + e has expired. When UniqueId is specified, if there are any of the specified entries =20 + the dispatch queue during dispatch, repeat the DelayedDispatch cycle. =20 + =20 + @param DelayedDispatchTable Pointer to dispatch table =20 + @param OPTIONAL UniqueId used to insure particular time is met. =20 + =20 + @return BOOLEAN =20 +**/ =20 +BOOLEAN =20 +DelayedDispatchDispatcher ( =20 + IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable, =20 + IN EFI_GUID *UniqueId OPTIONAL =20 + ) =20 +{ =20 + BOOLEAN Dispatched; =20 + UINT32 TimeCurrent; =20 + UINT32 MaxDispatchTime; =20 + UINTN Index1; =20 + BOOLEAN UniqueIdPresent; =20 + DELAYED_DISPATCH_ENTRY *Entry; =20 + =20 + Dispatched =3D FALSE; =20 + UniqueIdPresent =3D TRUE; =20 + MaxDispatchTime =3D GET_TIME_IN_US () + FixedPcdGet32 (PcdDelayedDispatchCompletionTimeoutUs); =20 + while ((DelayedDispatchTable->Count > 0) && (UniqueIdPresent)) { =20 + UniqueIdPresent =3D FALSE; =20 + DelayedDispatchTable->DispCount++; =20 + =20 + // If dispatching is messed up, clear DelayedDispatchTable and exit. =20 + TimeCurrent =3D GET_TIME_IN_US (); =20 + if (TimeCurrent > MaxDispatchTime) { =20 + DEBUG ((DEBUG_ERROR, "%a - DelayedDispatch Completion timeout!\n", __func__)); =20 + ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE), (EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABORTED)); =20 + ASSERT (FALSE); =20 + DelayedDispatchTable->Count =3D 0; =20 + break; =20 + } =20 + =20 + // Check each entry in the table for possible dispatch =20 + for (Index1 =3D 0; Index1 < DelayedDispatchTable->Count;) { =20 + Entry =3D &(DelayedDispatchTable->Entry[Index1]); =20 + // If UniqueId is present, insure there is an additional check of the table. =20 + if (NULL !=3D UniqueId) { =20 + if (CompareGuid (UniqueId, &Entry->UniqueId)) { =20 + UniqueIdPresent =3D TRUE; =20 + } =20 + } =20 + =20 + TimeCurrent =3D GET_TIME_IN_US (); =20 + if (TimeCurrent >=3D Entry->DispatchTime) { =20 + // Time expired, invoked the function =20 + DEBUG (( =20 + DEBUG_ERROR, =20 + "Delayed dispatch entry %d @ %p, Target=3D%d, Act=3D%d Disp=3D%d\n", =20 + Index1, =20 + Entry->Function, =20 + Entry->DispatchTime, =20 + TimeCurrent, =20 + DelayedDispatchTable->DispCount =20 + )); =20 + Dispatched =3D TRUE; =20 + Entry->MicrosecondDelay =3D 0; =20 + Entry->Function ( =20 + &Entry->Context, =20 + &Entry->MicrosecondDelay =20 + ); =20 + DEBUG ((DEBUG_ERROR, "Delayed dispatch Function returned delay=3D%d\n", Entry->MicrosecondDelay)); =20 + if (0 =3D=3D Entry->MicrosecondDelay) { =20 + // NewTime =3D 0 =3D delete this entry from the table =20 + DelayedDispatchTable->Count--; =20 + CopyMem (Entry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY) * (DelayedDispatchTable->Count - Index1)); =20 + } else { =20 + if (Entry->MicrosecondDelay > FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs)) { =20 + DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d requested\n", __func__, Entry->MicrosecondDelay)); =20 + ASSERT (FALSE); =20 + Entry->MicrosecondDelay =3D FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs); =20 + } =20 + =20 + // NewTime !=3D 0 - update the time from us to Dispatch time =20 + Entry->DispatchTime =3D GET_TIME_IN_US () + Entry->MicrosecondDelay; =20 + Index1++; =20 + } =20 + } else { =20 + Index1++; =20 + } =20 + } =20 + } =20 + =20 + return Dispatched; =20 +} =20 + =20 +/** =20 + Wait on a registered Delayed Dispatch unit that has a UniqueId. Continue =20 + to dispatch all registered delayed dispatch entries until *ALL* entries with =20 + UniqueId have completed. =20 + =20 + @param[in] This The Delayed Dispatch PPI pointer. =20 + @param[in] UniqueId UniqueId of delayed dispatch entry. =20 + =20 + @retval EFI_SUCCESS The operation succeeds. =20 + @retval EFI_INVALID_PARAMETER The parameters are invalid. =20 + =20 +**/ =20 +EFI_STATUS =20 +EFIAPI =20 +PeiDelayedDispatchWaitOnUniqueId ( =20 + IN EFI_DELAYED_DISPATCH_PPI *This, =20 + IN EFI_GUID *UniqueId =20 + ) =20 +{ =20 + PERF_FUNCTION_BEGIN (); =20 + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; =20 + =20 + // Get delayed dispatch table =20 + DelayedDispatchTable =3D GetDelayedDispatchTable (); =20 + if (NULL =3D=3D DelayedDispatchTable) { =20 + PERF_FUNCTION_END (); =20 + return EFI_UNSUPPORTED; =20 + } =20 + =20 + if ((NULL =3D=3D UniqueId) || (IsZeroGuid (UniqueId))) { =20 + ASSERT (FALSE); =20 + PERF_FUNCTION_END (); =20 + return EFI_UNSUPPORTED; =20 + } =20 + =20 + DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=3D%d, DispatchCount=3D%d\n", UniqueId, DelayedDispatchTable->Count, DelayedDispatchTable->DispCount)); =20 + PERF_EVENT_SIGNAL_BEGIN (UniqueId); =20 + DelayedDispatchDispatcher (DelayedDispatchTable, UniqueId); =20 + PERF_EVENT_SIGNAL_END (UniqueId); =20 + =20 + PERF_FUNCTION_END (); =20 + return EFI_SUCCESS; =20 +} =20 + =20 +/** =20 + DelayedDispatch End of PEI callback function. Insure that all of the delayed dispatch =20 + entries are complete before exiting PEI. =20 + =20 + @param[in] PeiServices - Pointer to PEI Services Table. =20 + @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that =20 + caused this function to execute. =20 + @param[in] Ppi - Pointer to the PPI data associated with this function. =20 + =20 + @retval EFI_STATUS - Always return EFI_SUCCESS =20 +**/ =20 +EFI_STATUS =20 +EFIAPI =20 +PeiDelayedDispatchOnEndOfPei ( =20 + IN EFI_PEI_SERVICES **PeiServices, =20 + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, =20 + IN VOID *Ppi =20 + ) =20 +{ =20 + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; =20 + =20 + // Get delayed dispatch table =20 + DelayedDispatchTable =3D GetDelayedDispatchTable (); =20 + if (NULL =3D=3D DelayedDispatchTable) { =20 + return EFI_UNSUPPORTED; =20 + } =20 + =20 + PERF_INMODULE_BEGIN ("PerfDelayedDispatchEndOfPei"); =20 + while (DelayedDispatchTable->Count > 0) { =20 + DelayedDispatchDispatcher (DelayedDispatchTable, NULL); =20 + } =20 + =20 + DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n", __func__, DelayedDispatchTable->DispCount)); =20 + PERF_INMODULE_END ("PerfDelayedDispatchEndOfPei"); =20 + =20 + return EFI_SUCCESS; =20 +} =20 + =20 /** =20 =20 =20 Discover all PEIMs and optional Apriori file in one FV. There is at most one =20 @@ -1365,12 +1692,31 @@ PeiDispatcher ( EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; =20 EFI_FV_FILE_INFO FvFileInfo; =20 PEI_CORE_FV_HANDLE *CoreFvHandle; =20 + EFI_HOB_GUID_TYPE *GuidHob; =20 + UINT32 TableSize; =20 =20 =20 PeiServices =3D (CONST EFI_PEI_SERVICES **)&Private->Ps; =20 PeimEntryPoint =3D NULL; =20 PeimFileHandle =3D NULL; =20 EntryPoint =3D 0; =20 =20 =20 + if (NULL =3D=3D Private->DelayedDispatchTable) { =20 + GuidHob =3D GetFirstGuidHob (&gEfiDelayedDispatchTableGuid); =20 + if (NULL !=3D GuidHob) { =20 + Private->DelayedDispatchTable =3D (DELAYED_DISPATCH_TABLE *)(GET_GUID_HOB_DATA (GuidHob)); =20 + } else { =20 + TableSize =3D sizeof (DELAYED_DISPATCH_TABLE) + ((FixedPcdGet32 (PcdDelayedDispatchMaxEntries) - 1) * sizeof (DELAYED_DISPATCH_ENTRY)); =20 + Private->DelayedDispatchTable =3D BuildGuidHob (&gEfiDelayedDispatchTableGuid, TableSize); =20 + if (NULL !=3D Private->DelayedDispatchTable) { =20 + ZeroMem (Private->DelayedDispatchTable, TableSize); =20 + Status =3D PeiServicesInstallPpi (&mDelayedDispatchDesc); =20 + ASSERT_EFI_ERROR (Status); =20 + Status =3D PeiServicesNotifyPpi (&mDelayedDispatchNotifyDesc); =20 + ASSERT_EFI_ERROR (Status); =20 + } =20 + } =20 + } =20 + =20 if ((Private->PeiMemoryInstalled) && =20 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || =20 (Private->HobList.HandoffInformationTable->BootMode !=3D BOOT_ON_S3_RESUME) || =20 @@ -1621,6 +1967,13 @@ PeiDispatcher ( } =20 } =20 } =20 + =20 + // Dispatch pending delalyed dispatch requests =20 + if (NULL !=3D Private->DelayedDispatchTable) { =20 + if (DelayedDispatchDispatcher (Private->DelayedDispatchTable, NULL)) { =20 + ProcessDispatchNotifyList (Private); =20 + } =20 + } =20 } =20 =20 =20 // =20 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 =3D (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset); =20 } =20 =20 =20 + // Force relocating the dispatch table =20 + OldCoreData->DelayedDispatchTable =3D NULL; =20 + =20 // =20 // Fixup for PeiService's address =20 // =20 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 =20 =20 #include =20 #include =20 +#include =20 +#include =20 #include =20 #include =20 #include =20 @@ -41,6 +43,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include =20 #include =20 #include =20 +#include =20 #include =20 #include =20 #include =20 @@ -207,6 +210,29 @@ EFI_STATUS =20 =20 #define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C') =20 =20 =20 +#define GET_TIME_IN_US() ((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter ()), 1000)) =20 + =20 +// =20 +// Internal structure for delayed dispatch entries. =20 +// =20 +#pragma pack (push, 1) =20 + =20 +typedef struct { =20 + EFI_GUID UniqueId; =20 + UINT64 Context; =20 + EFI_DELAYED_DISPATCH_FUNCTION Function; =20 + UINT32 DispatchTime; =20 + UINT32 MicrosecondDelay; =20 +} DELAYED_DISPATCH_ENTRY; =20 + =20 +typedef struct { =20 + UINT32 Count; =20 + UINT32 DispCount; =20 + DELAYED_DISPATCH_ENTRY Entry[1]; // Actual size based on PCD PcdDelayedDispatchMaxEntries; =20 +} DELAYED_DISPATCH_TABLE; =20 + =20 +#pragma pack (pop) =20 + =20 /// =20 /// Pei Core private data structure instance =20 /// =20 @@ -307,6 +333,11 @@ struct _PEI_CORE_INSTANCE { // Those Memory Range will be migrated into physical memory. =20 // =20 HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER]; =20 + =20 + // =20 + // Table of delayed dispatch requests =20 + // =20 + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; =20 }; =20 =20 =20 /// =20 @@ -2038,4 +2069,49 @@ PeiReinitializeFv ( IN PEI_CORE_INSTANCE *PrivateData =20 ); =20 =20 =20 +/** =20 +Register a callback to be called after a minimum delay has occurred. =20 + =20 +This service is the single member function of the EFI_DELAYED_DISPATCH_PPI =20 + =20 + @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI instance =20 + @param[in] Function Function to call back =20 + @param[in] Context Context data =20 + @param[in] UniqueId GUID for this Delayed Dispatch request. =20 + @param[in] Delay Delay interval =20 + =20 + @retval EFI_SUCCESS Function successfully loaded =20 + @retval EFI_INVALID_PARAMETER One of the Arguments is not supported =20 + @retval EFI_OUT_OF_RESOURCES No more entries =20 + =20 +**/ =20 +EFI_STATUS =20 +EFIAPI =20 +PeiDelayedDispatchRegister ( =20 + IN EFI_DELAYED_DISPATCH_PPI *This, =20 + IN EFI_DELAYED_DISPATCH_FUNCTION Function, =20 + IN UINT64 Context, =20 + IN EFI_GUID *UniqueId OPTIONAL, =20 + IN UINT32 Delay =20 + ); =20 + =20 +/** =20 + Wait on a registered Delayed Dispatch unit that has a UniqueId. Continue =20 + to dispatch all registered delayed dispatch entries until *ALL* entries with =20 + UniqueId have completed. =20 + =20 + @param[in] This The Delayed Dispatch PPI pointer. =20 + @param[in] UniqueId UniqueId of delayed dispatch entry. =20 + =20 + @retval EFI_SUCCESS The operation succeeds. =20 + @retval EFI_INVALID_PARAMETER The parameters are invalid. =20 + =20 +**/ =20 +EFI_STATUS =20 +EFIAPI =20 +PeiDelayedDispatchWaitOnUniqueId ( =20 + IN EFI_DELAYED_DISPATCH_PPI *This, =20 + IN EFI_GUID *UniqueId =20 + ); =20 + =20 #endif =20 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 =20 PeiServicesTablePointerLib =20 PcdLib =20 + TimerLib =20 =20 =20 [Guids] =20 gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File =20 @@ -78,6 +79,7 @@ [Guids] gEfiFirmwareFileSystem3Guid =20 gStatusCodeCallbackGuid =20 gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB =20 + gEfiDelayedDispatchTableGuid ## SOMETIMES_PRODUCES ## HOB =20 =20 =20 [Ppis] =20 gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist =20 @@ -100,6 +102,8 @@ [Ppis] gEfiPeiReset2PpiGuid ## SOMETIMES_CONSUMES =20 gEfiSecHobDataPpiGuid ## SOMETIMES_CONSUMES =20 gEfiPeiCoreFvLocationPpiGuid ## SOMETIMES_CONSUMES =20 + gEfiPeiDelayedDispatchPpiGuid ## SOMETIMES_CONSUMES =20 [Liming] Here should PRODUCES.=20 =20 + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 =20 =20 [Pcd] =20 gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES =20 @@ -112,6 +116,9 @@ [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES =20 gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES =20 =20 gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolu mes ## CONSUMES =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs ## CONSUMES =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout Us ## CONSUMES =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries ## CONSUMES =20 =20 =20 # [BootMode] =20 # S3_RESUME ## SOMETIMES_CONSUMES =20 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 =20 gEdkiiMigratedFvInfoGuid =3D { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf4, 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } } =20 =20 =20 + ## Delayed Dispatch table GUID =20 + gEfiDelayedDispatchTableGuid =3D { 0x4b733449, 0x8eff, 0x488c, {0x92, 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07}} =20 + [Liming] This GUID is only used in PeiMain. I suggest to define the global GUID variable in PeiCore for this usage. =20 =20 # =20 # GUID defined in UniversalPayload =20 # =20 @@ -991,6 +994,18 @@ [PcdsFixedAtBuild] # @ValidList 0x80000006 | 0x03058002 =20 =20 gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|U INT32|0x30001040 =20 =20 =20 + ## Delayed Dispatch Maximum Delay in us (microseconds) =20 + # Maximum delay for any particular delay request - 5 seconds =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|500000 0|UINT32|0x3000104A =20 + =20 + ## Delayed Dispatch timeout in us (microseconds) =20 + # Maximum delay when waiting for completion (ie EndOfPei) - 10 seconds =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout Us|10000000|UINT32|0x3000104B =20 + =20 + ## Delayed Dispatch Max Entries =20 + # Maximum number of delayed dispatch entries =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries|8|UINT3 2|0x3000104C =20 + [Liming] I suggest to define MACRO in PeiCore for them. If there is real usage model, new PCD can be introduced later.=20 =20 Thanks Liming =20 ## Mask to control the NULL address detection in code for different phases. =20 # If enabled, accessing NULL address in UEFI or SMM code can be caught.

=20 # BIT0 - Enable NULL pointer detection for UEFI.
=20 -- 2.41.0.windows.2 =20 =20 =20 =20 =20 =20 =20 =20 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#109379): https://edk2.groups.io/g/devel/message/109379 Mute This Topic: https://groups.io/mt/101812406/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- ------=_NextPart_000_0803_01D9F920.17433350 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

Kun:

=C2=A0F= or this usage, this PCD is not required. We can update the code logic to av= oid new PCD. You can set the default PPI number for current usage. If so, P= PI number will not be increased.

 

Thanks

Liming

<= p class=3DMsoNormal>=E5=8F=91=E4=BB=B6=E4=BA=BA:= devel@edk2.groups.io <devel@edk2.groups.io> =E4=BB=A3=E8=A1= =A8 Kun Qin
=E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2023=E5=B9=B410=E6=9C= =884=E6=97=A5 22:54
= =E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io; gaoliming@byosoft.com.cn
=E6=8A=84= =E9=80=81: 'Jian J Wang' &= lt;jian.j.wang@intel.com>; 'Dandan Bi' <dandan.bi@intel.com>; 'Deb= kumar De' <debkumar.de@intel.com>; 'Catharine West' <catharine.wes= t@intel.com>; 'Mike Turner' <mikeyt@pobox.com>
=E4=B8= =BB=E9=A2=98: Re: = =E5=9B=9E=E5=A4=8D: [edk2-devel] =E5=9B=9E=E5=A4= =8D: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce imp= lementation 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 tha= t this PPI is designed to be available at pre-mem phase. The practical usag= e would be a small number of platforms just needing an additional one or tw= o slots, which we think this is ideal for a build time PCD. Could you pleas= e let us know how you think?

Thanks,
Kun

On 8/1/2023 10:15 PM, gaoliming v= ia groups.io wrote:

Kun:

 PcdDelayedDispatchMaxEntries is not required. The required Ent= ry number can be increased at boot time. You can see MaxFvCount in PrivateD= ata that is increased by FV_GROWTH_STEP

 

Thanks<= /o:p>

Liming

=E5=8F=91=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io <dev= el@edk2.groups.io> =E4=BB=A3=E8=A1=A8 Kun Qin
= =E5=8F= =91=E9=80=81=E6=97=B6=E9=97=B4: 2023= =E5= =B9=B48=E6=9C=881=E6=97= =A5 12:16
=E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io; gaoliming@byosoft.com.cn
=E6=8A=84=E9=80=81: 'Jian J Wang' <jian.j.wang@intel.com>; 'Dandan Bi' <dandan.bi@intel.com>; 'Debkumar = De' <debkumar.de@intel.com><= /a>; 'Catharine West' <catha= rine.west@intel.com>; 'Mike Turner' <mikeyt@pobox.com>
=E4=B8=BB=E9=A2=98: Re: [edk2-devel] =E5=9B=9E= =E5=A4=8D: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introdu= ce implementation of delayed dispatch
=

 =

Hi Liming,

Thanks for th= e 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.) o= n the following new PCDs:

gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedD= ispatchMaxDelayUs
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs<= br>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 se= quence, 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 valu= e as a macro definition will
limit the usage and we might come to update= it very soon.

- There is alread= y usage on our platforms that would override the timeout PCDs
to based o= n the firmware builds. For example, on a test build, we might register extr= a
entries to the PPI and thus extend the completion timeout.

I ag= ree with your comments on other fronts. Please let me know if you have furt= her
concerns regarding the PCDs above. I can send out an updated version= after your input
on those.

Thanks,
Kun

<= div>

On 7/24/2023 7:17 PM, gaoliming= via groups.io wrote:

Kun: 
  I add my comments below. 
 
=
-----=E9=82=AE=E4=BB=B6=E5=8E=9F=E4=BB=B6-----
=E5=8F=91=E4=BB=B6=E4=BA=BA: Kun Qin <kuqin12@gmail.com&=
gt;
=E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2023=E5=B9=B47=E6=9C=88<=
span lang=3DEN-US>21=E6=97=A5 5:07
=E6=94=B6=E4=BB=B6=E4=BA=BA: devel@edk2.groups.io
=
=E6=8A=84=E9=80=81: Jian J Wang <jian.j.wang@intel.com>; Dandan Bi
<dandan.bi@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
Debkumar De <debkumar.de@intel.com>; Catharine West
<c=
atharine.west@intel.com>; Mike Turner <mikeyt@pobox.com>
=E4=B8=BB=E9=
=A2=98: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce =
implementation of
delayed di=
spatch
 
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=
=3D4496
 
This change adds the implementation t=
hat 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 func=
tions to wait for GUIDed delayed dispatch callbacks.
 
Cc: Jian J Wang <jian.j.wan=
g@intel.com>
Cc: Dand=
an Bi <dandan.bi@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn><=
/o:p>
Cc: Debkumar De <debkumar.de@intel.com>=
Cc: Catharine West <catharine.west@intel.com>
 
Co-authored-by: Mike Turner <m=
ikeyt@pobox.com>
Sign=
ed-off-by: Kun Qin <kuqin12@gmail.c=
om>
---
 MdeModulePkg/Core/Pei/Dispatcher/Dispatc=
her.c | 353
++++++++++++++++=
++++
 MdeModulePkg/Core/Pei/=
PeiMain/PeiMain.c       |   3 +
 MdeModulePkg/Core/Pei/PeiMain.=
h             &=
nbsp; |  76 +++++
=
 MdeModulePkg/Core/Pei/PeiMain.inf       =
;      |   7 +
MdeModulePkg/MdeModulePkg.dec    = ;             |=   15 +
 5 files changed=
, 454 insertions(+)
 
diff --git a/MdeModulePkg/Cor=
e/Pei/Dispatcher/Dispatcher.c
b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 5f32ebb560ae..50e59bdbe732 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Di=
spatcher.c
+++ b/MdeModulePk=
g/Core/Pei/Dispatcher/Dispatcher.c
@@ -3,12 +3,339 @@
=
 
 
 Copyright (c) 2006 - 2019, Intel Corporat=
ion. All rights reserved.<BR>
 
 (C) Copyrig=
ht 2016 Hewlett Packard Enterprise Development LP<BR>
 
+Copyright (c) Microsoft Corporation.
 
=
 SPDX-License-Identifier: BSD-2-Clause-Patent
<=
span lang=3DEN-US> 
&nb=
sp;
 =
 **/
 
 <=
/o:p>
 
#include "PeiMain.h"
 
 
 =
+/**
 
+ =
 DelayedDispatchDispatcher
&=
nbsp;
+
 
+  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
spe=
cified entries
 
+  the dispatch queue during =
dispatch, repeat the DelayedDispatch cycle.
 
+
 
<= /blockquote>
[Liming] Above comments are incomplete.=
 Please update. 
 =
+  @param DelayedDispatchTable  Pointe=
r to dispatch table
 
+  @param OPTIONAL =
             Un=
iqueId used to insure particular
time is met.
 
+
<=
span lang=3DEN-US> 
+&n=
bsp; @return BOOLEAN
 <=
o:p>
+**/
=
 
+BOOLEAN
 
+DelayedDispatchDispatcher (
 
<=
span lang=3DEN-US>+  IN DELAYED_DISPATCH_TABLE  *DelayedDispatchT=
able,
 
+  IN EFI_GUID    =
            *UniqueI=
d           OPTIONAL=
 
+  );
 
+
 
+/**
 =
+  DelayedDispatch End of P=
EI callback function. Insure that all of the
delayed dispatch
 
+  entries=
 are complete before exiting PEI.
 
+
 
+  @param[in] PeiServices   - Pointer to PEI Se=
rvices Table.
 
+  @param[in] NotifyDesc =
   - Pointer to the descriptor for the
Notification
event that
 
+     &nbs=
p;            &=
nbsp;          caused this fun=
ction to execute.
 
+  @param[in] Ppi &nb=
sp;         - Pointer to the PPI da=
ta associated with this
func=
tion.
 
+
 
+  @retval=
 EFI_STATUS       - Always return EFI_SUCCESS=
 
+**/
 
+EFI_STATUS<=
/o:p>
 
+EFIAPI
 
+PeiDelayedDispatchO=
nEndOfPei (
 
+  IN EFI_PEI_SERVICES &nbs=
p;         **PeiServices,
 
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
 
=
+  IN VOID      =
            &nb=
sp;    *Ppi
&=
nbsp;
+  );<=
/span>
 
+
 =
+EFI_DELAYED_DISPATCH_PPI  =
mDelayedDispatchPpi  =3D
{ PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnUniqueId };
 
=
+EFI_PEI_PPI_DESCRIPTOR    mDelayedDispat=
chDesc =3D {
 
+  (EFI_PEI_PPI_DESCRIPTOR_PPI =
|
EFI_PEI_PPI_DESCRIPTOR_TER=
MINATE_LIST),
 
+  &gEfiPeiDelayedDispatch=
PpiGuid,
 
+  &mDelayedDispatchPpi
 
=
+};
 =
;
+
<= pre> 
+EFI_PEI_NOTIFY_DESCRIPTOR  mDelayedDispatchNotifyDesc =3D {
 
=
+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LI=
ST,
 =
+  &gEfiEndOfPeiSignalPpiGuid,<=
/o:p>
 
+  PeiDelayedDispatchOnEndOfPei=
 
+};
 
+
 
+/**
 
<= pre>+  Helper function to look up DELAYED_DISPATCH_= TABLE published in HOB.
&nbs=
p;
+
=
 
+  @return Pointer to DELAYED_DISPATCH_TABLE from HOB
 
+**/
 
+DELAYED_DISPATCH_TABLE *<=
/o:p>
 
+GetDelayedDispatchTable ( 
+=
  VOID
 
+  )
 
+=
{
 
+  EFI_HOB_GUID_TYPE  *GuidHob;<=
/o:p>
 
+
 =
;
+  GuidHob =3D GetFir=
stGuidHob (&gEfiDelayedDispatchTableGuid);
=
 
+&=
nbsp; if (NULL =3D=3D GuidHob) {
 
+  &nb=
sp; DEBUG ((DEBUG_ERROR, "Delayed Dispatch PPI ERROR - Delayed
Dispatch Hob not available.\n"=
));
 =
+    ASSERT (FALSE);
 
+    return NULL;
 
+  }
 =
+
 
+  re=
turn (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob);
 
+}
 
+
 
+/**
 
=
+Register a callback to be called after a minimum d=
elay has occurred.
 
+
=
 
+T=
his service is the single member function of the
EFI_DELAYED_DISPATCH_PPI
<=
span lang=3DEN-US> 
+
 
+  @param[in] This    &nb=
sp;      Pointer to the EFI_DELAYED_DISPATCH_PPI
instance
 
+  @param[in] Function       Funct=
ion to call back
 =
+  @param[in] Context =
       Context data
 
+  @param[in] UniqueId       GUID for t=
his Delayed Dispatch request.
 
+  @param[in] =
Delay          Delay interval<=
o:p>
 
+
=
 
+  @retval EFI_S=
UCCESS           &nb=
sp;   Function successfully loaded
 
+&nb=
sp; @retval EFI_INVALID_PARAMETER     One of the Argume=
nts is not
supported
 
=
+  @retval EFI_OUT_OF_RESOURCES   &n=
bsp;  No more entries
&=
nbsp;
+
 
+**/
 =
+EFI_STATUS
 
=
+EFIAPI
 
+PeiDelayedDispatchRegister (<=
/span>
 
+  IN  EFI_DELAYED_DISPATCH_PPI   &=
nbsp;   *This,
&nb=
sp;
+  IN  EFI_DEL=
AYED_DISPATCH_FUNCTION  Function,
 
+  IN=
  UINT64          &n=
bsp;            =
;  Context,
 =
+  IN  EFI_GUID &=
nbsp;           &nbs=
p;         *UniqueId   OP=
TIONAL,
 
+  IN  UINT32   =
             &n=
bsp;        Delay=
 
+  )
 
+{
 
+=
  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable;
 
+  DELAYED_DISPATCH_ENTRY  *Entry;
 
+
 
+  // Check input parameters
 
=
+  if ((NULL =3D=3D Function) || (Delay > FixedP=
cdGet32
(PcdDelayedDispatchM=
axDelayUs)) || (NULL =3D=3D This)) {
 
+  =
;  DEBUG ((DEBUG_ERROR, "%a Invalid parameter\n", __func__))=
;
 
+    return EFI_INVALID_PARAMETE=
R;
 <=
/pre>
+  }
 
+
 
<=
span lang=3DEN-US>+  // Get delayed dispatch table
 
+  DelayedDispatchTable =3D GetDelayedDispatchTable ();<=
/o:p>
 
+  if (NULL =3D=3D DelayedDispatchTable) {
 
+    DEBUG ((DEBUG_ERROR, "%a Unabl= e to locate dispatch table\n",
__func__));
 <=
o:p>
+    return E=
FI_UNSUPPORTED;
 <=
/o:p>
+  }
=
 
+
 
+  // Check for available entry slots
 
+  if (DelayedDispatchTable->Count >=3D=
 FixedPcdGet32
(PcdDelayedDi=
spatchMaxEntries)) {
 <=
o:p>
+    ASSERT (=
DelayedDispatchTable->Count < FixedPcdGet32
(PcdDelayedDispatchMaxEntries));
 
+    DEBUG ((DEBUG_ERROR, "%a Too many entries re=
quested\n",
__func__));=
 
+    return EFI_OUT_OF_RESOURCES;=
 
+  }
 
+=
 
+  Entry       &nbs=
p;       =3D
&(DelayedDispatchTable->Entry[DelayedDispatchTable-&g=
t;Count]);
 =
+  Entry->Function  =
   =3D Function;
&=
nbsp;
+  Entry->Cont=
ext      =3D Context;
=
 
+&=
nbsp; Entry->DispatchTime =3D GET_TIME_IN_US () + Delay;
 
+  if (NULL !=3D UniqueId) {
 
+&nb=
sp;   CopyGuid (&Entry->UniqueId, UniqueId);
 
+  } else {
 
+   =
 ZeroMem (&Entry->UniqueId, sizeof (EFI_GUID));
 
+  }
 <=
/o:p>
+
 
+&nbs=
p; Entry->MicrosecondDelay =3D Delay;
 
+  =
DelayedDispatchTable->Count++;
 
+
 
+  DEBUG ((DEBUG_INFO, "%a  Adding dispatch Ent=
ry\n", __func__));
&nbs=
p;
+  DEBUG ((DEBUG_INF=
O, "    Requested Delay =3D %d\n", Delay));
 
+  DEBUG ((DEBUG_INFO, "    Tr= igger Time =3D %d\n",
E=
ntry->DispatchTime));
&nb=
sp;
+  DEBUG ((DEBUG_IN=
FO, "    Context =3D 0x%08lx\n", Entry->Context=
));
 =
+  DEBUG ((DEBUG_INFO, "  =
;  Function =3D %p\n", Entry->Function));
 
+  DEBUG ((DEBUG_INFO, "    GuidHandle =3D %=
g\n", &(Entry->UniqueId)));
 
+
 
=
+  if (0 =3D=3D Delay) {
 
=
+    // Force early dispatch point
 
+    DelayedDispatchDispatcher (DelayedDispatchTable, NULL)=
;
 
+  }
 
+
 
+  return EFI_SUCCESS;
 
+}
 
+
&=
nbsp;
+/**=
 
+  DelayedDispatchDispatcher
 
+=
 
+  ayed Dispach cycle (ie one pass) through each= entry, calling functions
wh=
en their
 
+  e has expired.  When Unique=
Id is specified, if there are any of the
specified entries
 
+  the dispat=
ch queue during dispatch, repeat the DelayedDispatch cycle.
 
+
 
+  @param DelayedDispatchTable&=
nbsp; Pointer to dispatch table
 
+  @param OP=
TIONAL           &nb=
sp;  UniqueId used to insure particular
time is met.
 
+=
 
+  @return BOOLEAN
 
+**/<=
/span>
 
+BOOLEAN
&nbs=
p;
+DelayedDispatchDispatche=
r (
 =
+  IN DELAYED_DISPATCH_TABLE  *Dela=
yedDispatchTable,
 
+  IN EFI_GUID  =
            &nb=
sp; *UniqueId           O=
PTIONAL
 
+  )
 
+{
 
=
+  BOOLEAN       =
;          Dispatched;
 
=
+  UINT32      &=
nbsp;           TimeCurre=
nt;
 =
+  UINT32     &=
nbsp;            Max=
DispatchTime;
 
+  UINTN   &nbs=
p;            &=
nbsp;  Index1;
 
+  BOOLEAN  &n=
bsp;            =
;  UniqueIdPresent;
&nb=
sp;
+  DELAYED_DISPATCH=
_ENTRY  *Entry;
 <=
o:p>
+
 
=
+  Dispatched      =3D FALSE;
 
+  UniqueIdPresent =3D TRUE;
 
+&nb=
sp; MaxDispatchTime =3D GET_TIME_IN_US () + FixedPcdGet32=
(PcdDelayedDispatchCompletionTimeoutUs);=
 
+  while ((DelayedDispatchTable->Count > 0= ) && (UniqueIdPresent)) {
 
+  &n=
bsp; UniqueIdPresent =3D FALSE;
 
+  &nbs=
p; DelayedDispatchTable->DispCount++;
 
+
 
+    // If dispatching is messed up, cle= ar DelayedDispatchTable and exit.
 
+  &n=
bsp; TimeCurrent =3D  GET_TIME_IN_US ();
<=
span lang=3DEN-US> 
+&n=
bsp;   if (TimeCurrent > MaxDispatchTime) {<=
/pre>
 
+      DEBUG ((DEBUG_ERROR, "%a - De=
layedDispatch Completion
tim=
eout!\n", __func__));
&=
nbsp;
+   &nb=
sp;  ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE),<=
/span>
(EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABOR=
TED));
 
+      ASSERT (FA=
LSE);
 
+      DelayedDisp=
atchTable->Count =3D 0;
&=
nbsp;
+    &n=
bsp; break;
 =
+    }=
 
+
 
+    // Check ea=
ch entry in the table for possible dispatch
 
+&nbs=
p;   for (Index1 =3D 0; Index1 < DelayedDispatchTable->Coun=
t;) {
 
+      Entry =3D &=
amp;(DelayedDispatchTable->Entry[Index1]);
<=
span lang=3DEN-US> 
+&n=
bsp;     // If UniqueId is present, insure there is an =
additional check of
the
table.
=
 
+&=
nbsp;     if (NULL !=3D UniqueId) {
 
+        if (CompareGuid (Uniqu=
eId, &Entry->UniqueId)) {
 
+  &nb=
sp;       UniqueIdPresent =3D TRUE;
 
+        }
 
+      }
 
+=
 
+      TimeCurrent =3D&=
nbsp; GET_TIME_IN_US ();
&nb=
sp;
+    =
;  if (TimeCurrent >=3D Entry->DispatchTime) {=
 
+        // Time expired, invok=
ed the function
 <=
/o:p>
+     &n=
bsp;  DEBUG ((
 
+    &nbs=
p;     DEBUG_ERROR,
 
+ &n=
bsp;        "Delayed dispatch entry=
 %d @ %p, Target=3D%d, Act=3D%d
Disp=3D%d\n",
 =
;
+    &=
nbsp;     Index1,
 
+ &nbs=
p;        Entry->Function,=
 
+          Ent=
ry->DispatchTime,
 <=
o:p>
+    &nb=
sp;     TimeCurrent,
 
+ &=
nbsp;        DelayedDispatchTable->Di=
spCount
 
+      &nbs=
p;   ));
 
+     =
;   Dispatched        &nb=
sp;     =3D TRUE;
 
+ &nbs=
p;      Entry->MicrosecondDelay =3D 0;
 
<=
span lang=3DEN-US>+        Entry->Fun=
ction (
 
+      &nbs=
p;          &Entry->Con=
text,
 
+       =
          &Entry->Micro=
secondDelay
 
+      =
           );<=
/span>
 
+        DEBUG ((DEBUG_ER=
ROR, "Delayed dispatch Function returned
<=
span lang=3DEN-US>delay=3D%d\n", Entry->MicrosecondDelay));
 
=
+        if (0 =3D=3D=
 Entry->MicrosecondDelay) {
 
+   =
;       // NewTime =3D 0 =3D delete this entr=
y from the table
 =
+     &=
nbsp;    DelayedDispatchTable->Count--;=
 
+          CopyMem (E=
ntry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY)
=
* (DelayedDispatchTable->Count - Index1));=
 
+        } else {
 
+         = if (Entry->MicrosecondDelay > FixedPcdGet32
<= pre>(PcdDelayedDispatchMaxDelayUs)) {<= /pre>
 
+           =
; DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d
requested\n", __func__, Entry->Microsecond=
Delay));
 
+      &nb=
sp;     ASSERT (FALSE);
 
+&nbs=
p;           Entry->Mi=
crosecondDelay =3D FixedPcdGet32
(PcdDelayedDispatchMaxDelayUs);
 
+  =
;        }
<=
span lang=3DEN-US> 
+
 
+        &=
nbsp; // NewTime !=3D 0 - update the time from us to Dispatch time
 
<=
span lang=3DEN-US>+          E=
ntry->DispatchTime =3D  GET_TIME_IN_US () +
=
Entry->MicrosecondDelay;
=
 
+          Index1++;
 
+        }
 
+      } else {=
 
+        Index1++;
 
+      }
 
+=
    }
 <=
o:p>
+  }<=
/pre>
 
+
 =
+  return Dispatched;<=
/span>
 
+}
 
+
<=
span lang=3DEN-US> 
+/*=
*
 
+  Wait on a registered Delayed Dispatch u=
nit that has a UniqueId.
Con=
tinue
 
+  to dispatch all registered delayed =
dispatch entries until *ALL* entries
with
 =
+  UniqueId have completed.<=
/o:p>
 
+
 =
;
+  @param[in] &n=
bsp;   This         =
   The Delayed Dispatch PPI pointer.
=
 
+&=
nbsp; @param[in]     UniqueId    &n=
bsp;   UniqueId of delayed dispatch entry.
 
+
 
+  @retval EFI_SUCCESS  &nbs=
p;         The operation succeeds.<=
o:p>
 
+  @retval EFI_INVALID_PARAMETER  The p=
arameters are invalid.
 =
;
+
<= pre> 
+**/
 
+EFI_STATUS
 
+EFI=
API
 =
+PeiDelayedDispatchWaitOnUniqueId (
 
+  IN EFI_DELAYED_DISPATCH_PPI  *This,
 
+  IN EFI_GUID      &nb=
sp;           *UniqueId
 
+  )
 
+{
 
+  PERF_FUNCTION_BEGIN ();
 
=
+  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable;
 
+
 
+  // Get delayed dispatch tabl=
e
 
+  DelayedDispatchTable =3D GetDelayedDisp=
atchTable ();
 
+  if (NULL =3D=3D DelayedDisp=
atchTable) {
 
+    PERF_FUNCTION_EN=
D ();
 
+    return EFI_UNSUPPORTED;=
 
+  }
 
+=
 
+  if ((NULL =3D=3D UniqueId) || (IsZeroGuid (UniqueId=
))) {
 
+    ASSERT (FALSE);
 
=
+    PERF_FUNCTION_END ();
 
+    return EFI_UNSUPPORTED;
 
+  }
 
+
=
 
+&=
nbsp; DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=3D%d,
DispatchCount=3D%d\n", UniqueI=
d, DelayedDispatchTable->Count,
DelayedDispatchTable->DispCount));
=
 
+&=
nbsp; PERF_EVENT_SIGNAL_BEGIN (UniqueId);
 
+ =
 DelayedDispatchDispatcher (DelayedDispatchTable, UniqueId);
 
+  PERF_EVENT_SIGNAL_END (UniqueId);
 
+
 
+  PERF_FUNCTION_END ();
 
+  return EFI_SUCCESS;
 
+}=
 
+
&nbs=
p;
+/**
 
+  DelayedDispatch End of PEI callback function. Insure that all=
 of the
delayed dispatch
 
<= pre>+  entries are complete before exiting PEI.
 
<= pre>+
&nb=
sp;
+  @param[in] PeiSe=
rvices   - Pointer to PEI Services Table.
=
 
+  @param[in] NotifyDesc    - Pointer to the descrip=
tor for the
Not=
ification
event that
=
 
+            =
;            &n=
bsp;    caused this function to execute.
 
+  @param[in] Ppi       &n=
bsp;   - Pointer to the PPI data associated with this<=
/span>
function.
<=
span lang=3DEN-US> 
+
 
+  @retval EFI_STATUS    =
   - Always return EFI_SUCCESS
 
+**/
 
<= pre>+EFI_STATUS
 
+EFIAPI=
 
+PeiDelayedDispatchOnEndOfPei (
 
+  IN EFI_PEI_SERVICES       &=
nbsp;   **PeiServices,
 
+  IN EFI_P=
EI_NOTIFY_DESCRIPTOR  *NotifyDesc,
 
+  I=
N VOID           &nb=
sp;           *Ppi
 
+  )
 
+{
 
+  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable;<=
/o:p>
 
+
 =
;
+  // Get delayed dis=
patch table
 
+  DelayedDispatchTable =3D GetD=
elayedDispatchTable ();
&nbs=
p;
+  if (NULL =3D=3D D=
elayedDispatchTable) {
 =
;
+    return=
 EFI_UNSUPPORTED;
 
+  }
 
+
 
+  PERF_INMODULE_BEGIN ("PerfDel=
ayedDispatchEndOfPei");
 
+  while (Delay=
edDispatchTable->Count > 0) {
 
+  =
;  DelayedDispatchDispatcher (DelayedDispatchTable, NULL);<=
/span>
 
+  }
&nb=
sp;
+
 
+  DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n&=
quot;, __func__,
DelayedDisp=
atchTable->DispCount));
&=
nbsp;
+  PERF_INMODULE_=
END ("PerfDelayedDispatchEndOfPei");
=
 
+<=
o:p>
 
+  return EFI_SUCCESS;
 
+}
 
+
 
 /**
 
=
 
&n=
bsp;
   Discover a=
ll PEIMs and optional Apriori file in one FV. There is at=
most one
=
 
@@ -1365,12 =
+1692,31 @@ PeiDispatcher (
=
   EFI_PEI_FILE_HANDLE     SaveCurrentFileHan=
dle;
 
   EFI_FV_FILE_INFO  &nb=
sp;     FvFileInfo;
 
 &nb=
sp; PEI_CORE_FV_HANDLE      *CoreFvHandle;
 
=
+  EFI_HOB_GUID_TYPE     &=
nbsp; *GuidHob;
 <=
/o:p>
+  UINT32   &=
nbsp;            &nb=
sp; TableSize;
 
 
 
   PeiServices    =3D (CONST EFI_PEI_SERVICES =
**)&Private->Ps;
&nbs=
p;
   PeimEntryPoi=
nt =3D NULL;
 
   PeimFileHandle =3D NULL=
;
 
   EntryPoint    =
 =3D 0;
 
 
 
+  =
if (NULL =3D=3D Private->DelayedDispatchTable) {
=
 
+    GuidHob =3D GetFirstGuidHob (&gEfiDelayedDispatc=
hTableGuid);
 
+    if (NULL !=3D Gu=
idHob) {
 
+      Private-=
>DelayedDispatchTable =3D (DELAYED_DISPATCH_TABLE
*)(GET_GUID_HOB_DATA (GuidHob));=
 
+    } else {
 
+ &nbs=
p;    TableSize       &nb=
sp;            =
 =3D sizeof
(DELAYED_DISPATC=
H_TABLE) + ((FixedPcdGet32
(=
PcdDelayedDispatchMaxEntries) - 1) * sizeof (DELAYED_DISPATCH_ENTRY));=
 
+      Private->DelayedDi= spatchTable =3D BuildGuidHob
(&gEfiDelayedDispatchTableGuid, TableSize);
 
=
+      if (NULL !=3D Private->DelayedDispatchTa=
ble) {
 
+       =
; ZeroMem (Private->DelayedDispatchTable, TableSize);<=
/pre>
 
+        Status =3D PeiServices=
InstallPpi (&mDelayedDispatchDesc);
 
+ &n=
bsp;      ASSERT_EFI_ERROR (Status);
 
+        Status =3D PeiServ=
icesNotifyPpi (&mDelayedDispatchNotifyDesc);
 
=
+        ASSERT_EFI_ERROR (Status);=
 
+      }
 
+    }
 
+  }
 
<=
span lang=3DEN-US>+
 
   if ((Private->=
;PeiMemoryInstalled) &&
 
   =
;    (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||<=
o:p>
 
        (Priva=
te->HobList.HandoffInformationTable->BootMode !=3D<=
/pre>
BOOT_ON_S3_RESUME) ||
<= pre> 
@@ -1621,6 +1967,13 @@ PeiDispatcher (
          &n=
bsp;  }
 
      =
     }
&=
nbsp;
   &nbs=
p;     }
 
+<=
/pre>
 
+        // Dispatch pending de=
lalyed dispatch requests
&nb=
sp;
+    =
;    if (NULL !=3D Private->DelayedDispatchTable) {<=
/o:p>
 
+         = ; if (DelayedDispatchDispatcher (Private->DelayedDispatchTable,
NULL)) {
 
+=
            ProcessD=
ispatchNotifyList (Private);
 
+   &=
nbsp;      }
 
+ &nbs=
p;      }
 
  =
     }
&=
nbsp;
 
 
       //
<= pre> 
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index bf1719d7941a..e5643adf7027 1=
00644
--- a/MdeModulePkg/Cor=
e/Pei/PeiMain/PeiMain.c
+++ =
b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -277,6 +277,9 @@ PeiCore (
         OldCoreDat=
a->TempFileHandles =3D (EFI_PEI_FILE_HANDLE
=
*)((UINT8 *)OldCoreData->TempFileHandles - OldCoreDat=
a->HeapOffset);
 
     =
  }
 
 
 
+ =
     // Force relocating the dispatch table<=
/span>
 
+      OldCoreData->DelayedDispa=
tchTable =3D NULL;
 
+
=
 
&n=
bsp;      //
 
  =
;     // Fixup for PeiService's address
 
       //
<= pre> 
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h
=
b/MdeModulePkg/Core/Pei/PeiMain.h
index 556beddad533..3b8bbe7f25a1 100644=
--- a/MdeModulePkg/Core/Pei/PeiMain.h<=
o:p>
+++ b/MdeModulePkg/Core/Pei/=
PeiMain.h
@@ -11,6 +11,8 @@ =
SPDX-License-Identifier: BSD-2-Clause-Patent
 
&nbs=
p;
 #include <PiPei.h>=
 
 #include <Ppi/DxeIpl.h>=
 
+#include <Ppi/DelayedDispatch.h>
 
=
+#include <Ppi/EndOfPeiPhase.h>
 
 #include &=
lt;Ppi/MemoryDiscovered.h>
 
 #include <Ppi/S=
tatusCode.h>
 <=
/o:p>
 #include <Ppi/Reset.h>
 
<= pre>@@ -41,6 +43,7 @@ SPDX-License-Identifier: BSD-2-Cla= use-Patent
 #include <Ind=
ustryStandard/PeImage.h>
=
 
 #include <Library=
/PeiServicesTablePointerLib.h>
 
 #include <L=
ibrary/MemoryAllocationLib.h>
 
+#include <Li=
brary/TimerLib.h>
 <=
o:p>
 #include <Guid/FirmwareF=
ileSystem2.h>
 =
 #include <Guid/FirmwareFileS=
ystem3.h>
 
 #include <Guid/AprioriFileName.h=
>
 
@@ -207,6 +210,29 @@ EFI_STATUS
 
 
 #defin=
e PEI_CORE_HANDLE_SIGNATURE  SIGNATURE_32('P','e','i','C')<=
/span>
 
 
 =
+#define GET_TIME_IN_US()
((UINT32)DivU64x32(GetTimeInN=
anoSecond(GetPerformanceCounter ()),
1000))
 <=
/o:p>
+
 
+//
 
+// Internal structure for delayed dispatch entrie=
s.
 <=
/pre>
+//
 
+#pragma pack (p=
ush, 1)
 
+
 
+typedef str=
uct {
 
+  EFI_GUID    &nb=
sp;            =
        UniqueId;
 
+  UINT64         &nb=
sp;            =
     Context;
 
+  EFI_DEL=
AYED_DISPATCH_FUNCTION    Function;
<= pre> 
+  UINT32          =
;            &n=
bsp;    DispatchTime;
 
+  UINT=
32            &=
nbsp;           &nbs=
p;  MicrosecondDelay;
&=
nbsp;
+} DELAYED_DISPATCH_EN=
TRY;
 
+
 
+typedef struct =
{
 
+  UINT32     &nb=
sp;            =
  Count;
 
+  UINT32   &nb=
sp;             =
;   DispCount;
 
+  DELAYED_DIS=
PATCH_ENTRY    Entry[1];     // Actual s=
ize based on
PCD PcdDelayedD=
ispatchMaxEntries;
 
+} DELAYED_DISPATCH_TABLE;
 
<= pre>+
&nb=
sp;
+#pragma pack (pop)=
 
+
&nbs=
p;
 ///
 
 /// Pei Core private data structure instance
=
 
 ///
 
@@ -307,6 +333,11 @@ struct _PEI_CORE_INS=
TANCE {
   // Thos=
e Memory Range will be migrated into physical memory.
 
   //
 <=
o:p>
   HOLE_MEMORY_DAT=
A
HoleData[HOLE_MAX_NUMBER];=
 
+
 
+  //
 
+  // Table of delayed dispatch requests
 
+  //
&nb=
sp;
+  DELAYED_DISPATCH=
_TABLE            *D=
elayedDispatchTable;
 <=
o:p>
 };
<= pre> 
 
 
 ///
 
@@ -2038,=
4 +2069,49 @@ PeiReinitializeFv (
   IN  PEI_CORE_INSTANCE  *PrivateData=
 
   );
 
 =
 
+/**
 <=
o:p>
+Register a callback to be c=
alled after a minimum delay has occurred.
 
+<=
/o:p>
 
+This service is the single member function of the
EFI_DELAYED_DISPATCH_PPI
 
+
 =
+  @param[in] This&nbs=
p;          Pointer to the EFI=
_DELAYED_DISPATCH_PPI
instan=
ce
 <=
/pre>
+  @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
 =
;
+
<= pre> 
+  @retval EFI_SUCCESS       &nbs=
p;       Function successfully loaded
 
=
+  @retval EFI_INVALID_PARAMETER   &=
nbsp; One of the Arguments is not
supported
 <=
/o:p>
+  @retval EFI_OUT_OF_RESOUR=
CES      No more entries
 
+
 <=
/pre>
+**/
 
+EFI_STATUS
 
<= pre>+EFIAPI
 
+PeiDelayedDispatc=
hRegister (
 
+  IN  EFI_DELAYED_DISPATCH=
_PPI       *This,
 
+=
  IN  EFI_DELAYED_DISPATCH_FUNCTION  Function,
 
+  IN  UINT64      &nb=
sp;            =
      Context,
 
+  I=
N  EFI_GUID          =
;             *=
UniqueId   OPTIONAL,
 
+  IN  U=
INT32           &nbs=
p;             =
Delay
 
+  );
 
+=
 
+/**
&=
nbsp;
+  Wait on a regi=
stered Delayed Dispatch unit that has a UniqueId.
Continue
 
+  to dispatc=
h all registered delayed dispatch entries until *ALL* entries
with
=
 
+  Uniq=
ueId have completed.
 <=
o:p>
+
 
=
+  @param[in]     This    &nbs=
p;       The Delayed Dispatch PPI pointer.
 
=
+  @param[in]     UniqueId=
        UniqueId of delayed dispatch ent=
ry.
 =
+
 
+  @retval E=
FI_SUCCESS           =
; The operation succeeds.
&n=
bsp;
+  @retval EFI_INV=
ALID_PARAMETER  The parameters are invalid.
 
=
+
 
+**/
 
+EFI_STATUS=
 
+EFIAPI
 
+PeiDelayedDispatch=
WaitOnUniqueId (
 =
+  IN EFI_DELAYED_DISPATCH_=
PPI  *This,
 =
+  IN EFI_GUID  &=
nbsp;           &nbs=
p;   *UniqueId
&nb=
sp;
+  );
 
+
 
 #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
 
   PeiServicesTablePo=
interLib
 
   PcdLib
 
+  TimerLib
 =
;
 
 
 [Guids]
 
   gPeiAprioriFileNam=
eGuid       ## SOMETIMES_CONSUMES  =
 ## File
 
@@ -78,6 +79,7 @@ [Guids]
   gEfiFirmwareFileSystem3Guid
 
   gStatusCodeCallbackGuid
 
   gEdkiiMigratedFvInfoGuid    &=
nbsp;           &nbs=
p;     ##
SOMETIMES_PRODUCES     ## HOB
=
 
+  gEfiDelayedDispatchTableGuid      =
            ##<=
/o:p>
SOMETIMES_PRODUCES  &nb=
sp;  ## HOB
 =
 
 
 [Ppis]
 
   gEfiPeiStatusCodePpiGuid&nb=
sp;            =
         ##
=
SOMETIMES_CONSUMES # PeiReportStatusService is not =
ready if this PPI
doesn't ex=
ist
 =
@@ -100,6 +102,8 @@ [Ppis]<=
/pre>
   gEfiPeiReset2PpiGuid  &=
nbsp;           &nbs=
p;           ##
SOMETIMES_CONSUMES<=
/pre>
 
   gEfiSecHobDataPpiGuid     &n=
bsp;            =
;       ##
SOMETIMES_CONSUMES
 
   gEfi=
PeiCoreFvLocationPpiGuid        &nb=
sp;         ##
SOMETIMES_CONSUMES
<=
span lang=3DEN-US> 
+&n=
bsp; gEfiPeiDelayedDispatchPpiGuid       =
;          ##
SOMETIMES_CONSUMES
 
[Liming] Here should PRODUCES. 
<=
span lang=3DEN-US> 
+  gEfiEndOfPe=
iSignalPpiGuid          &=
nbsp;          ## CONSUMES
 
<= pre> 
 
 [Pcd]
 
   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiS=
tackSize
## CONSUMES
 
=
@@ -112,6 +116,9 @@ [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimO=
nBoot
## CONSUMES=
 
   gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInT=
empStack
## CONSUMES
 
=
 
gE=
fiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolu<=
/span>
mes      ## CO=
NSUMES
 
+  gEfiMdeModulePkgTokenSpaceGuid.Pcd=
DelayedDispatchMaxDelayUs
##=
 CONSUMES
 <=
/span>
+
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeou=
t
Us    =
  ## CONSUMES
 
+  gEfiMdeModulePkgTokenS=
paceGuid.PcdDelayedDispatchMaxEntries
## CONSUMES
 =
 
 
 # [BootMode]
 
 # S3_RESUME   =
;          ## SOMETIMES_CONSUM=
ES
 <=
/pre>
diff --git a/MdeModulePkg/MdeModulePkg.dec
b/MdeModulePkg/MdeModulePkg.dec=
index 0ff058b0a9da..2f4bd2f=
2b773 100644
--- a/MdeModule=
Pkg/MdeModulePkg.dec
+++ b/M=
deModulePkg/MdeModulePkg.dec
@@ -418,6 +418,9 @@ [Guids]
   ## Include/Guid/MigratedFvInfo.h
=
 
&n=
bsp;  gEdkiiMigratedFvInfoGuid =3D { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa=
2, 0xf4,
0xc6, 0xce, 0xfd, 0=
x17, 0x98, 0x71 } }
 
 
 
+  ## Delayed Dispatch table GUID
 
+ =
; gEfiDelayedDispatchTableGuid =3D { 0x4b733449, 0x8eff, 0x488c, {0x92,
0x1a, 0x15, 0x4a, 0xda, 0x25, 0=
x18, 0x07}}
 
+
[Liming] This GUID is only used in PeiMain. I sugg=
est to define the global
GUI=
D variable in PeiCore for this usage.
 
 
   #
 
 &=
nbsp; # GUID defined in UniversalPayload
 
 &n=
bsp; #
 
@@ -991,6 +994,18 @@ [PcdsFixedAtBuild]
   # @ValidList =
; 0x80000006 | 0x03058002
&n=
bsp;
 
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeS=
etVariable|0x03058002|U
INT3=
2|0x30001040
 
 
<=
span lang=3DEN-US> 
+&n=
bsp; ## Delayed Dispatch Maximum Delay in us (microseconds)
 
+  # Maximum delay for any particular delay request - 5 sec=
onds
 
+
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|500000
0|UINT32|0x3000104A<=
/span>
 
+
 =
+  ## Delayed Dispatch time=
out in us (microseconds)
&nb=
sp;
+  # Maximum delay =
when waiting for completion (ie EndOfPei) - 10 seconds
 
+
gEfiMdeModulePkgToke=
nSpaceGuid.PcdDelayedDispatchCompletionTimeout
=
Us|10000000|UINT32|0x3000104B
 
=
+
 
+  ## Delayed Dispatch Max Entries
 
=
+  # Maximum number of delayed dispatch entries
 
<= pre>+
gEf=
iMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries|8|UINT3=
2|0x3000104C
 
+
[Liming] I s=
uggest to define MACRO in PeiCore for them. If there is real
usage model, new PCD can be introduced lat=
er. 
 
Thanks
Liming
 
   ## Mask to control the NULL address=
 detection in code for different
phases.
 
   #  If enabled, acc=
essing NULL address in UEFI or SMM code can be
=
caught.<BR><BR>
=
 
&n=
bsp;  #    BIT0    - Enable NULL pointer=
 detection for UEFI.<BR>
 
--
2.41.0.windows.2
 
 
 
 
 
 
 =
 

_._,_._,_

Groups.io Links:

=20 You receive all messages sent to this group. =20 =20

View/Reply Online (#109379) | =20 | Mute= This Topic | New Topic
Your Subscriptio= n | Contact Group Owner | Unsubscribe [importer@patchew.org]

_._,_._,_
------=_NextPart_000_0803_01D9F920.17433350--