* [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
@ 2018-04-27 8:20 Star Zeng
2018-05-04 6:05 ` Yao, Jiewen
0 siblings, 1 reply; 2+ messages in thread
From: Star Zeng @ 2018-04-27 8:20 UTC (permalink / raw)
To: edk2-devel; +Cc: Star Zeng, Jiewen Yao
It is the second step for
https://bugzilla.tianocore.org/show_bug.cgi?id=540.
V2: Use error handling instead of ASSERT for FIT table checking result.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
---
.../Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c | 251 +++++++++++++-
.../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 +++++++++++++++++++--
.../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 13 +-
.../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +-
4 files changed, 601 insertions(+), 29 deletions(-)
diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
index ef5e630caf01..bc1387b3dddd 100644
--- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
+++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
@@ -272,7 +272,7 @@ FmpSetImage (
}
Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize, &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 = 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));
if (!EFI_ERROR(Status)) {
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
@@ -415,6 +415,212 @@ FmpSetPackageInfo (
}
/**
+ Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.
+
+ @param[in] MicrocodeFmpPrivate private data structure to be initialized.
+
+**/
+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 = MicrocodeFmpPrivate->FitMicrocodeInfo;
+ NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
+ FitMicrocodeEntryEnd = 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 = NextFitMicrocodeEntry + 1;
+ }
+
+ FitMicrocodeEntry = FitMicrocodeEntry + 1;
+ NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
+ }
+}
+
+/**
+ Initialize FIT microcode information.
+
+ @param[in] MicrocodeFmpPrivate private data structure to be initialized.
+
+ @return EFI_SUCCESS FIT microcode information is initialized.
+ @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
+ @return EFI_DEVICE_ERROR There is something wrong in FIT microcode entry.
+**/
+EFI_STATUS
+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;
+ FIT_MICROCODE_INFO *FitMicrocodeInfoNext;
+ CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;
+ UINTN FitMicrocodeIndex;
+ MICROCODE_INFO *MicrocodeInfo;
+ UINTN MicrocodeIndex;
+
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
+ FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
+ MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
+ MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
+ }
+
+ FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
+ if ((FitPointer == 0) ||
+ (FitPointer == 0xFFFFFFFFFFFFFFFF) ||
+ (FitPointer == 0xEEEEEEEEEEEEEEEE)) {
+ //
+ // No FIT table.
+ //
+ return EFI_SUCCESS;
+ }
+ FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
+ if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
+ (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
+ //
+ // Invalid FIT table, treat it as no FIT table.
+ //
+ return EFI_SUCCESS;
+ }
+
+ EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
+
+ //
+ // Calculate microcode entry number.
+ //
+ MicrocodeEntryNum = 0;
+ for (Index = 0; Index < EntryNum; Index++) {
+ if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
+ MicrocodeEntryNum++;
+ }
+ }
+ if (MicrocodeEntryNum == 0) {
+ //
+ // No FIT microcode entry.
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Allocate buffer.
+ //
+ MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
+
+ MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
+ MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
+
+ //
+ // Collect microcode entry info.
+ //
+ MicrocodeEntryNum = 0;
+ for (Index = 0; Index < EntryNum; Index++) {
+ if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
+ Address = (UINTN) FitEntry[Index].Address;
+ if ((Address < (UINTN) MicrocodePatchAddress) ||
+ (Address >= ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",
+ Address
+ ));
+ goto ErrorExit;
+ }
+ FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];
+ FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) Address;
+ if ((*(UINT32 *) Address) == 0xFFFFFFFF) {
+ //
+ // It is the empty slot as long as the first dword is 0xFFFF_FFFF.
+ //
+ FitMicrocodeInfo->Empty = TRUE;
+ } else {
+ FitMicrocodeInfo->Empty = FALSE;
+ }
+ MicrocodeEntryNum++;
+ }
+ }
+
+ //
+ // Every microcode should have a FIT microcode entry.
+ //
+ for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
+ MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];
+ for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {
+ FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
+ if (MicrocodeInfo->MicrocodeEntryPoint == FitMicrocodeInfo->MicrocodeEntryPoint) {
+ FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;
+ FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;
+ break;
+ }
+ }
+ if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",
+ MicrocodeInfo->MicrocodeEntryPoint
+ ));
+ goto ErrorExit;
+ }
+ }
+
+ SortFitMicrocodeInfo (MicrocodeFmpPrivate);
+
+ //
+ // Check overlap.
+ //
+ for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {
+ FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
+ MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;
+ FitMicrocodeInfoNext = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];
+ MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;
+ if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||
+ ((FitMicrocodeInfo->TotalSize != 0) &&
+ ((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >
+ (UINTN) MicrocodeEntryPointNext)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",
+ MicrocodeEntryPoint,
+ MicrocodeEntryPointNext
+ ));
+ goto ErrorExit;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+ FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
+ MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
+ MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
+ return EFI_DEVICE_ERROR;
+}
+
+/**
Initialize Processor Microcode Index.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
@@ -460,14 +666,16 @@ InitializedProcessorMicrocodeIndex (
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
- @return EFI_SUCCESS Microcode Descriptor is initialized.
+ @return EFI_SUCCESS Microcode Descriptor is initialized.
+ @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
**/
EFI_STATUS
InitializeMicrocodeDescriptor (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
- UINT8 CurrentMicrocodeCount;
+ EFI_STATUS Status;
+ UINT8 CurrentMicrocodeCount;
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);
@@ -496,6 +704,7 @@ InitializeMicrocodeDescriptor (
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
+ FreePool (MicrocodeFmpPrivate->ImageDescriptor);
return EFI_OUT_OF_RESOURCES;
}
}
@@ -505,6 +714,14 @@ InitializeMicrocodeDescriptor (
InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
+ Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
+ if (EFI_ERROR(Status)) {
+ FreePool (MicrocodeFmpPrivate->ImageDescriptor);
+ FreePool (MicrocodeFmpPrivate->MicrocodeInfo);
+ DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));
+ return Status;
+ }
+
return EFI_SUCCESS;
}
@@ -513,7 +730,8 @@ InitializeMicrocodeDescriptor (
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
- @return EFI_SUCCESS private data is initialized.
+ @return EFI_SUCCESS Processor information is initialized.
+ @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
**/
EFI_STATUS
InitializeProcessorInfo (
@@ -583,6 +801,7 @@ DumpPrivateInfo (
PROCESSOR_INFO *ProcessorInfo;
MICROCODE_INFO *MicrocodeInfo;
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
+ FIT_MICROCODE_INFO *FitMicrocodeInfo;
DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));
@@ -635,6 +854,23 @@ DumpPrivateInfo (
DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));
DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
}
+
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
+ DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));
+ FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;
+ DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate->FitMicrocodeEntryCount));
+ for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {
+ DEBUG ((
+ DEBUG_INFO,
+ " FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",
+ Index,
+ FitMicrocodeInfo[Index].MicrocodeEntryPoint,
+ FitMicrocodeInfo[Index].TotalSize,
+ FitMicrocodeInfo[Index].InUse,
+ FitMicrocodeInfo[Index].Empty
+ ));
+ }
+ }
}
/**
@@ -671,8 +907,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));
Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);
if (!Result) {
@@ -688,6 +924,7 @@ InitializePrivateData (
Status = 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.
@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 = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
if (AbortReason != NULL) {
- *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags");
+ *AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"), L"UnsupportedProcessorSignature/ProcessorFlags");
}
return EFI_UNSUPPORTED;
}
@@ -623,6 +623,124 @@ GetNextMicrocode (
}
/**
+ 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 = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {
+ if (MicrocodeEntryPoint == MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint) {
+ if (Index == (UINTN) MicrocodeFmpPrivate->FitMicrocodeEntryCount - 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
+ MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
+
+ for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo[Index].Empty) {
+ MicrocodeEntryPoint = MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;
+ NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate, MicrocodeEntryPoint);
+ if (NextMicrocodeEntryPoint != NULL) {
+ *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN) MicrocodeEntryPoint;
+ } else {
+ *AvailableSize = (UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;
+ }
+ if (*AvailableSize >= 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 FIT 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
+ MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
+
+ for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {
+ if (!MicrocodeFmpPrivate->FitMicrocodeInfo[Index].InUse) {
+ MicrocodeEntryPoint = MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;
+ NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate, MicrocodeEntryPoint);
+ if (NextMicrocodeEntryPoint != NULL) {
+ *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN) MicrocodeEntryPoint;
+ } else {
+ *AvailableSize = (UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;
+ }
+ if (*AvailableSize >= ImageSize) {
+ return MicrocodeEntryPoint;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
Get current Microcode used region size.
@param[in] MicrocodeFmpPrivate The Microcode driver private data
@@ -666,7 +784,7 @@ UpdateMicrocode (
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));
Status = MicrocodeFlashWrite (
Address,
@@ -682,6 +800,201 @@ UpdateMicrocode (
}
/**
+ 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
+ MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
+
+ MicrocodePatchScratchBuffer = AllocateZeroPool (MicrocodePatchRegionSize);
+ if (MicrocodePatchScratchBuffer == NULL) {
+ DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n"));
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ScratchBufferPtr = MicrocodePatchScratchBuffer;
+ ScratchBufferSize = 0;
+
+ //
+ // Target data collection
+ //
+ TargetTotalSize = 0;
+ AvailableSize = 0;
+ if (TargetMicrocodeEntryPoint != NULL) {
+ if (TargetMicrocodeEntryPoint->DataSize == 0) {
+ TargetTotalSize = 2048;
+ } else {
+ TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize;
+ }
+ DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize));
+ NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate, TargetMicrocodeEntryPoint);
+ DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", NextMicrocodeEntryPoint));
+ if (NextMicrocodeEntryPoint != NULL) {
+ ASSERT ((UINTN) NextMicrocodeEntryPoint >= ((UINTN) TargetMicrocodeEntryPoint + TargetTotalSize));
+ AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN) TargetMicrocodeEntryPoint;
+ } else {
+ AvailableSize = (UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN) TargetMicrocodeEntryPoint;
+ }
+ DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
+ ASSERT (AvailableSize >= 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)
+ // +------+-----------+-----+------+===================+
+ // | MCU1 | Microcode | PAD | MCU2 | Empty |
+ // +------+-----------+-----+------+===================+
+ // | TotalSize |
+ // |<-AvailableSize->|
+ //
+ // (2)
+ // +------+-----------+===================+
+ // | MCU | Microcode | Empty |
+ // +------+-----------+===================+
+ // | 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 >= ImageSize) {
+ DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
+ //
+ // +------+------------+------+===================+
+ // |Other | Old Image | ... | Empty |
+ // +------+------------+------+===================+
+ //
+ // +------+---------+--+------+===================+
+ // |Other |New Image|FF| ... | Empty |
+ // +------+---------+--+------+===================+
+ //
+ // 1.1. Copy new image
+ CopyMem (ScratchBufferPtr, Image, ImageSize);
+ ScratchBufferSize += ImageSize;
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
+ // 1.2. Pad 0xFF
+ RestSize = AvailableSize - ImageSize;
+ if (RestSize > 0) {
+ SetMem (ScratchBufferPtr, RestSize, 0xFF);
+ ScratchBufferSize += RestSize;
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
+ }
+ Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
+ return Status;
+ }
+
+ //
+ // 2. If there is empty FIT microcode entry with enough space, use it.
+ //
+ EmptyFitMicrocodeEntry = FindEmptyFitMicrocode (MicrocodeFmpPrivate, ImageSize, &AvailableSize);
+ if (EmptyFitMicrocodeEntry != NULL) {
+ DEBUG((DEBUG_INFO, "Use empty FIT microcode entry\n"));
+ // 2.1. Copy new image
+ CopyMem (ScratchBufferPtr, Image, ImageSize);
+ ScratchBufferSize += ImageSize;
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
+ // 2.2. Pad 0xFF
+ RestSize = AvailableSize - ImageSize;
+ if (RestSize > 0) {
+ SetMem (ScratchBufferPtr, RestSize, 0xFF);
+ ScratchBufferSize += RestSize;
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
+ }
+ Status = UpdateMicrocode ((UINTN) EmptyFitMicrocodeEntry, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
+ if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {
+ //
+ // Empty old microcode.
+ //
+ ScratchBufferPtr = MicrocodePatchScratchBuffer;
+ SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);
+ ScratchBufferSize = TargetTotalSize;
+ ScratchBufferPtr = (UINT8 *) MicrocodePatchScratchBuffer + ScratchBufferSize;
+ UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
+ }
+ return Status;
+ }
+
+ //
+ // 3. If there is unused microcode entry with enough space, use it.
+ //
+ UnusedFitMicrocodeEntry = FindUnusedFitMicrocode (MicrocodeFmpPrivate, ImageSize, &AvailableSize);
+ if (UnusedFitMicrocodeEntry != NULL) {
+ DEBUG((DEBUG_INFO, "Use unused FIT microcode entry\n"));
+ // 3.1. Copy new image
+ CopyMem (ScratchBufferPtr, Image, ImageSize);
+ ScratchBufferSize += ImageSize;
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
+ // 3.2. Pad 0xFF
+ RestSize = AvailableSize - ImageSize;
+ if (RestSize > 0) {
+ SetMem (ScratchBufferPtr, RestSize, 0xFF);
+ ScratchBufferSize += RestSize;
+ ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
+ }
+ Status = UpdateMicrocode ((UINTN) UnusedFitMicrocodeEntry, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
+ if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {
+ //
+ // Empty old microcode.
+ //
+ ScratchBufferPtr = MicrocodePatchScratchBuffer;
+ SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);
+ ScratchBufferSize = TargetTotalSize;
+ ScratchBufferPtr = (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 = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
+ Status = EFI_OUT_OF_RESOURCES;
+
+ return Status;
+}
+
+/**
Update Microcode flash region.
@param[in] MicrocodeFmpPrivate The Microcode driver private data
@@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion (
AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;
}
DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
+ ASSERT (AvailableSize >= TargetTotalSize);
}
- ASSERT (AvailableSize >= TargetTotalSize);
UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);
DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize));
ASSERT (UsedRegionSize >= TargetTotalSize);
@@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion (
ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((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)
// +------+-----------+-----+------+===================+
@@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion (
DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
//
// +------+------------+------+===================+
- // |Other1| Old Image |Other2| Empty |
+ // |Other | Old Image | ... | Empty |
// +------+------------+------+===================+
//
// +------+---------+--+------+===================+
- // |Other1|New Image|FF|Other2| Empty |
+ // |Other |New Image|FF| ... | Empty |
// +------+---------+--+------+===================+
//
// 1.1. Copy new image
@@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion (
DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n"));
//
// +------+------------+------+===================+
- // |Other1| Old Image |Other2| Empty |
+ // |Other | Old Image | ... | Empty |
// +------+------------+------+===================+
//
// +------+---------------+------+================+
- // |Other1| New Image |Other2| Empty |
+ // |Other | New Image | ... | Empty |
// +------+---------------+------+================+
//
// 2.1. Copy new image
@@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion (
// 2.2. Copy rest images after the old image.
if (NextMicrocodeEntryPoint != 0) {
RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint);
- CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + TargetTotalSize, RestSize);
+ CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize);
ScratchBufferSize += RestSize;
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
}
@@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion (
call to FreePool().
@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;
}
- *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
TargetCpuIndex = (UINTN)-1;
Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);
if (EFI_ERROR(Status)) {
@@ -972,6 +1284,7 @@ MicrocodeWrite (
return Status;
}
DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));
+ *LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
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));
- Status = UpdateMicrocodeFlashRegion(
- MicrocodeFmpPrivate,
- TargetMicrocodeEntryPoint,
- AlignedImage,
- ImageSize,
- LastAttemptStatus
- );
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
+ Status = UpdateMicrocodeFlashRegionWithFit (
+ MicrocodeFmpPrivate,
+ TargetMicrocodeEntryPoint,
+ AlignedImage,
+ ImageSize,
+ LastAttemptStatus
+ );
+ } else {
+ Status = UpdateMicrocodeFlashRegion (
+ MicrocodeFmpPrivate,
+ TargetMicrocodeEntryPoint,
+ AlignedImage,
+ ImageSize,
+ LastAttemptStatus
+ );
+ }
FreePool(AlignedImage);
diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
index 4442032eb6b6..3f92c517a91c 100644
--- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
+++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
@@ -20,6 +20,8 @@
#include <Guid/SystemResourceTable.h>
#include <Guid/MicrocodeFmp.h>
+#include <IndustryStandard/FirmwareInterfaceTable.h>
+
#include <Protocol/FirmwareManagement.h>
#include <Protocol/MpService.h>
@@ -58,6 +60,13 @@ typedef struct {
} MICROCODE_INFO;
typedef struct {
+ CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ UINTN TotalSize;
+ BOOLEAN InUse;
+ BOOLEAN Empty;
+} FIT_MICROCODE_INFO;
+
+typedef struct {
UINTN CpuIndex;
UINT32 ProcessorSignature;
UINT8 PlatformId;
@@ -86,11 +95,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
UINTN BspIndex;
UINTN ProcessorCount;
PROCESSOR_INFO *ProcessorInfo;
+ UINT32 FitMicrocodeEntryCount;
+ FIT_MICROCODE_INFO *FitMicrocodeInfo;
};
typedef struct _MICROCODE_FMP_PRIVATE_DATA MICROCODE_FMP_PRIVATE_DATA;
-#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME L"MicrocodeLastAttempVar"
+#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME L"MicrocodeLastAttemptVar"
/**
Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the input a as Fmp.
diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf
index dbc90857a0a5..24f06c23d404 100644
--- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf
+++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf
@@ -3,7 +3,7 @@
#
# Produce FMP instance to update Microcode.
#
-# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# 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 may be found at
@@ -65,6 +65,7 @@ [Pcd]
[Depex]
gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
gEfiMpServiceProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
--
2.7.0.windows.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
2018-04-27 8:20 [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng
@ 2018-05-04 6:05 ` Yao, Jiewen
0 siblings, 0 replies; 2+ messages in thread
From: Yao, Jiewen @ 2018-05-04 6:05 UTC (permalink / raw)
To: Zeng, Star, edk2-devel@lists.01.org
Reviewed-by: Jiewen.yao@intel.com
> -----Original Message-----
> From: Zeng, Star
> Sent: Friday, April 27, 2018 1:20 AM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
> Subject: [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
>
> It is the second step for
> https://bugzilla.tianocore.org/show_bug.cgi?id=540.
>
> V2: Use error handling instead of ASSERT for FIT table checking result.
>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Star Zeng <star.zeng@intel.com>
> ---
> .../Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c | 251
> +++++++++++++-
> .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363
> +++++++++++++++++++--
> .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 13 +-
> .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +-
> 4 files changed, 601 insertions(+), 29 deletions(-)
>
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> index ef5e630caf01..bc1387b3dddd 100644
> --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
> @@ -272,7 +272,7 @@ FmpSetImage (
> }
>
> Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize,
> &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 = 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));
>
> if (!EFI_ERROR(Status)) {
> InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
> @@ -415,6 +415,212 @@ FmpSetPackageInfo (
> }
>
> /**
> + Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to
> high.
> +
> + @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> +
> +**/
> +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 = MicrocodeFmpPrivate->FitMicrocodeInfo;
> + NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
> + FitMicrocodeEntryEnd = 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 = NextFitMicrocodeEntry + 1;
> + }
> +
> + FitMicrocodeEntry = FitMicrocodeEntry + 1;
> + NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
> + }
> +}
> +
> +/**
> + Initialize FIT microcode information.
> +
> + @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> +
> + @return EFI_SUCCESS FIT microcode information is initialized.
> + @return EFI_OUT_OF_RESOURCES No enough resource for the
> initialization.
> + @return EFI_DEVICE_ERROR There is something wrong in FIT
> microcode entry.
> +**/
> +EFI_STATUS
> +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;
> + FIT_MICROCODE_INFO *FitMicrocodeInfoNext;
> + CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
> + CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;
> + UINTN FitMicrocodeIndex;
> + MICROCODE_INFO *MicrocodeInfo;
> + UINTN MicrocodeIndex;
> +
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
> + FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
> + MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
> + MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
> + }
> +
> + FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
> + if ((FitPointer == 0) ||
> + (FitPointer == 0xFFFFFFFFFFFFFFFF) ||
> + (FitPointer == 0xEEEEEEEEEEEEEEEE)) {
> + //
> + // No FIT table.
> + //
> + return EFI_SUCCESS;
> + }
> + FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
> + if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
> + (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
> + //
> + // Invalid FIT table, treat it as no FIT table.
> + //
> + return EFI_SUCCESS;
> + }
> +
> + EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
> +
> + //
> + // Calculate microcode entry number.
> + //
> + MicrocodeEntryNum = 0;
> + for (Index = 0; Index < EntryNum; Index++) {
> + if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
> + MicrocodeEntryNum++;
> + }
> + }
> + if (MicrocodeEntryNum == 0) {
> + //
> + // No FIT microcode entry.
> + //
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Allocate buffer.
> + //
> + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool
> (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
> +
> + MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + //
> + // Collect microcode entry info.
> + //
> + MicrocodeEntryNum = 0;
> + for (Index = 0; Index < EntryNum; Index++) {
> + if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
> + Address = (UINTN) FitEntry[Index].Address;
> + if ((Address < (UINTN) MicrocodePatchAddress) ||
> + (Address >= ((UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize))) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode
> Region\n",
> + Address
> + ));
> + goto ErrorExit;
> + }
> + FitMicrocodeInfo =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];
> + FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER
> *) Address;
> + if ((*(UINT32 *) Address) == 0xFFFFFFFF) {
> + //
> + // It is the empty slot as long as the first dword is 0xFFFF_FFFF.
> + //
> + FitMicrocodeInfo->Empty = TRUE;
> + } else {
> + FitMicrocodeInfo->Empty = FALSE;
> + }
> + MicrocodeEntryNum++;
> + }
> + }
> +
> + //
> + // Every microcode should have a FIT microcode entry.
> + //
> + for (MicrocodeIndex = 0; MicrocodeIndex <
> MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
> + MicrocodeInfo =
> &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];
> + for (FitMicrocodeIndex = 0; FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {
> + FitMicrocodeInfo =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
> + if (MicrocodeInfo->MicrocodeEntryPoint ==
> FitMicrocodeInfo->MicrocodeEntryPoint) {
> + FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;
> + FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;
> + break;
> + }
> + }
> + if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount)
> {
> + DEBUG ((
> + DEBUG_ERROR,
> + "InitializeFitMicrocodeInfo - There is no FIT microcode entry for
> Microcode (0x%x)\n",
> + MicrocodeInfo->MicrocodeEntryPoint
> + ));
> + goto ErrorExit;
> + }
> + }
> +
> + SortFitMicrocodeInfo (MicrocodeFmpPrivate);
> +
> + //
> + // Check overlap.
> + //
> + for (FitMicrocodeIndex = 0; FitMicrocodeIndex <
> MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {
> + FitMicrocodeInfo =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
> + MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;
> + FitMicrocodeInfoNext =
> &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];
> + MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;
> + if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||
> + ((FitMicrocodeInfo->TotalSize != 0) &&
> + ((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >
> + (UINTN) MicrocodeEntryPointNext)) {
> + DEBUG ((
> + DEBUG_ERROR,
> + "InitializeFitMicrocodeInfo - There is overlap between FIT microcode
> entries (0x%x 0x%x)\n",
> + MicrocodeEntryPoint,
> + MicrocodeEntryPointNext
> + ));
> + goto ErrorExit;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +
> +ErrorExit:
> + FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
> + MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
> + MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
> + return EFI_DEVICE_ERROR;
> +}
> +
> +/**
> Initialize Processor Microcode Index.
>
> @param[in] MicrocodeFmpPrivate private data structure to be initialized.
> @@ -460,14 +666,16 @@ InitializedProcessorMicrocodeIndex (
>
> @param[in] MicrocodeFmpPrivate private data structure to be initialized.
>
> - @return EFI_SUCCESS Microcode Descriptor is initialized.
> + @return EFI_SUCCESS Microcode Descriptor is initialized.
> + @return EFI_OUT_OF_RESOURCES No enough resource for the
> initialization.
> **/
> EFI_STATUS
> InitializeMicrocodeDescriptor (
> IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
> )
> {
> - UINT8 CurrentMicrocodeCount;
> + EFI_STATUS Status;
> + UINT8 CurrentMicrocodeCount;
>
> CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate,
> 0, NULL, NULL);
>
> @@ -496,6 +704,7 @@ InitializeMicrocodeDescriptor (
> if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
> MicrocodeFmpPrivate->MicrocodeInfo =
> AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount *
> sizeof(MICROCODE_INFO));
> if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
> + FreePool (MicrocodeFmpPrivate->ImageDescriptor);
> return EFI_OUT_OF_RESOURCES;
> }
> }
> @@ -505,6 +714,14 @@ InitializeMicrocodeDescriptor (
>
> InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
>
> + Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
> + if (EFI_ERROR(Status)) {
> + FreePool (MicrocodeFmpPrivate->ImageDescriptor);
> + FreePool (MicrocodeFmpPrivate->MicrocodeInfo);
> + DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));
> + return Status;
> + }
> +
> return EFI_SUCCESS;
> }
>
> @@ -513,7 +730,8 @@ InitializeMicrocodeDescriptor (
>
> @param[in] MicrocodeFmpPrivate private data structure to be initialized.
>
> - @return EFI_SUCCESS private data is initialized.
> + @return EFI_SUCCESS Processor information is initialized.
> + @return EFI_OUT_OF_RESOURCES No enough resource for the
> initialization.
> **/
> EFI_STATUS
> InitializeProcessorInfo (
> @@ -583,6 +801,7 @@ DumpPrivateInfo (
> PROCESSOR_INFO *ProcessorInfo;
> MICROCODE_INFO *MicrocodeInfo;
> EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
> + FIT_MICROCODE_INFO *FitMicrocodeInfo;
>
> DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
> DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n",
> MicrocodeFmpPrivate->ProcessorCount));
> @@ -635,6 +854,23 @@ DumpPrivateInfo (
> DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n",
> ImageDescriptor[Index].LastAttemptStatus));
> DEBUG((DEBUG_VERBOSE, " HardwareInstance -
> 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
> }
> +
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
> + DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));
> + FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;
> + DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n",
> MicrocodeFmpPrivate->FitMicrocodeEntryCount));
> + for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + DEBUG ((
> + DEBUG_INFO,
> + " FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",
> + Index,
> + FitMicrocodeInfo[Index].MicrocodeEntryPoint,
> + FitMicrocodeInfo[Index].TotalSize,
> + FitMicrocodeInfo[Index].InUse,
> + FitMicrocodeInfo[Index].Empty
> + ));
> + }
> + }
> }
>
> /**
> @@ -671,8 +907,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));
>
> Result =
> GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress,
> &MicrocodeFmpPrivate->MicrocodePatchRegionSize);
> if (!Result) {
> @@ -688,6 +924,7 @@ InitializePrivateData (
>
> Status = 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.
>
> @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 =
> LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
> if (AbortReason != NULL) {
> - *AbortReason =
> AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"),
> L"UnsupportedProcessSignature/ProcessorFlags");
> + *AbortReason =
> AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"),
> L"UnsupportedProcessorSignature/ProcessorFlags");
> }
> return EFI_UNSUPPORTED;
> }
> @@ -623,6 +623,124 @@ GetNextMicrocode (
> }
>
> /**
> + 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 = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + if (MicrocodeEntryPoint ==
> MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint) {
> + if (Index == (UINTN) MicrocodeFmpPrivate->FitMicrocodeEntryCount -
> 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo[Index].Empty) {
> + MicrocodeEntryPoint =
> MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;
> + NextMicrocodeEntryPoint = GetNextFitMicrocode
> (MicrocodeFmpPrivate, MicrocodeEntryPoint);
> + if (NextMicrocodeEntryPoint != NULL) {
> + *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN)
> MicrocodeEntryPoint;
> + } else {
> + *AvailableSize = (UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;
> + }
> + if (*AvailableSize >= 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 FIT
> 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount;
> Index++) {
> + if (!MicrocodeFmpPrivate->FitMicrocodeInfo[Index].InUse) {
> + MicrocodeEntryPoint =
> MicrocodeFmpPrivate->FitMicrocodeInfo[Index].MicrocodeEntryPoint;
> + NextMicrocodeEntryPoint = GetNextFitMicrocode
> (MicrocodeFmpPrivate, MicrocodeEntryPoint);
> + if (NextMicrocodeEntryPoint != NULL) {
> + *AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN)
> MicrocodeEntryPoint;
> + } else {
> + *AvailableSize = (UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN) MicrocodeEntryPoint;
> + }
> + if (*AvailableSize >= ImageSize) {
> + return MicrocodeEntryPoint;
> + }
> + }
> + }
> +
> + return NULL;
> +}
> +
> +/**
> Get current Microcode used region size.
>
> @param[in] MicrocodeFmpPrivate The Microcode driver private
> data
> @@ -666,7 +784,7 @@ UpdateMicrocode (
>
> 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));
>
> Status = MicrocodeFlashWrite (
> Address,
> @@ -682,6 +800,201 @@ UpdateMicrocode (
> }
>
> /**
> + 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 = MicrocodeFmpPrivate->MicrocodePatchAddress;
> + MicrocodePatchRegionSize =
> MicrocodeFmpPrivate->MicrocodePatchRegionSize;
> +
> + MicrocodePatchScratchBuffer = AllocateZeroPool
> (MicrocodePatchRegionSize);
> + if (MicrocodePatchScratchBuffer == NULL) {
> + DEBUG((DEBUG_ERROR, "Fail to allocate Microcode Scratch buffer\n"));
> + *LastAttemptStatus =
> LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
> + return EFI_OUT_OF_RESOURCES;
> + }
> + ScratchBufferPtr = MicrocodePatchScratchBuffer;
> + ScratchBufferSize = 0;
> +
> + //
> + // Target data collection
> + //
> + TargetTotalSize = 0;
> + AvailableSize = 0;
> + if (TargetMicrocodeEntryPoint != NULL) {
> + if (TargetMicrocodeEntryPoint->DataSize == 0) {
> + TargetTotalSize = 2048;
> + } else {
> + TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize;
> + }
> + DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize));
> + NextMicrocodeEntryPoint = GetNextFitMicrocode (MicrocodeFmpPrivate,
> TargetMicrocodeEntryPoint);
> + DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n",
> NextMicrocodeEntryPoint));
> + if (NextMicrocodeEntryPoint != NULL) {
> + ASSERT ((UINTN) NextMicrocodeEntryPoint >= ((UINTN)
> TargetMicrocodeEntryPoint + TargetTotalSize));
> + AvailableSize = (UINTN) NextMicrocodeEntryPoint - (UINTN)
> TargetMicrocodeEntryPoint;
> + } else {
> + AvailableSize = (UINTN) MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN) TargetMicrocodeEntryPoint;
> + }
> + DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
> + ASSERT (AvailableSize >= 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)
> + // +------+-----------+-----+------+===================+
> + // | MCU1 | Microcode | PAD | MCU2 | Empty |
> + // +------+-----------+-----+------+===================+
> + // | TotalSize |
> + // |<-AvailableSize->|
> + //
> + // (2)
> + // +------+-----------+===================+
> + // | MCU | Microcode | Empty |
> + // +------+-----------+===================+
> + // | 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 >= ImageSize) {
> + DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
> + //
> + // +------+------------+------+===================+
> + // |Other | Old Image | ... | Empty |
> + // +------+------------+------+===================+
> + //
> + // +------+---------+--+------+===================+
> + // |Other |New Image|FF| ... | Empty |
> + // +------+---------+--+------+===================+
> + //
> + // 1.1. Copy new image
> + CopyMem (ScratchBufferPtr, Image, ImageSize);
> + ScratchBufferSize += ImageSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + // 1.2. Pad 0xFF
> + RestSize = AvailableSize - ImageSize;
> + if (RestSize > 0) {
> + SetMem (ScratchBufferPtr, RestSize, 0xFF);
> + ScratchBufferSize += RestSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + }
> + Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + return Status;
> + }
> +
> + //
> + // 2. If there is empty FIT microcode entry with enough space, use it.
> + //
> + EmptyFitMicrocodeEntry = FindEmptyFitMicrocode (MicrocodeFmpPrivate,
> ImageSize, &AvailableSize);
> + if (EmptyFitMicrocodeEntry != NULL) {
> + DEBUG((DEBUG_INFO, "Use empty FIT microcode entry\n"));
> + // 2.1. Copy new image
> + CopyMem (ScratchBufferPtr, Image, ImageSize);
> + ScratchBufferSize += ImageSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + // 2.2. Pad 0xFF
> + RestSize = AvailableSize - ImageSize;
> + if (RestSize > 0) {
> + SetMem (ScratchBufferPtr, RestSize, 0xFF);
> + ScratchBufferSize += RestSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + }
> + Status = UpdateMicrocode ((UINTN) EmptyFitMicrocodeEntry,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {
> + //
> + // Empty old microcode.
> + //
> + ScratchBufferPtr = MicrocodePatchScratchBuffer;
> + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);
> + ScratchBufferSize = TargetTotalSize;
> + ScratchBufferPtr = (UINT8 *) MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + UpdateMicrocode ((UINTN) TargetMicrocodeEntryPoint,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + }
> + return Status;
> + }
> +
> + //
> + // 3. If there is unused microcode entry with enough space, use it.
> + //
> + UnusedFitMicrocodeEntry = FindUnusedFitMicrocode
> (MicrocodeFmpPrivate, ImageSize, &AvailableSize);
> + if (UnusedFitMicrocodeEntry != NULL) {
> + DEBUG((DEBUG_INFO, "Use unused FIT microcode entry\n"));
> + // 3.1. Copy new image
> + CopyMem (ScratchBufferPtr, Image, ImageSize);
> + ScratchBufferSize += ImageSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + // 3.2. Pad 0xFF
> + RestSize = AvailableSize - ImageSize;
> + if (RestSize > 0) {
> + SetMem (ScratchBufferPtr, RestSize, 0xFF);
> + ScratchBufferSize += RestSize;
> + ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> + }
> + Status = UpdateMicrocode ((UINTN) UnusedFitMicrocodeEntry,
> MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
> + if (!EFI_ERROR (Status) && (TargetMicrocodeEntryPoint != NULL)) {
> + //
> + // Empty old microcode.
> + //
> + ScratchBufferPtr = MicrocodePatchScratchBuffer;
> + SetMem (ScratchBufferPtr, TargetTotalSize, 0xFF);
> + ScratchBufferSize = TargetTotalSize;
> + ScratchBufferPtr = (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 =
> LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
> + Status = EFI_OUT_OF_RESOURCES;
> +
> + return Status;
> +}
> +
> +/**
> Update Microcode flash region.
>
> @param[in] MicrocodeFmpPrivate The Microcode driver private
> data
> @@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion (
> AvailableSize = (UINTN)MicrocodePatchAddress +
> MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;
> }
> DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
> + ASSERT (AvailableSize >= TargetTotalSize);
> }
> - ASSERT (AvailableSize >= TargetTotalSize);
> UsedRegionSize =
> GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);
> DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize));
> ASSERT (UsedRegionSize >= TargetTotalSize);
> @@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion (
> ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >=
> ((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)
> // +------+-----------+-----+------+===================+
> @@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion (
> DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
> //
> // +------+------------+------+===================+
> - // |Other1| Old Image |Other2| Empty |
> + // |Other | Old Image | ... | Empty |
> // +------+------------+------+===================+
> //
> // +------+---------+--+------+===================+
> - // |Other1|New Image|FF|Other2| Empty |
> + // |Other |New Image|FF| ... | Empty |
> // +------+---------+--+------+===================+
> //
> // 1.1. Copy new image
> @@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion (
> DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n"));
> //
> // +------+------------+------+===================+
> - // |Other1| Old Image |Other2| Empty |
> + // |Other | Old Image | ... | Empty |
> // +------+------------+------+===================+
> //
> // +------+---------------+------+================+
> - // |Other1| New Image |Other2| Empty |
> + // |Other | New Image | ... | Empty |
> // +------+---------------+------+================+
> //
> // 2.1. Copy new image
> @@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion (
> // 2.2. Copy rest images after the old image.
> if (NextMicrocodeEntryPoint != 0) {
> RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize -
> ((UINTN)NextMicrocodeEntryPoint);
> - CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint +
> TargetTotalSize, RestSize);
> + CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize);
> ScratchBufferSize += RestSize;
> ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer +
> ScratchBufferSize;
> }
> @@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion (
> call to FreePool().
>
> @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;
> }
>
> - *LastAttemptVersion = ((CPU_MICROCODE_HEADER
> *)Image)->UpdateRevision;
> TargetCpuIndex = (UINTN)-1;
> Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize,
> TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);
> if (EFI_ERROR(Status)) {
> @@ -972,6 +1284,7 @@ MicrocodeWrite (
> return Status;
> }
> DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));
> + *LastAttemptVersion = ((CPU_MICROCODE_HEADER
> *)Image)->UpdateRevision;
>
> 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));
>
> - Status = UpdateMicrocodeFlashRegion(
> - MicrocodeFmpPrivate,
> - TargetMicrocodeEntryPoint,
> - AlignedImage,
> - ImageSize,
> - LastAttemptStatus
> - );
> + if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
> + Status = UpdateMicrocodeFlashRegionWithFit (
> + MicrocodeFmpPrivate,
> + TargetMicrocodeEntryPoint,
> + AlignedImage,
> + ImageSize,
> + LastAttemptStatus
> + );
> + } else {
> + Status = UpdateMicrocodeFlashRegion (
> + MicrocodeFmpPrivate,
> + TargetMicrocodeEntryPoint,
> + AlignedImage,
> + ImageSize,
> + LastAttemptStatus
> + );
> + }
>
> FreePool(AlignedImage);
>
> diff --git
> a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> index 4442032eb6b6..3f92c517a91c 100644
> --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> +++
> b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h
> @@ -20,6 +20,8 @@
> #include <Guid/SystemResourceTable.h>
> #include <Guid/MicrocodeFmp.h>
>
> +#include <IndustryStandard/FirmwareInterfaceTable.h>
> +
> #include <Protocol/FirmwareManagement.h>
> #include <Protocol/MpService.h>
>
> @@ -58,6 +60,13 @@ typedef struct {
> } MICROCODE_INFO;
>
> typedef struct {
> + CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
> + UINTN TotalSize;
> + BOOLEAN InUse;
> + BOOLEAN Empty;
> +} FIT_MICROCODE_INFO;
> +
> +typedef struct {
> UINTN CpuIndex;
> UINT32 ProcessorSignature;
> UINT8 PlatformId;
> @@ -86,11 +95,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
> UINTN BspIndex;
> UINTN ProcessorCount;
> PROCESSOR_INFO *ProcessorInfo;
> + UINT32 FitMicrocodeEntryCount;
> + FIT_MICROCODE_INFO *FitMicrocodeInfo;
> };
>
> typedef struct _MICROCODE_FMP_PRIVATE_DATA
> MICROCODE_FMP_PRIVATE_DATA;
>
> -#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME
> L"MicrocodeLastAttempVar"
> +#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME
> L"MicrocodeLastAttemptVar"
>
> /**
> 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.<BR>
> +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> # 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 may be
> found at
> @@ -65,6 +65,7 @@ [Pcd]
>
> [Depex]
> gEfiVariableArchProtocolGuid AND
> + gEfiVariableWriteArchProtocolGuid AND
> gEfiMpServiceProtocolGuid
>
> [UserExtensions.TianoCore."ExtraFiles"]
> --
> 2.7.0.windows.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-05-04 6:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-27 8:20 [PATCH V2] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng
2018-05-04 6:05 ` Yao, Jiewen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox