.../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(-)
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
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
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 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.