From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.43; helo=mga05.intel.com; envelope-from=jiewen.yao@intel.com; receiver=edk2-devel@lists.01.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3B7692277AF21 for ; Mon, 23 Apr 2018 01:49:20 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 23 Apr 2018 01:49:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,317,1520924400"; d="scan'208";a="50013076" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by orsmga001.jf.intel.com with ESMTP; 23 Apr 2018 01:49:19 -0700 Received: from fmsmsx119.amr.corp.intel.com (10.18.124.207) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 23 Apr 2018 01:49:18 -0700 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by FMSMSX119.amr.corp.intel.com (10.18.124.207) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 23 Apr 2018 01:49:18 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.79]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.210]) with mapi id 14.03.0319.002; Mon, 23 Apr 2018 16:49:16 +0800 From: "Yao, Jiewen" To: "Zeng, Star" , "edk2-devel@lists.01.org" CC: "Yao, Jiewen" Thread-Topic: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Thread-Index: AQHT2tBVBdf5hwc9Xk+0OjMXfja2dKQOCh3g Date: Mon, 23 Apr 2018 08:49:16 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503AB79B07@shsmsx102.ccr.corp.intel.com> References: <1524466601-20812-1-git-send-email-star.zeng@intel.com> In-Reply-To: <1524466601-20812-1-git-send-email-star.zeng@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYjU3NzA5MjQtOGRlNy00MWY2LThjNmUtZjI4ZTlhZTIzMTkyIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJRZ3NPbGRhaHhaUmpGU0RcL2NMcUd0elcxeXFZRmpNZnh1Y3ZhWDFoTlUwNUpFbFNXQ1wvcW5RMVlVTkc2K3JXUFIifQ== x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.0.116 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Apr 2018 08:49:20 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Thanks for the update. Would you please share what unit test has been done for this patch? Thank you Yao Jiewen > -----Original Message----- > From: Zeng, Star > Sent: Monday, April 23, 2018 2:57 PM > To: edk2-devel@lists.01.org > Cc: Zeng, Star ; Yao, Jiewen > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table >=20 > It is the second step for > https://bugzilla.tianocore.org/show_bug.cgi?id=3D540. >=20 > Cc: Jiewen Yao > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Star Zeng > --- > .../Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c | 184 ++++++++++- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 > +++++++++++++++++++-- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- > .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- > 4 files changed, 535 insertions(+), 27 deletions(-) >=20 > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > index ebde93a91eb3..8276aaa0279b 100644 > --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > @@ -272,7 +272,7 @@ FmpSetImage ( > } >=20 > Status =3D MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSiz= e, > &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason); > - DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - > 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > + DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, Status - > 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > VarStatus =3D gRT->SetVariable( > MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME, > &gEfiCallerIdGuid, > @@ -280,7 +280,7 @@ FmpSetImage ( > sizeof(MicrocodeFmpPrivate->LastAttempt), > &MicrocodeFmpPrivate->LastAttempt > ); > - DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus)); > + DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus)); >=20 > if (!EFI_ERROR(Status)) { > InitializeMicrocodeDescriptor(MicrocodeFmpPrivate); > @@ -415,6 +415,159 @@ FmpSetPackageInfo ( > } >=20 > /** > + Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to > high. > + > + @param[in] MicrocodeFmpPrivate private data structure to be initialize= d. > + > +**/ > +VOID > +SortFitMicrocodeInfo ( > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > + ) > +{ > + FIT_MICROCODE_INFO *FitMicrocodeEntry; > + FIT_MICROCODE_INFO *NextFitMicrocodeEntry; > + FIT_MICROCODE_INFO TempFitMicrocodeEntry; > + FIT_MICROCODE_INFO *FitMicrocodeEntryEnd; > + > + FitMicrocodeEntry =3D MicrocodeFmpPrivate->FitMicrocodeInfo; > + NextFitMicrocodeEntry =3D FitMicrocodeEntry + 1; > + FitMicrocodeEntryEnd =3D MicrocodeFmpPrivate->FitMicrocodeInfo + > MicrocodeFmpPrivate->FitMicrocodeEntryCount; > + while (FitMicrocodeEntry < FitMicrocodeEntryEnd) { > + while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) { > + if (FitMicrocodeEntry->MicrocodeEntryPoint > > NextFitMicrocodeEntry->MicrocodeEntryPoint) { > + CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof > (FIT_MICROCODE_INFO)); > + CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof > (FIT_MICROCODE_INFO)); > + CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof > (FIT_MICROCODE_INFO)); > + } > + > + NextFitMicrocodeEntry =3D NextFitMicrocodeEntry + 1; > + } > + > + FitMicrocodeEntry =3D FitMicrocodeEntry + 1; > + NextFitMicrocodeEntry =3D FitMicrocodeEntry + 1; > + } > +} > + > +/** > + Initialize FIT microcode information. > + > + @param[in] MicrocodeFmpPrivate private data structure to be initialize= d. > + > +**/ > +VOID > +InitializeFitMicrocodeInfo ( > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > + ) > +{ > + UINT64 FitPointer; > + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; > + UINT32 EntryNum; > + UINT32 MicrocodeEntryNum; > + UINT32 Index; > + UINTN Address; > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > + UINTN FitMicrocodeIndex; > + MICROCODE_INFO *MicrocodeInfo; > + UINTN MicrocodeIndex; > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL) { > + FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo); > + MicrocodeFmpPrivate->FitMicrocodeInfo =3D NULL; > + MicrocodeFmpPrivate->FitMicrocodeEntryCount =3D 0; > + } > + > + FitPointer =3D *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS; > + if ((FitPointer =3D=3D 0) || > + (FitPointer =3D=3D 0xFFFFFFFFFFFFFFFF) || > + (FitPointer =3D=3D 0xEEEEEEEEEEEEEEEE)) { > + // > + // No FIT table; > + // > + return; > + } > + FitEntry =3D (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer; > + if ((FitEntry[0].Type !=3D FIT_TYPE_00_HEADER) || > + (FitEntry[0].Address !=3D FIT_TYPE_00_SIGNATURE)) { > + // > + // Invalid FIT table; > + // > + return; > + } > + > + EntryNum =3D *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF; > + > + // > + // Calculate microcode entry number. > + // > + MicrocodeEntryNum =3D 0; > + for (Index =3D 0; Index < EntryNum; Index++) { > + if (FitEntry[Index].Type =3D=3D FIT_TYPE_01_MICROCODE) { > + MicrocodeEntryNum++; > + } > + } > + if (MicrocodeEntryNum =3D=3D 0) { > + // > + // No FIT microcode entry. > + // > + return; > + } > + > + MicrocodeFmpPrivate->FitMicrocodeEntryCount =3D MicrocodeEntryNum; > + > + // > + // Allocate buffer. > + // > + MicrocodeFmpPrivate->FitMicrocodeInfo =3D AllocateZeroPool > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); > + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL); > + > + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; > + MicrocodePatchRegionSize =3D > MicrocodeFmpPrivate->MicrocodePatchRegionSize; > + > + // > + // Collect microcode entry info. > + // > + MicrocodeEntryNum =3D 0; > + for (Index =3D 0; Index < EntryNum; Index++) { > + if (FitEntry[Index].Type =3D=3D FIT_TYPE_01_MICROCODE) { > + Address =3D (UINTN) FitEntry[Index].Address; > + ASSERT ((Address >=3D (UINTN) MicrocodePatchAddress) && > + (Address < ((UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize))); > + FitMicrocodeInfo =3D > &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum]; > + FitMicrocodeInfo->MicrocodeEntryPoint =3D (CPU_MICROCODE_HEADER > *) Address; > + if ((*(UINT32 *) Address) =3D=3D 0xFFFFFFFF) { > + // > + // It is the empty slot as long as the first dword is 0xFFFF_FFF= F. > + // > + FitMicrocodeInfo->Empty =3D TRUE; > + } else { > + FitMicrocodeInfo->Empty =3D FALSE; > + } > + MicrocodeEntryNum++; > + } > + } > + > + // > + // Every microcode should have a FIT microcode entry. > + // > + for (MicrocodeIndex =3D 0; MicrocodeIndex < > MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) { > + MicrocodeInfo =3D > &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex]; > + for (FitMicrocodeIndex =3D 0; FitMicrocodeIndex < > MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) { > + FitMicrocodeInfo =3D > &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex]; > + if (MicrocodeInfo->MicrocodeEntryPoint =3D=3D > FitMicrocodeInfo->MicrocodeEntryPoint) { > + FitMicrocodeInfo->InUse =3D MicrocodeInfo->InUse; > + break; > + } > + } > + ASSERT (FitMicrocodeIndex < > MicrocodeFmpPrivate->FitMicrocodeEntryCount); > + } > + > + SortFitMicrocodeInfo (MicrocodeFmpPrivate); > +} > + > +/** > Initialize Processor Microcode Index. >=20 > @param[in] MicrocodeFmpPrivate private data structure to be initialize= d. > @@ -496,6 +649,7 @@ InitializeMicrocodeDescriptor ( > if (MicrocodeFmpPrivate->MicrocodeInfo =3D=3D NULL) { > MicrocodeFmpPrivate->MicrocodeInfo =3D > AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * > sizeof(MICROCODE_INFO)); > if (MicrocodeFmpPrivate->MicrocodeInfo =3D=3D NULL) { > + FreePool (MicrocodeFmpPrivate->ImageDescriptor); > return EFI_OUT_OF_RESOURCES; > } > } > @@ -505,6 +659,8 @@ InitializeMicrocodeDescriptor ( >=20 > InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); >=20 > + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); > + > return EFI_SUCCESS; > } >=20 > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( >=20 > @param[in] MicrocodeFmpPrivate private data structure to be initialize= d. >=20 > - @return EFI_SUCCESS private data is initialized. > + @return EFI_SUCCESS Processor information is initialized. > **/ > EFI_STATUS > InitializeProcessorInfo ( > @@ -583,6 +739,7 @@ DumpPrivateInfo ( > PROCESSOR_INFO *ProcessorInfo; > MICROCODE_INFO *MicrocodeInfo; > EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; >=20 > DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); > DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", > MicrocodeFmpPrivate->ProcessorCount)); > @@ -635,6 +792,22 @@ DumpPrivateInfo ( > DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", > ImageDescriptor[Index].LastAttemptStatus)); > DEBUG((DEBUG_VERBOSE, " HardwareInstance - > 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); > } > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL) { > + DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n")); > + FitMicrocodeInfo =3D MicrocodeFmpPrivate->FitMicrocodeInfo; > + DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", > MicrocodeFmpPrivate->FitMicrocodeEntryCount)); > + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCoun= t; > Index++) { > + DEBUG (( > + DEBUG_INFO, > + " FitMicrocodeInfo[0x%x] - 0x%08x, (0x%x, 0x%x)\n", > + Index, > + FitMicrocodeInfo[Index].MicrocodeEntryPoint, > + FitMicrocodeInfo[Index].InUse, > + FitMicrocodeInfo[Index].Empty > + )); > + } > + } > } >=20 > /** > @@ -671,8 +844,8 @@ InitializePrivateData ( > &VarSize, > &MicrocodeFmpPrivate->LastAttempt > ); > - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); > - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); >=20 > Result =3D > GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, > &MicrocodeFmpPrivate->MicrocodePatchRegionSize); > if (!Result) { > @@ -688,6 +861,7 @@ InitializePrivateData ( >=20 > Status =3D InitializeMicrocodeDescriptor(MicrocodeFmpPrivate); > if (EFI_ERROR(Status)) { > + FreePool (MicrocodeFmpPrivate->ProcessorInfo); > DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status))= ; > return Status; > } > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c > index 2cb0adbc44d5..9098712c2fc8 100644 > --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.= c > +++ > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c > @@ -368,7 +368,7 @@ GetMatchedProcessor ( > On output, the index of target > CPU which matches the Microcode. >=20 > @retval EFI_SUCCESS The Microcode image passes > verification. > - @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt. > + @retval EFI_VOLUME_CORRUPTED The Microcode image is > corrupted. > @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is > incorrect. > @retval EFI_UNSUPPORTED The Microcode ProcessorSignature > or ProcessorFlags is incorrect. > @retval EFI_SECURITY_VIOLATION The Microcode image fails to load. > @@ -550,7 +550,7 @@ VerifyMicrocode ( > } > *LastAttemptStatus =3D > LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION; > if (AbortReason !=3D NULL) { > - *AbortReason =3D > AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), > L"UnsupportedProcessSignature/ProcessorFlags"); > + *AbortReason =3D > AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"), > L"UnsupportedProcessorSignature/ProcessorFlags"); > } > return EFI_UNSUPPORTED; > } > @@ -623,6 +623,124 @@ GetNextMicrocode ( > } >=20 > /** > + Get next FIT Microcode entrypoint. > + > + @param[in] MicrocodeFmpPrivate The Microcode driver private > data > + @param[in] MicrocodeEntryPoint Current Microcode entrypoint > + > + @return next FIT Microcode entrypoint. > +**/ > +CPU_MICROCODE_HEADER * > +GetNextFitMicrocode ( > + IN MICROCODE_FMP_PRIVATE_DATA > *MicrocodeFmpPrivate, > + IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint > + ) > +{ > + UINTN Index; > + > + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; > Index++) { > + if (MicrocodeEntryPoint =3D=3D > MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint) { > + if (Index =3D=3D (UINTN) MicrocodeFmpPrivate->FitMicrocodeEntryCou= nt - > 1) { > + // it is last one > + return NULL; > + } else { > + // return next one > + return MicrocodeFmpPrivate->FitMicrocodeInfo[Index + > 1].MicrocodeEntryPoint; > + } > + } > + } > + > + ASSERT(FALSE); > + return NULL; > +} > + > +/** > + Find empty FIT Microcode entrypoint. > + > + @param[in] MicrocodeFmpPrivate The Microcode driver private > data > + @param[in] ImageSize The size of Microcode image > buffer in bytes. > + @param[out] AvailableSize Available size of the empty FIT > Microcode entrypoint. > + > + @return Empty FIT Microcode entrypoint. > +**/ > +CPU_MICROCODE_HEADER * > +FindEmptyFitMicrocode ( > + IN MICROCODE_FMP_PRIVATE_DATA > *MicrocodeFmpPrivate, > + IN UINTN ImageSize, > + OUT UINTN *AvailableSize > + ) > +{ > + UINTN Index; > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > + CPU_MICROCODE_HEADER > *NextMicrocodeEntryPoint; > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + > + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; > + MicrocodePatchRegionSize =3D > MicrocodeFmpPrivate->MicrocodePatchRegionSize; > + > + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; > Index++) { > + if (MicrocodeFmpPrivate->FitMicrocodeInfo[Index].Empty) { > + MicrocodeEntryPoint =3D > MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint; > + NextMicrocodeEntryPoint =3D GetNextFitMicrocode > (MicrocodeFmpPrivate, MicrocodeEntryPoint); > + if (NextMicrocodeEntryPoint !=3D NULL) { > + *AvailableSize =3D (UINTN) NextMicrocodeEntryPoint - (UINTN) > MicrocodeEntryPoint; > + } else { > + *AvailableSize =3D (UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint; > + } > + if (*AvailableSize >=3D ImageSize) { > + return MicrocodeEntryPoint; > + } > + } > + } > + > + return NULL; > +} > + > +/** > + Find unused FIT Microcode entrypoint. > + > + @param[in] MicrocodeFmpPrivate The Microcode driver private > data > + @param[in] ImageSize The size of Microcode image > buffer in bytes. > + @param[out] AvailableSize Available size of the unused FI= T > Microcode entrypoint. > + > + @return Unused FIT Microcode entrypoint. > +**/ > +CPU_MICROCODE_HEADER * > +FindUnusedFitMicrocode ( > + IN MICROCODE_FMP_PRIVATE_DATA > *MicrocodeFmpPrivate, > + IN UINTN ImageSize, > + OUT UINTN *AvailableSize > + ) > +{ > + UINTN Index; > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > + CPU_MICROCODE_HEADER > *NextMicrocodeEntryPoint; > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + > + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; > + MicrocodePatchRegionSize =3D > MicrocodeFmpPrivate->MicrocodePatchRegionSize; > + > + for (Index =3D 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; > Index++) { > + if (!MicrocodeFmpPrivate->FitMicrocodeInfo[Index].InUse) { > + MicrocodeEntryPoint =3D > MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint; > + NextMicrocodeEntryPoint =3D GetNextFitMicrocode > (MicrocodeFmpPrivate, MicrocodeEntryPoint); > + if (NextMicrocodeEntryPoint !=3D NULL) { > + *AvailableSize =3D (UINTN) NextMicrocodeEntryPoint - (UINTN) > MicrocodeEntryPoint; > + } else { > + *AvailableSize =3D (UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint; > + } > + if (*AvailableSize >=3D ImageSize) { > + return MicrocodeEntryPoint; > + } > + } > + } > + > + return NULL; > +} > + > +/** > Get current Microcode used region size. >=20 > @param[in] MicrocodeFmpPrivate The Microcode driver private > data > @@ -666,7 +784,7 @@ UpdateMicrocode ( >=20 > DEBUG((DEBUG_INFO, "PlatformUpdate:")); > DEBUG((DEBUG_INFO, " Address - 0x%lx,", Address)); > - DEBUG((DEBUG_INFO, " Legnth - 0x%x\n", ImageSize)); > + DEBUG((DEBUG_INFO, " Length - 0x%x\n", ImageSize)); >=20 > Status =3D MicrocodeFlashWrite ( > Address, > @@ -682,6 +800,201 @@ UpdateMicrocode ( > } >=20 > /** > + Update Microcode flash region with FIT. > + > + @param[in] MicrocodeFmpPrivate The Microcode driver private > data > + @param[in] TargetMicrocodeEntryPoint Target Microcode entrypoint to > be updated > + @param[in] Image The Microcode image buffer. > + @param[in] ImageSize The size of Microcode image > buffer in bytes. > + @param[out] LastAttemptStatus The last attempt status, which > will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. > + > + @retval EFI_SUCCESS The Microcode image is written. > + @retval EFI_WRITE_PROTECTED The flash device is read only. > +**/ > +EFI_STATUS > +UpdateMicrocodeFlashRegionWithFit ( > + IN MICROCODE_FMP_PRIVATE_DATA > *MicrocodeFmpPrivate, > + IN CPU_MICROCODE_HEADER > *TargetMicrocodeEntryPoint, > + IN VOID *Image, > + IN UINTN ImageSize, > + OUT UINT32 *LastAttemptStatus > + ) > +{ > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + UINTN TargetTotalSize; > + EFI_STATUS Status; > + VOID > *MicrocodePatchScratchBuffer; > + UINT8 *ScratchBufferPtr; > + UINTN ScratchBufferSize; > + UINTN RestSize; > + UINTN AvailableSize; > + VOID *NextMicrocodeEntryPoint; > + VOID *EmptyFitMicrocodeEntry; > + VOID *UnusedFitMicrocodeEntry; > + > + DEBUG((DEBUG_INFO, "UpdateMicrocodeFlashRegionWithFit: Image - 0x%x, > size - 0x%x\n", Image, ImageSize)); > + > + MicrocodePatchAddress =3D MicrocodeFmpPrivate->MicrocodePatchAddress; > + MicrocodePatchRegionSize =3D > MicrocodeFmpPrivate->MicrocodePatchRegionSize; > + > + MicrocodePatchScratchBuffer =3D AllocateZeroPool > (MicrocodePatchRegionSize); > + if (MicrocodePatchScratchBuffer =3D=3D NULL) { > + DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n")); > + *LastAttemptStatus =3D > LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; > + return EFI_OUT_OF_RESOURCES; > + } > + ScratchBufferPtr =3D MicrocodePatchScratchBuffer; > + ScratchBufferSize =3D 0; > + > + // > + // Target data collection > + // > + TargetTotalSize =3D 0; > + AvailableSize =3D 0; > + if (TargetMicrocodeEntryPoint !=3D NULL) { > + if (TargetMicrocodeEntryPoint->DataSize =3D=3D 0) { > + TargetTotalSize =3D 2048; > + } else { > + TargetTotalSize =3D TargetMicrocodeEntryPoint->TotalSize; > + } > + DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize)); > + NextMicrocodeEntryPoint =3D GetNextFitMicrocode (MicrocodeFmpPrivate= , > TargetMicrocodeEntryPoint); > + DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", > NextMicrocodeEntryPoint)); > + if (NextMicrocodeEntryPoint !=3D NULL) { > + ASSERT ((UINTN) NextMicrocodeEntryPoint >=3D ((UINTN) > TargetMicrocodeEntryPoint + TargetTotalSize)); > + AvailableSize =3D (UINTN) NextMicrocodeEntryPoint - (UINTN) > TargetMicrocodeEntryPoint; > + } else { > + AvailableSize =3D (UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize - (UINTN) TargetMicrocodeEntryPoint; > + } > + DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize)); > + ASSERT (AvailableSize >=3D TargetTotalSize); > + } > + // > + // Total Size means the Microcode size. > + // Available Size means the Microcode size plus the pad till (1) next > Microcode or (2) the end. > + // > + // (1) > + // +------+-----------+-----+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D+ > + // | MCU1 | Microcode | PAD | MCU2 | Empty | > + // +------+-----------+-----+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D+ > + // | TotalSize | > + // |<-AvailableSize->| > + // > + // (2) > + // +------+-----------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D+ > + // | MCU | Microcode | Empty | > + // +------+-----------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D+ > + // | TotalSize | > + // |<- AvailableSize ->| > + // > + > + // > + // Update based on policy > + // > + > + // > + // 1. If there is enough space to update old one in situ, replace old = microcode > in situ. > + // > + if (AvailableSize >=3D ImageSize) { > + DEBUG((DEBUG_INFO, "Replace old microcode in situ\n")); > + // > + // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > + // |Other | Old Image | ... | Empty | > + // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > + // > + // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > + // |Other |New Image|FF| ... | Empty | > + // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > + // > + // 1.1. Copy new image > + CopyMem (ScratchBufferPtr, Image, ImageSize); > + ScratchBufferSize +=3D ImageSize; > + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > + // 1.2. Pad 0xFF > + RestSize =3D AvailableSize - ImageSize; > + if (RestSize > 0) { > + SetMem (ScratchBufferPtr, RestSize, 0xFF); > + ScratchBufferSize +=3D RestSize; > + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > + } > + Status =3D UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, > MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); > + return Status; > + } > + > + // > + // 2. If there is empty FIT microcode entry with enough space, use it. > + // > + EmptyFitMicrocodeEntry =3D FindEmptyFitMicrocode (MicrocodeFmpPrivate, > ImageSize, &AvailableSize); > + if (EmptyFitMicrocodeEntry !=3D NULL) { > + DEBUG((DEBUG_INFO, "Use empty FIT microcode entry\n")); > + // 2.1. Copy new image > + CopyMem (ScratchBufferPtr, Image, ImageSize); > + ScratchBufferSize +=3D ImageSize; > + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > + // 2.2. Pad 0xFF > + RestSize =3D AvailableSize - ImageSize; > + if (RestSize > 0) { > + SetMem (ScratchBufferPtr, RestSize, 0xFF); > + ScratchBufferSize +=3D RestSize; > + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > + } > + Status =3D UpdateMicrocode ((UINTN) EmptyFitMicrocodeEntry, > MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); > + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint !=3D NULL)) { > + // > + // Empty old microcode. > + // > + ScratchBufferPtr =3D MicrocodePatchScratchBuffer; > + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF); > + ScratchBufferSize =3D TargetTotalSize; > + ScratchBufferPtr =3D (UINT8 *) MicrocodePatchScratchBuffer + > ScratchBufferSize; > + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, > MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); > + } > + return Status; > + } > + > + // > + // 3. If there is unused microcode entry with enough space, use it. > + // > + UnusedFitMicrocodeEntry =3D FindUnusedFitMicrocode > (MicrocodeFmpPrivate, ImageSize, &AvailableSize); > + if (UnusedFitMicrocodeEntry !=3D NULL) { > + DEBUG((DEBUG_INFO, "Use unused FIT microcode entry\n")); > + // 3.1. Copy new image > + CopyMem (ScratchBufferPtr, Image, ImageSize); > + ScratchBufferSize +=3D ImageSize; > + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > + // 3.2. Pad 0xFF > + RestSize =3D AvailableSize - ImageSize; > + if (RestSize > 0) { > + SetMem (ScratchBufferPtr, RestSize, 0xFF); > + ScratchBufferSize +=3D RestSize; > + ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > + } > + Status =3D UpdateMicrocode ((UINTN) UnusedFitMicrocodeEntry, > MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); > + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint !=3D NULL)) { > + // > + // Empty old microcode. > + // > + ScratchBufferPtr =3D MicrocodePatchScratchBuffer; > + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF); > + ScratchBufferSize =3D TargetTotalSize; > + ScratchBufferPtr =3D (UINT8 *) MicrocodePatchScratchBuffer + > ScratchBufferSize; > + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, > MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus); > + } > + return Status; > + } > + > + // > + // 4. No usable FIT microcode entry. > + // > + DEBUG((DEBUG_ERROR, "No usable FIT microcode entry\n")); > + *LastAttemptStatus =3D > LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES; > + Status =3D EFI_OUT_OF_RESOURCES; > + > + return Status; > +} > + > +/** > Update Microcode flash region. >=20 > @param[in] MicrocodeFmpPrivate The Microcode driver private > data > @@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion ( > AvailableSize =3D (UINTN)MicrocodePatchAddress + > MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint; > } > DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize)); > + ASSERT (AvailableSize >=3D TargetTotalSize); > } > - ASSERT (AvailableSize >=3D TargetTotalSize); > UsedRegionSize =3D > GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate); > DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize)); > ASSERT (UsedRegionSize >=3D TargetTotalSize); > @@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion ( > ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >=3D > ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize)); > } > // > - // Total Size means the Microcode data size. > - // Available Size means the Microcode data size plus the pad till (1) = next > Microcode or (2) the end. > + // Total Size means the Microcode size. > + // Available Size means the Microcode size plus the pad till (1) next > Microcode or (2) the end. > // > // (1) > // +------+-----------+-----+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D+ > @@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion ( > DEBUG((DEBUG_INFO, "Replace old microcode in situ\n")); > // > // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > - // |Other1| Old Image |Other2| Empty | > + // |Other | Old Image | ... | Empty | > // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > // > // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > - // |Other1|New Image|FF|Other2| Empty | > + // |Other |New Image|FF| ... | Empty | > // +------+---------+--+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D+ > // > // 1.1. Copy new image > @@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion ( > DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n")); > // > // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D+ > - // |Other1| Old Image |Other2| Empty | > + // |Other | Old Image | ... | Empty | > // +------+------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D+ > // > // +------+---------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ > - // |Other1| New Image |Other2| Empty | > + // |Other | New Image | ... | Empty | > // +------+---------------+------+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ > // > // 2.1. Copy new image > @@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion ( > // 2.2. Copy rest images after the old image. > if (NextMicrocodeEntryPoint !=3D 0) { > RestSize =3D (UINTN)MicrocodePatchAddress + UsedRegionSize - > ((UINTN)NextMicrocodeEntryPoint); > - CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + > TargetTotalSize, RestSize); > + CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize); > ScratchBufferSize +=3D RestSize; > ScratchBufferPtr =3D (UINT8 *)MicrocodePatchScratchBuffer + > ScratchBufferSize; > } > @@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion ( > call to FreePool(). >=20 > @retval EFI_SUCCESS The Microcode image is written. > - @retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt. > + @retval EFI_VOLUME_CORRUPTED The Microcode image is > corrupted. > @retval EFI_INCOMPATIBLE_VERSION The Microcode image version is > incorrect. > @retval EFI_SECURITY_VIOLATION The Microcode image fails to load. > @retval EFI_WRITE_PROTECTED The flash device is read only. > @@ -963,7 +1276,6 @@ MicrocodeWrite ( > return EFI_OUT_OF_RESOURCES; > } >=20 > - *LastAttemptVersion =3D ((CPU_MICROCODE_HEADER > *)Image)->UpdateRevision; > TargetCpuIndex =3D (UINTN)-1; > Status =3D VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSiz= e, > TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex); > if (EFI_ERROR(Status)) { > @@ -972,6 +1284,7 @@ MicrocodeWrite ( > return Status; > } > DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n")); > + *LastAttemptVersion =3D ((CPU_MICROCODE_HEADER > *)Image)->UpdateRevision; >=20 > DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex)); > ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount); > @@ -985,13 +1298,23 @@ MicrocodeWrite ( > } > DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", > TargetMicrocodeEntryPoint)); >=20 > - Status =3D UpdateMicrocodeFlashRegion( > - MicrocodeFmpPrivate, > - TargetMicrocodeEntryPoint, > - AlignedImage, > - ImageSize, > - LastAttemptStatus > - ); > + if (MicrocodeFmpPrivate->FitMicrocodeInfo !=3D NULL) { > + Status =3D UpdateMicrocodeFlashRegionWithFit ( > + MicrocodeFmpPrivate, > + TargetMicrocodeEntryPoint, > + AlignedImage, > + ImageSize, > + LastAttemptStatus > + ); > + } else { > + Status =3D UpdateMicrocodeFlashRegion ( > + MicrocodeFmpPrivate, > + TargetMicrocodeEntryPoint, > + AlignedImage, > + ImageSize, > + LastAttemptStatus > + ); > + } >=20 > FreePool(AlignedImage); >=20 > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h > index 9dc306324e62..d16b353eefa2 100644 > --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.= h > +++ > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h > @@ -20,6 +20,8 @@ > #include > #include >=20 > +#include > + > #include > #include >=20 > @@ -58,6 +60,12 @@ typedef struct { > } MICROCODE_INFO; >=20 > typedef struct { > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > + BOOLEAN Empty; > + BOOLEAN InUse; > +} FIT_MICROCODE_INFO; > + > +typedef struct { > UINTN CpuIndex; > UINT32 ProcessorSignature; > UINT8 PlatformId; > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { > UINTN BspIndex; > UINTN ProcessorCount; > PROCESSOR_INFO *ProcessorInfo; > + UINT32 FitMicrocodeEntryCount; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > }; >=20 > typedef struct _MICROCODE_FMP_PRIVATE_DATA > MICROCODE_FMP_PRIVATE_DATA; >=20 > -#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME > L"MicrocodeLastAttempVar" > +#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME > L"MicrocodeLastAttemptVar" >=20 > /** > Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from > the input a as Fmp. > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i > nf > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i > nf > index dbc90857a0a5..24f06c23d404 100644 > --- > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i > nf > +++ > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.i > nf > @@ -3,7 +3,7 @@ > # > # Produce FMP instance to update Microcode. > # > -# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved. > +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved. > # This program and the accompanying materials > # are licensed and made available under the terms and conditions of the= BSD > License > # which accompanies this distribution. The full text of the license ma= y be > found at > @@ -65,6 +65,7 @@ [Pcd] >=20 > [Depex] > gEfiVariableArchProtocolGuid AND > + gEfiVariableWriteArchProtocolGuid AND > gEfiMpServiceProtocolGuid >=20 > [UserExtensions.TianoCore."ExtraFiles"] > -- > 2.7.0.windows.1