mirror of https://github.com/acidanthera/audk.git
IntelSiliconPkg MicrocodeUpdateDxe: Honor FIT table
It is the second step for https://bugzilla.tianocore.org/show_bug.cgi?id=540. V2: Use error handling instead of ASSERT for FIT table checking result. Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
parent
0edb7ec5ce
commit
e91797885a
|
@ -272,7 +272,7 @@ FmpSetImage (
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);
|
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(
|
VarStatus = gRT->SetVariable(
|
||||||
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
|
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
|
||||||
&gEfiCallerIdGuid,
|
&gEfiCallerIdGuid,
|
||||||
|
@ -280,7 +280,7 @@ FmpSetImage (
|
||||||
sizeof(MicrocodeFmpPrivate->LastAttempt),
|
sizeof(MicrocodeFmpPrivate->LastAttempt),
|
||||||
&MicrocodeFmpPrivate->LastAttempt
|
&MicrocodeFmpPrivate->LastAttempt
|
||||||
);
|
);
|
||||||
DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));
|
DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));
|
||||||
|
|
||||||
if (!EFI_ERROR(Status)) {
|
if (!EFI_ERROR(Status)) {
|
||||||
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
||||||
|
@ -414,6 +414,212 @@ FmpSetPackageInfo (
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SortFitMicrocodeInfo (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FIT_MICROCODE_INFO *FitMicrocodeEntry;
|
||||||
|
FIT_MICROCODE_INFO *NextFitMicrocodeEntry;
|
||||||
|
FIT_MICROCODE_INFO TempFitMicrocodeEntry;
|
||||||
|
FIT_MICROCODE_INFO *FitMicrocodeEntryEnd;
|
||||||
|
|
||||||
|
FitMicrocodeEntry = MicrocodeFmpPrivate->FitMicrocodeInfo;
|
||||||
|
NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
|
||||||
|
FitMicrocodeEntryEnd = MicrocodeFmpPrivate->FitMicrocodeInfo + MicrocodeFmpPrivate->FitMicrocodeEntryCount;
|
||||||
|
while (FitMicrocodeEntry < FitMicrocodeEntryEnd) {
|
||||||
|
while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) {
|
||||||
|
if (FitMicrocodeEntry->MicrocodeEntryPoint > NextFitMicrocodeEntry->MicrocodeEntryPoint) {
|
||||||
|
CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));
|
||||||
|
CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));
|
||||||
|
CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
|
NextFitMicrocodeEntry = NextFitMicrocodeEntry + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FitMicrocodeEntry = FitMicrocodeEntry + 1;
|
||||||
|
NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize FIT microcode information.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS FIT microcode information is initialized.
|
||||||
|
@return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
|
||||||
|
@return EFI_DEVICE_ERROR There is something wrong in FIT microcode entry.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitializeFitMicrocodeInfo (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 FitPointer;
|
||||||
|
FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
|
||||||
|
UINT32 EntryNum;
|
||||||
|
UINT32 MicrocodeEntryNum;
|
||||||
|
UINT32 Index;
|
||||||
|
UINTN Address;
|
||||||
|
VOID *MicrocodePatchAddress;
|
||||||
|
UINTN MicrocodePatchRegionSize;
|
||||||
|
FIT_MICROCODE_INFO *FitMicrocodeInfo;
|
||||||
|
FIT_MICROCODE_INFO *FitMicrocodeInfoNext;
|
||||||
|
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
|
||||||
|
CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;
|
||||||
|
UINTN FitMicrocodeIndex;
|
||||||
|
MICROCODE_INFO *MicrocodeInfo;
|
||||||
|
UINTN MicrocodeIndex;
|
||||||
|
|
||||||
|
if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
|
||||||
|
FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
|
||||||
|
MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
|
||||||
|
MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
|
||||||
|
if ((FitPointer == 0) ||
|
||||||
|
(FitPointer == 0xFFFFFFFFFFFFFFFF) ||
|
||||||
|
(FitPointer == 0xEEEEEEEEEEEEEEEE)) {
|
||||||
|
//
|
||||||
|
// No FIT table.
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
|
||||||
|
if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
|
||||||
|
(FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
|
||||||
|
//
|
||||||
|
// Invalid FIT table, treat it as no FIT table.
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate microcode entry number.
|
||||||
|
//
|
||||||
|
MicrocodeEntryNum = 0;
|
||||||
|
for (Index = 0; Index < EntryNum; Index++) {
|
||||||
|
if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
|
||||||
|
MicrocodeEntryNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MicrocodeEntryNum == 0) {
|
||||||
|
//
|
||||||
|
// No FIT microcode entry.
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate buffer.
|
||||||
|
//
|
||||||
|
MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
|
||||||
|
if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
|
||||||
|
|
||||||
|
MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
|
||||||
|
MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Collect microcode entry info.
|
||||||
|
//
|
||||||
|
MicrocodeEntryNum = 0;
|
||||||
|
for (Index = 0; Index < EntryNum; Index++) {
|
||||||
|
if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
|
||||||
|
Address = (UINTN) FitEntry[Index].Address;
|
||||||
|
if ((Address < (UINTN) MicrocodePatchAddress) ||
|
||||||
|
(Address >= ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",
|
||||||
|
Address
|
||||||
|
));
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];
|
||||||
|
FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) Address;
|
||||||
|
if ((*(UINT32 *) Address) == 0xFFFFFFFF) {
|
||||||
|
//
|
||||||
|
// It is the empty slot as long as the first dword is 0xFFFF_FFFF.
|
||||||
|
//
|
||||||
|
FitMicrocodeInfo->Empty = TRUE;
|
||||||
|
} else {
|
||||||
|
FitMicrocodeInfo->Empty = FALSE;
|
||||||
|
}
|
||||||
|
MicrocodeEntryNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Every microcode should have a FIT microcode entry.
|
||||||
|
//
|
||||||
|
for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
|
||||||
|
MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];
|
||||||
|
for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {
|
||||||
|
FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
|
||||||
|
if (MicrocodeInfo->MicrocodeEntryPoint == FitMicrocodeInfo->MicrocodeEntryPoint) {
|
||||||
|
FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;
|
||||||
|
FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",
|
||||||
|
MicrocodeInfo->MicrocodeEntryPoint
|
||||||
|
));
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SortFitMicrocodeInfo (MicrocodeFmpPrivate);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check overlap.
|
||||||
|
//
|
||||||
|
for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {
|
||||||
|
FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
|
||||||
|
MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;
|
||||||
|
FitMicrocodeInfoNext = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];
|
||||||
|
MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;
|
||||||
|
if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||
|
||||||
|
((FitMicrocodeInfo->TotalSize != 0) &&
|
||||||
|
((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >
|
||||||
|
(UINTN) MicrocodeEntryPointNext)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",
|
||||||
|
MicrocodeEntryPoint,
|
||||||
|
MicrocodeEntryPointNext
|
||||||
|
));
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
ErrorExit:
|
||||||
|
FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
|
||||||
|
MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
|
||||||
|
MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize Processor Microcode Index.
|
Initialize Processor Microcode Index.
|
||||||
|
|
||||||
|
@ -461,12 +667,14 @@ InitializedProcessorMicrocodeIndex (
|
||||||
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
||||||
|
|
||||||
@return EFI_SUCCESS Microcode Descriptor is initialized.
|
@return EFI_SUCCESS Microcode Descriptor is initialized.
|
||||||
|
@return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
InitializeMicrocodeDescriptor (
|
InitializeMicrocodeDescriptor (
|
||||||
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
UINT8 CurrentMicrocodeCount;
|
UINT8 CurrentMicrocodeCount;
|
||||||
|
|
||||||
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);
|
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);
|
||||||
|
@ -496,6 +704,7 @@ InitializeMicrocodeDescriptor (
|
||||||
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
|
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
|
||||||
MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));
|
MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));
|
||||||
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
|
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
|
||||||
|
FreePool (MicrocodeFmpPrivate->ImageDescriptor);
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,6 +714,14 @@ InitializeMicrocodeDescriptor (
|
||||||
|
|
||||||
InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
|
InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
|
||||||
|
|
||||||
|
Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
FreePool (MicrocodeFmpPrivate->ImageDescriptor);
|
||||||
|
FreePool (MicrocodeFmpPrivate->MicrocodeInfo);
|
||||||
|
DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +730,8 @@ InitializeMicrocodeDescriptor (
|
||||||
|
|
||||||
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
||||||
|
|
||||||
@return EFI_SUCCESS private data is initialized.
|
@return EFI_SUCCESS Processor information is initialized.
|
||||||
|
@return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
InitializeProcessorInfo (
|
InitializeProcessorInfo (
|
||||||
|
@ -583,6 +801,7 @@ DumpPrivateInfo (
|
||||||
PROCESSOR_INFO *ProcessorInfo;
|
PROCESSOR_INFO *ProcessorInfo;
|
||||||
MICROCODE_INFO *MicrocodeInfo;
|
MICROCODE_INFO *MicrocodeInfo;
|
||||||
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
|
||||||
|
FIT_MICROCODE_INFO *FitMicrocodeInfo;
|
||||||
|
|
||||||
DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
|
DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
|
||||||
DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));
|
DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));
|
||||||
|
@ -635,6 +854,23 @@ DumpPrivateInfo (
|
||||||
DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));
|
DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));
|
||||||
DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
|
DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
|
||||||
|
DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));
|
||||||
|
FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;
|
||||||
|
DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate->FitMicrocodeEntryCount));
|
||||||
|
for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
" FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",
|
||||||
|
Index,
|
||||||
|
FitMicrocodeInfo[Index].MicrocodeEntryPoint,
|
||||||
|
FitMicrocodeInfo[Index].TotalSize,
|
||||||
|
FitMicrocodeInfo[Index].InUse,
|
||||||
|
FitMicrocodeInfo[Index].Empty
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -671,8 +907,8 @@ InitializePrivateData (
|
||||||
&VarSize,
|
&VarSize,
|
||||||
&MicrocodeFmpPrivate->LastAttempt
|
&MicrocodeFmpPrivate->LastAttempt
|
||||||
);
|
);
|
||||||
DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
|
DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));
|
||||||
DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
|
DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
|
||||||
|
|
||||||
Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);
|
Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);
|
||||||
if (!Result) {
|
if (!Result) {
|
||||||
|
@ -688,6 +924,7 @@ InitializePrivateData (
|
||||||
|
|
||||||
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
|
FreePool (MicrocodeFmpPrivate->ProcessorInfo);
|
||||||
DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));
|
DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,7 +368,7 @@ GetMatchedProcessor (
|
||||||
On output, the index of target CPU which matches the Microcode.
|
On output, the index of target CPU which matches the Microcode.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The Microcode image passes verification.
|
@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_INCOMPATIBLE_VERSION The Microcode image version is incorrect.
|
||||||
@retval EFI_UNSUPPORTED The Microcode ProcessorSignature or ProcessorFlags is incorrect.
|
@retval EFI_UNSUPPORTED The Microcode ProcessorSignature or ProcessorFlags is incorrect.
|
||||||
@retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
|
@retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
|
||||||
|
@ -550,7 +550,7 @@ VerifyMicrocode (
|
||||||
}
|
}
|
||||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
|
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
|
||||||
if (AbortReason != NULL) {
|
if (AbortReason != NULL) {
|
||||||
*AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags");
|
*AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorSignature/ProcessorFlags"), L"UnsupportedProcessorSignature/ProcessorFlags");
|
||||||
}
|
}
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -622,6 +622,124 @@ GetNextMicrocode (
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
Get current Microcode used region size.
|
||||||
|
|
||||||
|
@ -666,7 +784,7 @@ UpdateMicrocode (
|
||||||
|
|
||||||
DEBUG((DEBUG_INFO, "PlatformUpdate:"));
|
DEBUG((DEBUG_INFO, "PlatformUpdate:"));
|
||||||
DEBUG((DEBUG_INFO, " Address - 0x%lx,", Address));
|
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 (
|
Status = MicrocodeFlashWrite (
|
||||||
Address,
|
Address,
|
||||||
|
@ -681,6 +799,201 @@ UpdateMicrocode (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
Update Microcode flash region.
|
||||||
|
|
||||||
|
@ -753,8 +1066,8 @@ UpdateMicrocodeFlashRegion (
|
||||||
AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;
|
AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;
|
||||||
}
|
}
|
||||||
DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
|
DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
|
||||||
}
|
|
||||||
ASSERT (AvailableSize >= TargetTotalSize);
|
ASSERT (AvailableSize >= TargetTotalSize);
|
||||||
|
}
|
||||||
UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);
|
UsedRegionSize = GetCurrentMicrocodeUsedRegionSize(MicrocodeFmpPrivate);
|
||||||
DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize));
|
DEBUG((DEBUG_INFO, " UsedRegionSize - 0x%x\n", UsedRegionSize));
|
||||||
ASSERT (UsedRegionSize >= TargetTotalSize);
|
ASSERT (UsedRegionSize >= TargetTotalSize);
|
||||||
|
@ -762,8 +1075,8 @@ UpdateMicrocodeFlashRegion (
|
||||||
ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));
|
ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Total Size means the Microcode data size.
|
// Total Size means the Microcode size.
|
||||||
// Available Size means the Microcode data size plus the pad till (1) next Microcode or (2) the end.
|
// Available Size means the Microcode size plus the pad till (1) next Microcode or (2) the end.
|
||||||
//
|
//
|
||||||
// (1)
|
// (1)
|
||||||
// +------+-----------+-----+------+===================+
|
// +------+-----------+-----+------+===================+
|
||||||
|
@ -793,11 +1106,11 @@ UpdateMicrocodeFlashRegion (
|
||||||
DEBUG((DEBUG_INFO, "Replace old microcode in situ\n"));
|
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
|
// 1.1. Copy new image
|
||||||
|
@ -835,11 +1148,11 @@ UpdateMicrocodeFlashRegion (
|
||||||
DEBUG((DEBUG_INFO, "Reorg and replace old microcode\n"));
|
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
|
// 2.1. Copy new image
|
||||||
|
@ -849,7 +1162,7 @@ UpdateMicrocodeFlashRegion (
|
||||||
// 2.2. Copy rest images after the old image.
|
// 2.2. Copy rest images after the old image.
|
||||||
if (NextMicrocodeEntryPoint != 0) {
|
if (NextMicrocodeEntryPoint != 0) {
|
||||||
RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint);
|
RestSize = (UINTN)MicrocodePatchAddress + UsedRegionSize - ((UINTN)NextMicrocodeEntryPoint);
|
||||||
CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + TargetTotalSize, RestSize);
|
CopyMem (ScratchBufferPtr, NextMicrocodeEntryPoint, RestSize);
|
||||||
ScratchBufferSize += RestSize;
|
ScratchBufferSize += RestSize;
|
||||||
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
}
|
}
|
||||||
|
@ -932,7 +1245,7 @@ UpdateMicrocodeFlashRegion (
|
||||||
call to FreePool().
|
call to FreePool().
|
||||||
|
|
||||||
@retval EFI_SUCCESS The Microcode image is written.
|
@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_INCOMPATIBLE_VERSION The Microcode image version is incorrect.
|
||||||
@retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
|
@retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
|
||||||
@retval EFI_WRITE_PROTECTED The flash device is read only.
|
@retval EFI_WRITE_PROTECTED The flash device is read only.
|
||||||
|
@ -963,7 +1276,6 @@ MicrocodeWrite (
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
*LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
|
|
||||||
TargetCpuIndex = (UINTN)-1;
|
TargetCpuIndex = (UINTN)-1;
|
||||||
Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);
|
Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
|
@ -972,6 +1284,7 @@ MicrocodeWrite (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));
|
DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));
|
||||||
|
*LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
|
||||||
|
|
||||||
DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex));
|
DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex));
|
||||||
ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);
|
ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);
|
||||||
|
@ -985,6 +1298,15 @@ MicrocodeWrite (
|
||||||
}
|
}
|
||||||
DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint));
|
DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint));
|
||||||
|
|
||||||
|
if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
|
||||||
|
Status = UpdateMicrocodeFlashRegionWithFit (
|
||||||
|
MicrocodeFmpPrivate,
|
||||||
|
TargetMicrocodeEntryPoint,
|
||||||
|
AlignedImage,
|
||||||
|
ImageSize,
|
||||||
|
LastAttemptStatus
|
||||||
|
);
|
||||||
|
} else {
|
||||||
Status = UpdateMicrocodeFlashRegion (
|
Status = UpdateMicrocodeFlashRegion (
|
||||||
MicrocodeFmpPrivate,
|
MicrocodeFmpPrivate,
|
||||||
TargetMicrocodeEntryPoint,
|
TargetMicrocodeEntryPoint,
|
||||||
|
@ -992,6 +1314,7 @@ MicrocodeWrite (
|
||||||
ImageSize,
|
ImageSize,
|
||||||
LastAttemptStatus
|
LastAttemptStatus
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
FreePool(AlignedImage);
|
FreePool(AlignedImage);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <Guid/SystemResourceTable.h>
|
#include <Guid/SystemResourceTable.h>
|
||||||
#include <Guid/MicrocodeFmp.h>
|
#include <Guid/MicrocodeFmp.h>
|
||||||
|
|
||||||
|
#include <IndustryStandard/FirmwareInterfaceTable.h>
|
||||||
|
|
||||||
#include <Protocol/FirmwareManagement.h>
|
#include <Protocol/FirmwareManagement.h>
|
||||||
#include <Protocol/MpService.h>
|
#include <Protocol/MpService.h>
|
||||||
|
|
||||||
|
@ -57,6 +59,13 @@ typedef struct {
|
||||||
BOOLEAN InUse;
|
BOOLEAN InUse;
|
||||||
} MICROCODE_INFO;
|
} MICROCODE_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
|
||||||
|
UINTN TotalSize;
|
||||||
|
BOOLEAN InUse;
|
||||||
|
BOOLEAN Empty;
|
||||||
|
} FIT_MICROCODE_INFO;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINTN CpuIndex;
|
UINTN CpuIndex;
|
||||||
UINT32 ProcessorSignature;
|
UINT32 ProcessorSignature;
|
||||||
|
@ -86,11 +95,13 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
|
||||||
UINTN BspIndex;
|
UINTN BspIndex;
|
||||||
UINTN ProcessorCount;
|
UINTN ProcessorCount;
|
||||||
PROCESSOR_INFO *ProcessorInfo;
|
PROCESSOR_INFO *ProcessorInfo;
|
||||||
|
UINT32 FitMicrocodeEntryCount;
|
||||||
|
FIT_MICROCODE_INFO *FitMicrocodeInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _MICROCODE_FMP_PRIVATE_DATA MICROCODE_FMP_PRIVATE_DATA;
|
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.
|
Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the input a as Fmp.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
# Produce FMP instance to update Microcode.
|
# 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
|
# This program and the accompanying materials
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
# 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
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -65,6 +65,7 @@
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiVariableArchProtocolGuid AND
|
gEfiVariableArchProtocolGuid AND
|
||||||
|
gEfiVariableWriteArchProtocolGuid AND
|
||||||
gEfiMpServiceProtocolGuid
|
gEfiMpServiceProtocolGuid
|
||||||
|
|
||||||
[UserExtensions.TianoCore."ExtraFiles"]
|
[UserExtensions.TianoCore."ExtraFiles"]
|
||||||
|
|
Loading…
Reference in New Issue