* [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table @ 2018-04-23 6:56 Star Zeng 2018-04-23 8:49 ` Yao, Jiewen 0 siblings, 1 reply; 6+ messages in thread From: Star Zeng @ 2018-04-23 6:56 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. 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 | 184 ++++++++++- .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 +++++++++++++++++++-- .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- 4 files changed, 535 insertions(+), 27 deletions(-) diff --git a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c index ebde93a91eb3..8276aaa0279b 100644 --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c @@ -272,7 +272,7 @@ FmpSetImage ( } 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,159 @@ 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. + +**/ +VOID +InitializeFitMicrocodeInfo ( + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate + ) +{ + UINT64 FitPointer; + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; + UINT32 EntryNum; + UINT32 MicrocodeEntryNum; + UINT32 Index; + UINTN Address; + VOID *MicrocodePatchAddress; + UINTN MicrocodePatchRegionSize; + FIT_MICROCODE_INFO *FitMicrocodeInfo; + UINTN FitMicrocodeIndex; + MICROCODE_INFO *MicrocodeInfo; + UINTN MicrocodeIndex; + + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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; + } + 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; + // + return; + } + + 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; + } + + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum; + + // + // Allocate buffer. + // + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL); + + 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; + ASSERT ((Address >= (UINTN) MicrocodePatchAddress) && + (Address < ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))); + 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->InUse = MicrocodeInfo->InUse; + break; + } + } + ASSERT (FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount); + } + + SortFitMicrocodeInfo (MicrocodeFmpPrivate); +} + +/** Initialize Processor Microcode Index. @param[in] MicrocodeFmpPrivate private data structure to be initialized. @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor ( InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); + return EFI_SUCCESS; } @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( @param[in] MicrocodeFmpPrivate private data structure to be initialized. - @return EFI_SUCCESS private data is initialized. + @return EFI_SUCCESS Processor information is initialized. **/ EFI_STATUS InitializeProcessorInfo ( @@ -583,6 +739,7 @@ DumpPrivateInfo ( PROCESSOR_INFO *ProcessorInfo; MICROCODE_INFO *MicrocodeInfo; EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; + FIT_MICROCODE_INFO *FitMicrocodeInfo; DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount)); @@ -635,6 +792,22 @@ DumpPrivateInfo ( DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus)); DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); } + + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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%x, 0x%x)\n", + Index, + FitMicrocodeInfo[Index].MicrocodeEntryPoint, + FitMicrocodeInfo[Index].InUse, + FitMicrocodeInfo[Index].Empty + )); + } + } } /** @@ -671,8 +844,8 @@ InitializePrivateData ( &VarSize, &MicrocodeFmpPrivate->LastAttempt ); - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize); if (!Result) { @@ -688,6 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct { } MICROCODE_INFO; typedef struct { + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; + BOOLEAN Empty; + BOOLEAN InUse; +} FIT_MICROCODE_INFO; + +typedef struct { UINTN CpuIndex; UINT32 ProcessorSignature; UINT8 PlatformId; @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { UINTN BspIndex; UINTN ProcessorCount; PROCESSOR_INFO *ProcessorInfo; + UINT32 FitMicrocodeEntryCount; + FIT_MICROCODE_INFO *FitMicrocodeInfo; }; 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] 6+ messages in thread
* Re: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table 2018-04-23 6:56 [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng @ 2018-04-23 8:49 ` Yao, Jiewen 2018-04-23 8:55 ` Zeng, Star 0 siblings, 1 reply; 6+ messages in thread From: Yao, Jiewen @ 2018-04-23 8:49 UTC (permalink / raw) To: Zeng, Star, edk2-devel@lists.01.org; +Cc: Yao, Jiewen Thanks for the update. Would you please share what unit test has been done for this patch? Thank you Yao Jiewen > -----Original Message----- > From: Zeng, Star > Sent: Monday, April 23, 2018 2:57 PM > To: edk2-devel@lists.01.org > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com> > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > It is the second step for > https://bugzilla.tianocore.org/show_bug.cgi?id=540. > > 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 | 184 ++++++++++- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 > +++++++++++++++++++-- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- > .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- > 4 files changed, 535 insertions(+), 27 deletions(-) > > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > index ebde93a91eb3..8276aaa0279b 100644 > --- a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > @@ -272,7 +272,7 @@ FmpSetImage ( > } > > 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,159 @@ 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. > + > +**/ > +VOID > +InitializeFitMicrocodeInfo ( > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > + ) > +{ > + UINT64 FitPointer; > + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; > + UINT32 EntryNum; > + UINT32 MicrocodeEntryNum; > + UINT32 Index; > + UINTN Address; > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > + UINTN FitMicrocodeIndex; > + MICROCODE_INFO *MicrocodeInfo; > + UINTN MicrocodeIndex; > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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; > + } > + 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; > + // > + return; > + } > + > + 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; > + } > + > + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum; > + > + // > + // Allocate buffer. > + // > + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); > + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL); > + > + 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; > + ASSERT ((Address >= (UINTN) MicrocodePatchAddress) && > + (Address < ((UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize))); > + 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->InUse = MicrocodeInfo->InUse; > + break; > + } > + } > + ASSERT (FitMicrocodeIndex < > MicrocodeFmpPrivate->FitMicrocodeEntryCount); > + } > + > + SortFitMicrocodeInfo (MicrocodeFmpPrivate); > +} > + > +/** > Initialize Processor Microcode Index. > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor ( > > InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); > > + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); > + > return EFI_SUCCESS; > } > > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > - @return EFI_SUCCESS private data is initialized. > + @return EFI_SUCCESS Processor information is initialized. > **/ > EFI_STATUS > InitializeProcessorInfo ( > @@ -583,6 +739,7 @@ DumpPrivateInfo ( > PROCESSOR_INFO *ProcessorInfo; > MICROCODE_INFO *MicrocodeInfo; > EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); > DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", > MicrocodeFmpPrivate->ProcessorCount)); > @@ -635,6 +792,22 @@ DumpPrivateInfo ( > DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", > ImageDescriptor[Index].LastAttemptStatus)); > DEBUG((DEBUG_VERBOSE, " HardwareInstance - > 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); > } > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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%x, 0x%x)\n", > + Index, > + FitMicrocodeInfo[Index].MicrocodeEntryPoint, > + FitMicrocodeInfo[Index].InUse, > + FitMicrocodeInfo[Index].Empty > + )); > + } > + } > } > > /** > @@ -671,8 +844,8 @@ InitializePrivateData ( > &VarSize, > &MicrocodeFmpPrivate->LastAttempt > ); > - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); > - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > Result = > GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, > &MicrocodeFmpPrivate->MicrocodePatchRegionSize); > if (!Result) { > @@ -688,6 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct { > } MICROCODE_INFO; > > typedef struct { > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > + BOOLEAN Empty; > + BOOLEAN InUse; > +} FIT_MICROCODE_INFO; > + > +typedef struct { > UINTN CpuIndex; > UINT32 ProcessorSignature; > UINT8 PlatformId; > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { > UINTN BspIndex; > UINTN ProcessorCount; > PROCESSOR_INFO *ProcessorInfo; > + UINT32 FitMicrocodeEntryCount; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > }; > > 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] 6+ messages in thread
* Re: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table 2018-04-23 8:49 ` Yao, Jiewen @ 2018-04-23 8:55 ` Zeng, Star 2018-04-23 9:38 ` Zeng, Star 2018-04-26 15:15 ` Yao, Jiewen 0 siblings, 2 replies; 6+ messages in thread From: Zeng, Star @ 2018-04-23 8:55 UTC (permalink / raw) To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zhu, Yonghong, Zeng, Star Yonghong helped run regression test for the cases without FIT table. I created below cases with FIT table, checked the boot log and confirmed the signature is correct after microcode update. 1. Update in situ. 2. Empty FIT microcode entry with enough space. 3. Unused FIT microcode entry with enough space. Thanks, Star -----Original Message----- From: Yao, Jiewen Sent: Monday, April 23, 2018 4:49 PM To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org Cc: Yao, Jiewen <jiewen.yao@intel.com> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Thanks for the update. Would you please share what unit test has been done for this patch? Thank you Yao Jiewen > -----Original Message----- > From: Zeng, Star > Sent: Monday, April 23, 2018 2:57 PM > To: edk2-devel@lists.01.org > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen > <jiewen.yao@intel.com> > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > It is the second step for > https://bugzilla.tianocore.org/show_bug.cgi?id=540. > > 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 | 184 ++++++++++- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 > +++++++++++++++++++-- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- > .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- > 4 files changed, 535 insertions(+), 27 deletions(-) > > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > index ebde93a91eb3..8276aaa0279b 100644 > --- > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp. > +++ c > @@ -272,7 +272,7 @@ FmpSetImage ( > } > > 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,159 @@ 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. > + > +**/ > +VOID > +InitializeFitMicrocodeInfo ( > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > + ) > +{ > + UINT64 FitPointer; > + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; > + UINT32 EntryNum; > + UINT32 MicrocodeEntryNum; > + UINT32 Index; > + UINTN Address; > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > + UINTN FitMicrocodeIndex; > + MICROCODE_INFO *MicrocodeInfo; > + UINTN MicrocodeIndex; > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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; > + } > + 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; > + // > + return; > + } > + > + 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; > + } > + > + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum; > + > + // > + // Allocate buffer. > + // > + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); > + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL); > + > + 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; > + ASSERT ((Address >= (UINTN) MicrocodePatchAddress) && > + (Address < ((UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize))); > + 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->InUse = MicrocodeInfo->InUse; > + break; > + } > + } > + ASSERT (FitMicrocodeIndex < > MicrocodeFmpPrivate->FitMicrocodeEntryCount); > + } > + > + SortFitMicrocodeInfo (MicrocodeFmpPrivate); } > + > +/** > Initialize Processor Microcode Index. > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor ( > > InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); > > + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); > + > return EFI_SUCCESS; > } > > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > - @return EFI_SUCCESS private data is initialized. > + @return EFI_SUCCESS Processor information is initialized. > **/ > EFI_STATUS > InitializeProcessorInfo ( > @@ -583,6 +739,7 @@ DumpPrivateInfo ( > PROCESSOR_INFO *ProcessorInfo; > MICROCODE_INFO *MicrocodeInfo; > EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); > DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", > MicrocodeFmpPrivate->ProcessorCount)); > @@ -635,6 +792,22 @@ DumpPrivateInfo ( > DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", > ImageDescriptor[Index].LastAttemptStatus)); > DEBUG((DEBUG_VERBOSE, " HardwareInstance - > 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); > } > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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%x, 0x%x)\n", > + Index, > + FitMicrocodeInfo[Index].MicrocodeEntryPoint, > + FitMicrocodeInfo[Index].InUse, > + FitMicrocodeInfo[Index].Empty > + )); > + } > + } > } > > /** > @@ -671,8 +844,8 @@ InitializePrivateData ( > &VarSize, > &MicrocodeFmpPrivate->LastAttempt > ); > - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); > - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > Result = > GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, > &MicrocodeFmpPrivate->MicrocodePatchRegionSize); > if (!Result) { > @@ -688,6 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct { > } MICROCODE_INFO; > > typedef struct { > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > + BOOLEAN Empty; > + BOOLEAN InUse; > +} FIT_MICROCODE_INFO; > + > +typedef struct { > UINTN CpuIndex; > UINT32 ProcessorSignature; > UINT8 PlatformId; > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { > UINTN BspIndex; > UINTN ProcessorCount; > PROCESSOR_INFO *ProcessorInfo; > + UINT32 FitMicrocodeEntryCount; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > }; > > 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/MicrocodeUpdateDx > e.i > nf > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > e.i > nf > index dbc90857a0a5..24f06c23d404 100644 > --- > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > e.i > nf > +++ > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > e.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] 6+ messages in thread
* Re: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table 2018-04-23 8:55 ` Zeng, Star @ 2018-04-23 9:38 ` Zeng, Star 2018-04-26 15:15 ` Yao, Jiewen 1 sibling, 0 replies; 6+ messages in thread From: Zeng, Star @ 2018-04-23 9:38 UTC (permalink / raw) To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zhu, Yonghong, Zeng, Star I also built VS2015/GCC49 (tool chain in my local), and checked ecc result. Thanks, Star -----Original Message----- From: Zeng, Star Sent: Monday, April 23, 2018 4:55 PM To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org Cc: Zhu, Yonghong <yonghong.zhu@intel.com>; Zeng, Star <star.zeng@intel.com> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Yonghong helped run regression test for the cases without FIT table. I created below cases with FIT table, checked the boot log and confirmed the signature is correct after microcode update. 1. Update in situ. 2. Empty FIT microcode entry with enough space. 3. Unused FIT microcode entry with enough space. Thanks, Star -----Original Message----- From: Yao, Jiewen Sent: Monday, April 23, 2018 4:49 PM To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org Cc: Yao, Jiewen <jiewen.yao@intel.com> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Thanks for the update. Would you please share what unit test has been done for this patch? Thank you Yao Jiewen > -----Original Message----- > From: Zeng, Star > Sent: Monday, April 23, 2018 2:57 PM > To: edk2-devel@lists.01.org > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen > <jiewen.yao@intel.com> > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > It is the second step for > https://bugzilla.tianocore.org/show_bug.cgi?id=540. > > 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 | 184 ++++++++++- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 > +++++++++++++++++++-- > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- > .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- > 4 files changed, 535 insertions(+), 27 deletions(-) > > diff --git > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > index ebde93a91eb3..8276aaa0279b 100644 > --- > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp. > +++ c > @@ -272,7 +272,7 @@ FmpSetImage ( > } > > 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,159 @@ 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. > + > +**/ > +VOID > +InitializeFitMicrocodeInfo ( > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > + ) > +{ > + UINT64 FitPointer; > + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; > + UINT32 EntryNum; > + UINT32 MicrocodeEntryNum; > + UINT32 Index; > + UINTN Address; > + VOID *MicrocodePatchAddress; > + UINTN MicrocodePatchRegionSize; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > + UINTN FitMicrocodeIndex; > + MICROCODE_INFO *MicrocodeInfo; > + UINTN MicrocodeIndex; > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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; > + } > + 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; > + // > + return; > + } > + > + 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; > + } > + > + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum; > + > + // > + // Allocate buffer. > + // > + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); > + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL); > + > + 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; > + ASSERT ((Address >= (UINTN) MicrocodePatchAddress) && > + (Address < ((UINTN) MicrocodePatchAddress + > MicrocodePatchRegionSize))); > + 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->InUse = MicrocodeInfo->InUse; > + break; > + } > + } > + ASSERT (FitMicrocodeIndex < > MicrocodeFmpPrivate->FitMicrocodeEntryCount); > + } > + > + SortFitMicrocodeInfo (MicrocodeFmpPrivate); } > + > +/** > Initialize Processor Microcode Index. > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor ( > > InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); > > + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); > + > return EFI_SUCCESS; > } > > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > - @return EFI_SUCCESS private data is initialized. > + @return EFI_SUCCESS Processor information is initialized. > **/ > EFI_STATUS > InitializeProcessorInfo ( > @@ -583,6 +739,7 @@ DumpPrivateInfo ( > PROCESSOR_INFO *ProcessorInfo; > MICROCODE_INFO *MicrocodeInfo; > EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); > DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", > MicrocodeFmpPrivate->ProcessorCount)); > @@ -635,6 +792,22 @@ DumpPrivateInfo ( > DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", > ImageDescriptor[Index].LastAttemptStatus)); > DEBUG((DEBUG_VERBOSE, " HardwareInstance - > 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); > } > + > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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%x, 0x%x)\n", > + Index, > + FitMicrocodeInfo[Index].MicrocodeEntryPoint, > + FitMicrocodeInfo[Index].InUse, > + FitMicrocodeInfo[Index].Empty > + )); > + } > + } > } > > /** > @@ -671,8 +844,8 @@ InitializePrivateData ( > &VarSize, > &MicrocodeFmpPrivate->LastAttempt > ); > - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); > - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); > + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > Result = > GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, > &MicrocodeFmpPrivate->MicrocodePatchRegionSize); > if (!Result) { > @@ -688,6 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct { > } MICROCODE_INFO; > > typedef struct { > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > + BOOLEAN Empty; > + BOOLEAN InUse; > +} FIT_MICROCODE_INFO; > + > +typedef struct { > UINTN CpuIndex; > UINT32 ProcessorSignature; > UINT8 PlatformId; > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { > UINTN BspIndex; > UINTN ProcessorCount; > PROCESSOR_INFO *ProcessorInfo; > + UINT32 FitMicrocodeEntryCount; > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > }; > > 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/MicrocodeUpdateDx > e.i > nf > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > e.i > nf > index dbc90857a0a5..24f06c23d404 100644 > --- > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > e.i > nf > +++ > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > e.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] 6+ messages in thread
* Re: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table 2018-04-23 8:55 ` Zeng, Star 2018-04-23 9:38 ` Zeng, Star @ 2018-04-26 15:15 ` Yao, Jiewen 2018-04-27 8:22 ` Zeng, Star 1 sibling, 1 reply; 6+ messages in thread From: Yao, Jiewen @ 2018-04-26 15:15 UTC (permalink / raw) To: Zeng, Star, edk2-devel@lists.01.org Thanks. Maybe we should also do more test on different FIT table (correct format, or wrong format), to check the robustness of the code. For example, don't use ASSERT to check FIT table content, because it might not in Initial Boot Block (IBB) region. Thank you Yao Jiewen > -----Original Message----- > From: Zeng, Star > Sent: Monday, April 23, 2018 1:55 AM > To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org > Cc: Zhu, Yonghong <yonghong.zhu@intel.com>; Zeng, Star > <star.zeng@intel.com> > Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > Yonghong helped run regression test for the cases without FIT table. > I created below cases with FIT table, checked the boot log and confirmed the > signature is correct after microcode update. > 1. Update in situ. > 2. Empty FIT microcode entry with enough space. > 3. Unused FIT microcode entry with enough space. > > > Thanks, > Star > -----Original Message----- > From: Yao, Jiewen > Sent: Monday, April 23, 2018 4:49 PM > To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org > Cc: Yao, Jiewen <jiewen.yao@intel.com> > Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > Thanks for the update. > > Would you please share what unit test has been done for this patch? > > > Thank you > Yao Jiewen > > > -----Original Message----- > > From: Zeng, Star > > Sent: Monday, April 23, 2018 2:57 PM > > To: edk2-devel@lists.01.org > > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen > > <jiewen.yao@intel.com> > > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > > > It is the second step for > > https://bugzilla.tianocore.org/show_bug.cgi?id=540. > > > > 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 | 184 > ++++++++++- > > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 > > +++++++++++++++++++-- > > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- > > .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- > > 4 files changed, 535 insertions(+), 27 deletions(-) > > > > diff --git > > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > > index ebde93a91eb3..8276aaa0279b 100644 > > --- > > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp. > > +++ c > > @@ -272,7 +272,7 @@ FmpSetImage ( > > } > > > > 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,159 @@ 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. > > + > > +**/ > > +VOID > > +InitializeFitMicrocodeInfo ( > > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > > + ) > > +{ > > + UINT64 FitPointer; > > + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; > > + UINT32 EntryNum; > > + UINT32 MicrocodeEntryNum; > > + UINT32 Index; > > + UINTN Address; > > + VOID *MicrocodePatchAddress; > > + UINTN MicrocodePatchRegionSize; > > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > + UINTN FitMicrocodeIndex; > > + MICROCODE_INFO *MicrocodeInfo; > > + UINTN MicrocodeIndex; > > + > > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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; > > + } > > + 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; > > + // > > + return; > > + } > > + > > + 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; > > + } > > + > > + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum; > > + > > + // > > + // Allocate buffer. > > + // > > + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool > > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); > > + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL); > > + > > + 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; > > + ASSERT ((Address >= (UINTN) MicrocodePatchAddress) && > > + (Address < ((UINTN) MicrocodePatchAddress + > > MicrocodePatchRegionSize))); > > + 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->InUse = MicrocodeInfo->InUse; > > + break; > > + } > > + } > > + ASSERT (FitMicrocodeIndex < > > MicrocodeFmpPrivate->FitMicrocodeEntryCount); > > + } > > + > > + SortFitMicrocodeInfo (MicrocodeFmpPrivate); } > > + > > +/** > > Initialize Processor Microcode Index. > > > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor ( > > > > InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); > > > > + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); > > + > > return EFI_SUCCESS; > > } > > > > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( > > > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > > > - @return EFI_SUCCESS private data is initialized. > > + @return EFI_SUCCESS Processor information is initialized. > > **/ > > EFI_STATUS > > InitializeProcessorInfo ( > > @@ -583,6 +739,7 @@ DumpPrivateInfo ( > > PROCESSOR_INFO *ProcessorInfo; > > MICROCODE_INFO *MicrocodeInfo; > > EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; > > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > > > DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); > > DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", > > MicrocodeFmpPrivate->ProcessorCount)); > > @@ -635,6 +792,22 @@ DumpPrivateInfo ( > > DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - > 0x%x\n", > > ImageDescriptor[Index].LastAttemptStatus)); > > DEBUG((DEBUG_VERBOSE, " HardwareInstance - > > 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); > > } > > + > > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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%x, 0x%x)\n", > > + Index, > > + FitMicrocodeInfo[Index].MicrocodeEntryPoint, > > + FitMicrocodeInfo[Index].InUse, > > + FitMicrocodeInfo[Index].Empty > > + )); > > + } > > + } > > } > > > > /** > > @@ -671,8 +844,8 @@ InitializePrivateData ( > > &VarSize, > > &MicrocodeFmpPrivate->LastAttempt > > ); > > - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); > > - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", > > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); > > + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", > > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > > > Result = > > GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, > > &MicrocodeFmpPrivate->MicrocodePatchRegionSize); > > if (!Result) { > > @@ -688,6 +861,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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct { > > } MICROCODE_INFO; > > > > typedef struct { > > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > > + BOOLEAN Empty; > > + BOOLEAN InUse; > > +} FIT_MICROCODE_INFO; > > + > > +typedef struct { > > UINTN CpuIndex; > > UINT32 ProcessorSignature; > > UINT8 PlatformId; > > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { > > UINTN BspIndex; > > UINTN ProcessorCount; > > PROCESSOR_INFO *ProcessorInfo; > > + UINT32 FitMicrocodeEntryCount; > > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > }; > > > > 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/MicrocodeUpdateDx > > e.i > > nf > > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > > e.i > > nf > > index dbc90857a0a5..24f06c23d404 100644 > > --- > > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > > e.i > > nf > > +++ > > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDx > > e.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] 6+ messages in thread
* Re: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table 2018-04-26 15:15 ` Yao, Jiewen @ 2018-04-27 8:22 ` Zeng, Star 0 siblings, 0 replies; 6+ messages in thread From: Zeng, Star @ 2018-04-27 8:22 UTC (permalink / raw) To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zhu, Yonghong, Zeng, Star Great comment. Follow your suggestion, I just sent the V2 patch at https://lists.01.org/pipermail/edk2-devel/2018-April/024270.html. I created and verified some cases for the error path in InitializeFitMicrocodeInfo(). Thanks, Star -----Original Message----- From: Yao, Jiewen Sent: Thursday, April 26, 2018 11:15 PM To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org Cc: Zhu, Yonghong <yonghong.zhu@intel.com> Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Thanks. Maybe we should also do more test on different FIT table (correct format, or wrong format), to check the robustness of the code. For example, don't use ASSERT to check FIT table content, because it might not in Initial Boot Block (IBB) region. Thank you Yao Jiewen > -----Original Message----- > From: Zeng, Star > Sent: Monday, April 23, 2018 1:55 AM > To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org > Cc: Zhu, Yonghong <yonghong.zhu@intel.com>; Zeng, Star > <star.zeng@intel.com> > Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT > table > > Yonghong helped run regression test for the cases without FIT table. > I created below cases with FIT table, checked the boot log and > confirmed the signature is correct after microcode update. > 1. Update in situ. > 2. Empty FIT microcode entry with enough space. > 3. Unused FIT microcode entry with enough space. > > > Thanks, > Star > -----Original Message----- > From: Yao, Jiewen > Sent: Monday, April 23, 2018 4:49 PM > To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org > Cc: Yao, Jiewen <jiewen.yao@intel.com> > Subject: RE: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT > table > > Thanks for the update. > > Would you please share what unit test has been done for this patch? > > > Thank you > Yao Jiewen > > > -----Original Message----- > > From: Zeng, Star > > Sent: Monday, April 23, 2018 2:57 PM > > To: edk2-devel@lists.01.org > > Cc: Zeng, Star <star.zeng@intel.com>; Yao, Jiewen > > <jiewen.yao@intel.com> > > Subject: [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table > > > > It is the second step for > > https://bugzilla.tianocore.org/show_bug.cgi?id=540. > > > > 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 | 184 > ++++++++++- > > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.c | 363 > > +++++++++++++++++++-- > > .../Capsule/MicrocodeUpdateDxe/MicrocodeUpdate.h | 12 +- > > .../MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf | 3 +- > > 4 files changed, 535 insertions(+), 27 deletions(-) > > > > diff --git > > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > > index ebde93a91eb3..8276aaa0279b 100644 > > --- > > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c > > +++ b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp. > > +++ c > > @@ -272,7 +272,7 @@ FmpSetImage ( > > } > > > > 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,159 @@ 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. > > + > > +**/ > > +VOID > > +InitializeFitMicrocodeInfo ( > > + IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate > > + ) > > +{ > > + UINT64 FitPointer; > > + FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry; > > + UINT32 EntryNum; > > + UINT32 MicrocodeEntryNum; > > + UINT32 Index; > > + UINTN Address; > > + VOID *MicrocodePatchAddress; > > + UINTN MicrocodePatchRegionSize; > > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > + UINTN FitMicrocodeIndex; > > + MICROCODE_INFO *MicrocodeInfo; > > + UINTN MicrocodeIndex; > > + > > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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; > > + } > > + 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; > > + // > > + return; > > + } > > + > > + 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; > > + } > > + > > + MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum; > > + > > + // > > + // Allocate buffer. > > + // > > + MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool > > (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO)); > > + ASSERT (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL); > > + > > + 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; > > + ASSERT ((Address >= (UINTN) MicrocodePatchAddress) && > > + (Address < ((UINTN) MicrocodePatchAddress + > > MicrocodePatchRegionSize))); > > + 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->InUse = MicrocodeInfo->InUse; > > + break; > > + } > > + } > > + ASSERT (FitMicrocodeIndex < > > MicrocodeFmpPrivate->FitMicrocodeEntryCount); > > + } > > + > > + SortFitMicrocodeInfo (MicrocodeFmpPrivate); } > > + > > +/** > > Initialize Processor Microcode Index. > > > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > @@ -496,6 +649,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 +659,8 @@ InitializeMicrocodeDescriptor ( > > > > InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate); > > > > + InitializeFitMicrocodeInfo (MicrocodeFmpPrivate); > > + > > return EFI_SUCCESS; > > } > > > > @@ -513,7 +669,7 @@ InitializeMicrocodeDescriptor ( > > > > @param[in] MicrocodeFmpPrivate private data structure to be initialized. > > > > - @return EFI_SUCCESS private data is initialized. > > + @return EFI_SUCCESS Processor information is initialized. > > **/ > > EFI_STATUS > > InitializeProcessorInfo ( > > @@ -583,6 +739,7 @@ DumpPrivateInfo ( > > PROCESSOR_INFO *ProcessorInfo; > > MICROCODE_INFO *MicrocodeInfo; > > EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; > > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > > > DEBUG ((DEBUG_INFO, "ProcessorInfo:\n")); > > DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", > > MicrocodeFmpPrivate->ProcessorCount)); > > @@ -635,6 +792,22 @@ DumpPrivateInfo ( > > DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - > 0x%x\n", > > ImageDescriptor[Index].LastAttemptStatus)); > > DEBUG((DEBUG_VERBOSE, " HardwareInstance - > > 0x%lx\n", ImageDescriptor[Index].HardwareInstance)); > > } > > + > > + if (MicrocodeFmpPrivate->FitMicrocodeInfo != 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%x, 0x%x)\n", > > + Index, > > + FitMicrocodeInfo[Index].MicrocodeEntryPoint, > > + FitMicrocodeInfo[Index].InUse, > > + FitMicrocodeInfo[Index].Empty > > + )); > > + } > > + } > > } > > > > /** > > @@ -671,8 +844,8 @@ InitializePrivateData ( > > &VarSize, > > &MicrocodeFmpPrivate->LastAttempt > > ); > > - DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); > > - DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - > > 0x%x\n", > > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > + DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus)); > > + DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - > > + 0x%x\n", > > MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, > > MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus)); > > > > Result = > > GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, > > &MicrocodeFmpPrivate->MicrocodePatchRegionSize); > > if (!Result) { > > @@ -688,6 +861,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/ProcessorFla > > gs "), 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 9dc306324e62..d16b353eefa2 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,12 @@ typedef struct { > > } MICROCODE_INFO; > > > > typedef struct { > > + CPU_MICROCODE_HEADER *MicrocodeEntryPoint; > > + BOOLEAN Empty; > > + BOOLEAN InUse; > > +} FIT_MICROCODE_INFO; > > + > > +typedef struct { > > UINTN CpuIndex; > > UINT32 ProcessorSignature; > > UINT8 PlatformId; > > @@ -86,11 +94,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA { > > UINTN BspIndex; > > UINTN ProcessorCount; > > PROCESSOR_INFO *ProcessorInfo; > > + UINT32 FitMicrocodeEntryCount; > > + FIT_MICROCODE_INFO *FitMicrocodeInfo; > > }; > > > > 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/MicrocodeUpdate > > Dx > > e.i > > nf > > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate > > Dx > > e.i > > nf > > index dbc90857a0a5..24f06c23d404 100644 > > --- > > a/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate > > Dx > > e.i > > nf > > +++ > > b/IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdate > > Dx > > e.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] 6+ messages in thread
end of thread, other threads:[~2018-04-27 8:22 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-04-23 6:56 [PATCH] IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table Star Zeng 2018-04-23 8:49 ` Yao, Jiewen 2018-04-23 8:55 ` Zeng, Star 2018-04-23 9:38 ` Zeng, Star 2018-04-26 15:15 ` Yao, Jiewen 2018-04-27 8:22 ` Zeng, Star
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox