mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/MicrocodeUpdate: Add MP support.
Support the case that BSP and AP are using different Microcode. The previous logic validates new MCU on BSP only. The enhanced logic will validate MCU on every BSP and AP. As long as one processor loads the MCU successfully, it will be updated. Cc: Jeff Fan <jeff.fan@intel.com> Cc: Star Zeng <star.zeng@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com>
This commit is contained in:
parent
2ed658240c
commit
31d060d94e
|
@ -284,6 +284,7 @@ FmpSetImage (
|
||||||
|
|
||||||
if (!EFI_ERROR(Status)) {
|
if (!EFI_ERROR(Status)) {
|
||||||
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
||||||
|
DumpPrivateInfo (MicrocodeFmpPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -413,6 +414,47 @@ FmpSetPackageInfo (
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize Processor Microcode Index.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
InitializedProcessorMicrocodeIndex (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN CpuIndex;
|
||||||
|
UINTN MicrocodeIndex;
|
||||||
|
UINTN TargetCpuIndex;
|
||||||
|
UINT32 AttemptStatus;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
for (CpuIndex = 0; CpuIndex < MicrocodeFmpPrivate->ProcessorCount; CpuIndex++) {
|
||||||
|
if (MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex != (UINTN)-1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
|
||||||
|
if (!MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].InUse) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TargetCpuIndex = CpuIndex;
|
||||||
|
Status = VerifyMicrocode(
|
||||||
|
MicrocodeFmpPrivate,
|
||||||
|
MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].MicrocodeEntryPoint,
|
||||||
|
MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].TotalSize,
|
||||||
|
FALSE,
|
||||||
|
&AttemptStatus,
|
||||||
|
NULL,
|
||||||
|
&TargetCpuIndex
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex = MicrocodeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize Microcode Descriptor.
|
Initialize Microcode Descriptor.
|
||||||
|
|
||||||
|
@ -461,9 +503,140 @@ InitializeMicrocodeDescriptor (
|
||||||
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, MicrocodeFmpPrivate->DescriptorCount, MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->MicrocodeInfo);
|
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, MicrocodeFmpPrivate->DescriptorCount, MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->MicrocodeInfo);
|
||||||
ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);
|
ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);
|
||||||
|
|
||||||
|
InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize MicrocodeFmpDriver multiprocessor information.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS private data is initialized.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitializeProcessorInfo (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_MP_SERVICES_PROTOCOL *MpService;
|
||||||
|
UINTN NumberOfProcessors;
|
||||||
|
UINTN NumberOfEnabledProcessors;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN BspIndex;
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
|
||||||
|
MicrocodeFmpPrivate->MpService = MpService;
|
||||||
|
MicrocodeFmpPrivate->ProcessorCount = 0;
|
||||||
|
MicrocodeFmpPrivate->ProcessorInfo = NULL;
|
||||||
|
|
||||||
|
Status = MpService->GetNumberOfProcessors (MpService, &NumberOfProcessors, &NumberOfEnabledProcessors);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
MicrocodeFmpPrivate->ProcessorCount = NumberOfProcessors;
|
||||||
|
|
||||||
|
Status = MpService->WhoAmI (MpService, &BspIndex);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
MicrocodeFmpPrivate->BspIndex = BspIndex;
|
||||||
|
|
||||||
|
MicrocodeFmpPrivate->ProcessorInfo = AllocateZeroPool (sizeof(PROCESSOR_INFO) * MicrocodeFmpPrivate->ProcessorCount);
|
||||||
|
if (MicrocodeFmpPrivate->ProcessorInfo == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < NumberOfProcessors; Index++) {
|
||||||
|
MicrocodeFmpPrivate->ProcessorInfo[Index].CpuIndex = Index;
|
||||||
|
MicrocodeFmpPrivate->ProcessorInfo[Index].MicrocodeIndex = (UINTN)-1;
|
||||||
|
if (Index == BspIndex) {
|
||||||
|
CollectProcessorInfo (&MicrocodeFmpPrivate->ProcessorInfo[Index]);
|
||||||
|
} else {
|
||||||
|
Status = MpService->StartupThisAP (
|
||||||
|
MpService,
|
||||||
|
CollectProcessorInfo,
|
||||||
|
Index,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&MicrocodeFmpPrivate->ProcessorInfo[Index],
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump private information.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate private data structure.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpPrivateInfo (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
PROCESSOR_INFO *ProcessorInfo;
|
||||||
|
MICROCODE_INFO *MicrocodeInfo;
|
||||||
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
|
||||||
|
DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));
|
||||||
|
DEBUG ((DEBUG_INFO, " BspIndex - 0x%x\n", MicrocodeFmpPrivate->BspIndex));
|
||||||
|
|
||||||
|
ProcessorInfo = MicrocodeFmpPrivate->ProcessorInfo;
|
||||||
|
for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
" ProcessorInfo[0x%x] - 0x%08x, 0x%02x, 0x%08x, (0x%x)\n",
|
||||||
|
ProcessorInfo[Index].CpuIndex,
|
||||||
|
ProcessorInfo[Index].ProcessorSignature,
|
||||||
|
ProcessorInfo[Index].PlatformId,
|
||||||
|
ProcessorInfo[Index].MicrocodeRevision,
|
||||||
|
ProcessorInfo[Index].MicrocodeIndex
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "MicrocodeInfo:\n"));
|
||||||
|
MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;
|
||||||
|
DEBUG ((DEBUG_INFO, " MicrocodeRegion - 0x%x - 0x%x\n", MicrocodeFmpPrivate->MicrocodePatchAddress, MicrocodeFmpPrivate->MicrocodePatchRegionSize));
|
||||||
|
DEBUG ((DEBUG_INFO, " MicrocodeCount - 0x%x\n", MicrocodeFmpPrivate->DescriptorCount));
|
||||||
|
for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
" MicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x)\n",
|
||||||
|
Index,
|
||||||
|
MicrocodeInfo[Index].MicrocodeEntryPoint,
|
||||||
|
MicrocodeInfo[Index].TotalSize,
|
||||||
|
MicrocodeInfo[Index].InUse
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageDescriptor = MicrocodeFmpPrivate->ImageDescriptor;
|
||||||
|
DEBUG ((DEBUG_VERBOSE, "ImageDescriptor:\n"));
|
||||||
|
for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
|
||||||
|
DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", ImageDescriptor[Index].ImageIndex));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &ImageDescriptor[Index].ImageTypeId));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", ImageDescriptor[Index].ImageId));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", ImageDescriptor[Index].ImageIdName));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageDescriptor[Index].Version));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", ImageDescriptor[Index].VersionName));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", ImageDescriptor[Index].Size));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", ImageDescriptor[Index].AttributesSupported));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", ImageDescriptor[Index].AttributesSetting));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", ImageDescriptor[Index].Compatibilities));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", ImageDescriptor[Index].LowestSupportedImageVersion));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", ImageDescriptor[Index].LastAttemptVersion));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));
|
||||||
|
DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize MicrocodeFmpDriver private data structure.
|
Initialize MicrocodeFmpDriver private data structure.
|
||||||
|
|
||||||
|
@ -507,7 +680,19 @@ InitializePrivateData (
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = InitializeProcessorInfo (MicrocodeFmpPrivate);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
DEBUG((DEBUG_ERROR, "InitializeProcessorInfo - %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DumpPrivateInfo (MicrocodeFmpPrivate);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,36 +21,6 @@
|
||||||
|
|
||||||
#include "MicrocodeUpdate.h"
|
#include "MicrocodeUpdate.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Verify Microcode.
|
|
||||||
|
|
||||||
Caution: This function may receive untrusted input.
|
|
||||||
|
|
||||||
@param[in] Image The Microcode image buffer.
|
|
||||||
@param[in] ImageSize The size of Microcode image buffer in bytes.
|
|
||||||
@param[in] TryLoad Try to load Microcode or not.
|
|
||||||
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
|
|
||||||
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
|
|
||||||
details for the aborted operation. The buffer is allocated by this function
|
|
||||||
with AllocatePool(), and it is the caller's responsibility to free it with a
|
|
||||||
call to FreePool().
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The Microcode image passes verification.
|
|
||||||
@retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt.
|
|
||||||
@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.
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
VerifyMicrocode (
|
|
||||||
IN VOID *Image,
|
|
||||||
IN UINTN ImageSize,
|
|
||||||
IN BOOLEAN TryLoad,
|
|
||||||
OUT UINT32 *LastAttemptStatus,
|
|
||||||
OUT CHAR16 **AbortReason
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get Microcode Region.
|
Get Microcode Region.
|
||||||
|
|
||||||
|
@ -144,46 +114,92 @@ LoadMicrocode (
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
If the Microcode is used by current processor.
|
Load Microcode on an Application Processor.
|
||||||
|
The function prototype for invoking a function on an Application Processor.
|
||||||
|
|
||||||
@param[in] MicrocodeEntryPoint The Microcode buffer
|
@param[in,out] Buffer The pointer to private data buffer.
|
||||||
|
|
||||||
@retval TRUE The Microcode is used by current processor.
|
|
||||||
@retval FALSE The Microcode is NOT used by current processor.
|
|
||||||
**/
|
**/
|
||||||
BOOLEAN
|
VOID
|
||||||
IsMicrocodeInUse (
|
EFIAPI
|
||||||
IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint
|
MicrocodeLoadAp (
|
||||||
|
IN OUT VOID *Buffer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT32 AttemptStatus;
|
MICROCODE_LOAD_BUFFER *MicrocodeLoadBuffer;
|
||||||
UINTN TotalSize;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
if (MicrocodeEntryPoint->HeaderVersion == 0x1 && MicrocodeEntryPoint->LoaderRevision == 0x1) {
|
MicrocodeLoadBuffer = Buffer;
|
||||||
//
|
MicrocodeLoadBuffer->Revision = LoadMicrocode (MicrocodeLoadBuffer->Address);
|
||||||
// It is the microcode header. It is not the padding data between microcode patches
|
}
|
||||||
// becasue the padding data should not include 0x00000001 and it should be the repeated
|
|
||||||
// byte format (like 0xXYXYXYXY....).
|
/**
|
||||||
//
|
Load new Microcode on this processor
|
||||||
if (MicrocodeEntryPoint->DataSize == 0) {
|
|
||||||
TotalSize = 2048;
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
} else {
|
@param[in] CpuIndex The index of the processor.
|
||||||
TotalSize = MicrocodeEntryPoint->TotalSize;
|
@param[in] Address The address of new Microcode.
|
||||||
}
|
|
||||||
Status = VerifyMicrocode(MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL);
|
@return Loaded Microcode signature.
|
||||||
if (!EFI_ERROR(Status)) {
|
|
||||||
return TRUE;
|
**/
|
||||||
}
|
UINT32
|
||||||
|
LoadMicrocodeOnThis (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
|
||||||
|
IN UINTN CpuIndex,
|
||||||
|
IN UINT64 Address
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_MP_SERVICES_PROTOCOL *MpService;
|
||||||
|
MICROCODE_LOAD_BUFFER MicrocodeLoadBuffer;
|
||||||
|
|
||||||
|
if (CpuIndex == MicrocodeFmpPrivate->BspIndex) {
|
||||||
|
return LoadMicrocode (Address);
|
||||||
|
} else {
|
||||||
|
MpService = MicrocodeFmpPrivate->MpService;
|
||||||
|
MicrocodeLoadBuffer.Address = Address;
|
||||||
|
MicrocodeLoadBuffer.Revision = 0;
|
||||||
|
Status = MpService->StartupThisAP (
|
||||||
|
MpService,
|
||||||
|
MicrocodeLoadAp,
|
||||||
|
CpuIndex,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&MicrocodeLoadBuffer,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
return MicrocodeLoadBuffer.Revision;
|
||||||
}
|
}
|
||||||
return FALSE;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Collect processor information.
|
||||||
|
The function prototype for invoking a function on an Application Processor.
|
||||||
|
|
||||||
|
@param[in,out] Buffer The pointer to private data buffer.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
CollectProcessorInfo (
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PROCESSOR_INFO *ProcessorInfo;
|
||||||
|
|
||||||
|
ProcessorInfo = Buffer;
|
||||||
|
ProcessorInfo->ProcessorSignature = GetCurrentProcessorSignature();
|
||||||
|
ProcessorInfo->PlatformId = GetCurrentPlatformId();
|
||||||
|
ProcessorInfo->MicrocodeRevision = GetCurrentMicrocodeSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get current Microcode information.
|
Get current Microcode information.
|
||||||
|
|
||||||
NOTE: The DescriptorCount/ImageDescriptor/MicrocodeInfo in MicrocodeFmpPrivate
|
The ProcessorInformation (BspIndex/ProcessorCount/ProcessorInfo)
|
||||||
are not avaiable in this function.
|
in MicrocodeFmpPrivate must be initialized.
|
||||||
|
|
||||||
|
The MicrocodeInformation (DescriptorCount/ImageDescriptor/MicrocodeInfo)
|
||||||
|
in MicrocodeFmpPrivate may not be avaiable in this function.
|
||||||
|
|
||||||
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
@param[in] DescriptorCount The count of Microcode ImageDescriptor allocated.
|
@param[in] DescriptorCount The count of Microcode ImageDescriptor allocated.
|
||||||
|
@ -208,6 +224,9 @@ GetMicrocodeInfo (
|
||||||
UINTN Count;
|
UINTN Count;
|
||||||
UINT64 ImageAttributes;
|
UINT64 ImageAttributes;
|
||||||
BOOLEAN IsInUse;
|
BOOLEAN IsInUse;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 AttemptStatus;
|
||||||
|
UINTN TargetCpuIndex;
|
||||||
|
|
||||||
MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
|
MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
|
||||||
MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
|
MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
|
||||||
|
@ -231,7 +250,15 @@ GetMicrocodeInfo (
|
||||||
TotalSize = MicrocodeEntryPoint->TotalSize;
|
TotalSize = MicrocodeEntryPoint->TotalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
IsInUse = IsMicrocodeInUse (MicrocodeEntryPoint);
|
TargetCpuIndex = (UINTN)-1;
|
||||||
|
Status = VerifyMicrocode(MicrocodeFmpPrivate, MicrocodeEntryPoint, TotalSize, FALSE, &AttemptStatus, NULL, &TargetCpuIndex);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
IsInUse = TRUE;
|
||||||
|
ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);
|
||||||
|
MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex = Count;
|
||||||
|
} else {
|
||||||
|
IsInUse = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (ImageDescriptor != NULL && DescriptorCount > Count) {
|
if (ImageDescriptor != NULL && DescriptorCount > Count) {
|
||||||
ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1);
|
ImageDescriptor[Count].ImageIndex = (UINT8)(Count + 1);
|
||||||
|
@ -282,19 +309,63 @@ GetMicrocodeInfo (
|
||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return matched processor information.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
|
@param[in] ProcessorSignature The processor signature to be matched
|
||||||
|
@param[in] ProcessorFlags The processor flags to be matched
|
||||||
|
@param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.
|
||||||
|
On output, the index of target CPU which matches the Microcode.
|
||||||
|
|
||||||
|
@return matched processor information.
|
||||||
|
**/
|
||||||
|
PROCESSOR_INFO *
|
||||||
|
GetMatchedProcessor (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
|
||||||
|
IN UINT32 ProcessorSignature,
|
||||||
|
IN UINT32 ProcessorFlags,
|
||||||
|
IN OUT UINTN *TargetCpuIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
if (*TargetCpuIndex != (UINTN)-1) {
|
||||||
|
Index = *TargetCpuIndex;
|
||||||
|
if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) &&
|
||||||
|
((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) {
|
||||||
|
return &MicrocodeFmpPrivate->ProcessorInfo[Index];
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {
|
||||||
|
if ((ProcessorSignature == MicrocodeFmpPrivate->ProcessorInfo[Index].ProcessorSignature) &&
|
||||||
|
((ProcessorFlags & (1 << MicrocodeFmpPrivate->ProcessorInfo[Index].PlatformId)) != 0)) {
|
||||||
|
*TargetCpuIndex = Index;
|
||||||
|
return &MicrocodeFmpPrivate->ProcessorInfo[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Verify Microcode.
|
Verify Microcode.
|
||||||
|
|
||||||
Caution: This function may receive untrusted input.
|
Caution: This function may receive untrusted input.
|
||||||
|
|
||||||
@param[in] Image The Microcode image buffer.
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
@param[in] ImageSize The size of Microcode image buffer in bytes.
|
@param[in] Image The Microcode image buffer.
|
||||||
@param[in] TryLoad Try to load Microcode or not.
|
@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.
|
@param[in] TryLoad Try to load Microcode or not.
|
||||||
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
|
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
|
||||||
details for the aborted operation. The buffer is allocated by this function
|
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
|
||||||
with AllocatePool(), and it is the caller's responsibility to free it with a
|
details for the aborted operation. The buffer is allocated by this function
|
||||||
call to FreePool().
|
with AllocatePool(), and it is the caller's responsibility to free it with a
|
||||||
|
call to FreePool().
|
||||||
|
@param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.
|
||||||
|
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 corrupt.
|
||||||
|
@ -304,11 +375,13 @@ GetMicrocodeInfo (
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
VerifyMicrocode (
|
VerifyMicrocode (
|
||||||
IN VOID *Image,
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
|
||||||
IN UINTN ImageSize,
|
IN VOID *Image,
|
||||||
IN BOOLEAN TryLoad,
|
IN UINTN ImageSize,
|
||||||
OUT UINT32 *LastAttemptStatus,
|
IN BOOLEAN TryLoad,
|
||||||
OUT CHAR16 **AbortReason
|
OUT UINT32 *LastAttemptStatus,
|
||||||
|
OUT CHAR16 **AbortReason, OPTIONAL
|
||||||
|
IN OUT UINTN *TargetCpuIndex
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
@ -316,8 +389,7 @@ VerifyMicrocode (
|
||||||
UINTN TotalSize;
|
UINTN TotalSize;
|
||||||
UINTN DataSize;
|
UINTN DataSize;
|
||||||
UINT32 CurrentRevision;
|
UINT32 CurrentRevision;
|
||||||
UINT32 CurrentProcessorSignature;
|
PROCESSOR_INFO *ProcessorInfo;
|
||||||
UINT8 CurrentPlatformId;
|
|
||||||
UINT32 CheckSum32;
|
UINT32 CheckSum32;
|
||||||
UINTN ExtendedTableLength;
|
UINTN ExtendedTableLength;
|
||||||
UINT32 ExtendedTableCount;
|
UINT32 ExtendedTableCount;
|
||||||
|
@ -409,11 +481,10 @@ VerifyMicrocode (
|
||||||
//
|
//
|
||||||
// Check ProcessorSignature/ProcessorFlags
|
// Check ProcessorSignature/ProcessorFlags
|
||||||
//
|
//
|
||||||
CorrectMicrocode = FALSE;
|
|
||||||
CurrentProcessorSignature = GetCurrentProcessorSignature();
|
ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, MicrocodeEntryPoint->ProcessorSignature.Uint32, MicrocodeEntryPoint->ProcessorFlags, TargetCpuIndex);
|
||||||
CurrentPlatformId = GetCurrentPlatformId();
|
if (ProcessorInfo == NULL) {
|
||||||
if ((MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) ||
|
CorrectMicrocode = FALSE;
|
||||||
((MicrocodeEntryPoint->ProcessorFlags & (1 << CurrentPlatformId)) == 0)) {
|
|
||||||
ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER));
|
ExtendedTableLength = TotalSize - (DataSize + sizeof(CPU_MICROCODE_HEADER));
|
||||||
if (ExtendedTableLength != 0) {
|
if (ExtendedTableLength != 0) {
|
||||||
//
|
//
|
||||||
|
@ -438,8 +509,8 @@ VerifyMicrocode (
|
||||||
//
|
//
|
||||||
// Verify Header
|
// Verify Header
|
||||||
//
|
//
|
||||||
if ((ExtendedTable->ProcessorSignature.Uint32 == CurrentProcessorSignature) &&
|
ProcessorInfo = GetMatchedProcessor (MicrocodeFmpPrivate, ExtendedTable->ProcessorSignature.Uint32, ExtendedTable->ProcessorFlag, TargetCpuIndex);
|
||||||
(ExtendedTable->ProcessorFlag & (1 << CurrentPlatformId))) {
|
if (ProcessorInfo != NULL) {
|
||||||
//
|
//
|
||||||
// Find one
|
// Find one
|
||||||
//
|
//
|
||||||
|
@ -459,11 +530,7 @@ VerifyMicrocode (
|
||||||
}
|
}
|
||||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
|
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
|
||||||
if (AbortReason != NULL) {
|
if (AbortReason != NULL) {
|
||||||
if (MicrocodeEntryPoint->ProcessorSignature.Uint32 != CurrentProcessorSignature) {
|
*AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature/ProcessorFlags"), L"UnsupportedProcessSignature/ProcessorFlags");
|
||||||
*AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessSignature"), L"UnsupportedProcessSignature");
|
|
||||||
} else {
|
|
||||||
*AbortReason = AllocateCopyPool(sizeof(L"UnsupportedProcessorFlags"), L"UnsupportedProcessorFlags");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -472,8 +539,9 @@ VerifyMicrocode (
|
||||||
//
|
//
|
||||||
// Check UpdateRevision
|
// Check UpdateRevision
|
||||||
//
|
//
|
||||||
CurrentRevision = GetCurrentMicrocodeSignature();
|
CurrentRevision = ProcessorInfo->MicrocodeRevision;
|
||||||
if (MicrocodeEntryPoint->UpdateRevision < CurrentRevision) {
|
if ((MicrocodeEntryPoint->UpdateRevision < CurrentRevision) ||
|
||||||
|
(TryLoad && (MicrocodeEntryPoint->UpdateRevision == CurrentRevision))) {
|
||||||
if (TryLoad) {
|
if (TryLoad) {
|
||||||
DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on UpdateRevision\n"));
|
DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on UpdateRevision\n"));
|
||||||
}
|
}
|
||||||
|
@ -488,7 +556,7 @@ VerifyMicrocode (
|
||||||
// try load MCU
|
// try load MCU
|
||||||
//
|
//
|
||||||
if (TryLoad) {
|
if (TryLoad) {
|
||||||
CurrentRevision = LoadMicrocode((UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));
|
CurrentRevision = LoadMicrocodeOnThis(MicrocodeFmpPrivate, ProcessorInfo->CpuIndex, (UINTN)MicrocodeEntryPoint + sizeof(CPU_MICROCODE_HEADER));
|
||||||
if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) {
|
if (MicrocodeEntryPoint->UpdateRevision != CurrentRevision) {
|
||||||
DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n"));
|
DEBUG((DEBUG_ERROR, "VerifyMicrocode - fail on LoadMicrocode\n"));
|
||||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
|
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
|
||||||
|
@ -502,31 +570,6 @@ VerifyMicrocode (
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Get current Microcode in used.
|
|
||||||
|
|
||||||
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
|
||||||
|
|
||||||
@return current Microcode in used.
|
|
||||||
**/
|
|
||||||
VOID *
|
|
||||||
GetCurrentMicrocodeInUse (
|
|
||||||
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UINTN Index;
|
|
||||||
|
|
||||||
for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
|
|
||||||
if (!MicrocodeFmpPrivate->MicrocodeInfo[Index].InUse) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (IsMicrocodeInUse (MicrocodeFmpPrivate->MicrocodeInfo[Index].MicrocodeEntryPoint)) {
|
|
||||||
return MicrocodeFmpPrivate->MicrocodeInfo[Index].MicrocodeEntryPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get next Microcode entrypoint.
|
Get next Microcode entrypoint.
|
||||||
|
|
||||||
|
@ -622,7 +665,7 @@ UpdateMicrocode (
|
||||||
Update Microcode flash region.
|
Update Microcode flash region.
|
||||||
|
|
||||||
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
@param[in] CurrentMicrocodeEntryPoint Current Microcode entrypoint
|
@param[in] TargetMicrocodeEntryPoint Target Microcode entrypoint to be updated
|
||||||
@param[in] Image The Microcode image buffer.
|
@param[in] Image The Microcode image buffer.
|
||||||
@param[in] ImageSize The size of Microcode image buffer in bytes.
|
@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.
|
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
|
||||||
|
@ -633,7 +676,7 @@ UpdateMicrocode (
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
UpdateMicrocodeFlashRegion (
|
UpdateMicrocodeFlashRegion (
|
||||||
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
|
||||||
IN CPU_MICROCODE_HEADER *CurrentMicrocodeEntryPoint,
|
IN CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint,
|
||||||
IN VOID *Image,
|
IN VOID *Image,
|
||||||
IN UINTN ImageSize,
|
IN UINTN ImageSize,
|
||||||
OUT UINT32 *LastAttemptStatus
|
OUT UINT32 *LastAttemptStatus
|
||||||
|
@ -641,7 +684,7 @@ UpdateMicrocodeFlashRegion (
|
||||||
{
|
{
|
||||||
VOID *MicrocodePatchAddress;
|
VOID *MicrocodePatchAddress;
|
||||||
UINTN MicrocodePatchRegionSize;
|
UINTN MicrocodePatchRegionSize;
|
||||||
UINTN CurrentTotalSize;
|
UINTN TargetTotalSize;
|
||||||
UINTN UsedRegionSize;
|
UINTN UsedRegionSize;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
VOID *MicrocodePatchScratchBuffer;
|
VOID *MicrocodePatchScratchBuffer;
|
||||||
|
@ -669,38 +712,38 @@ UpdateMicrocodeFlashRegion (
|
||||||
ScratchBufferSize = 0;
|
ScratchBufferSize = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Current data collection
|
// Target data collection
|
||||||
//
|
//
|
||||||
CurrentTotalSize = 0;
|
TargetTotalSize = 0;
|
||||||
AvailableSize = 0;
|
AvailableSize = 0;
|
||||||
NextMicrocodeEntryPoint = NULL;
|
NextMicrocodeEntryPoint = NULL;
|
||||||
if (CurrentMicrocodeEntryPoint != NULL) {
|
if (TargetMicrocodeEntryPoint != NULL) {
|
||||||
if (CurrentMicrocodeEntryPoint->DataSize == 0) {
|
if (TargetMicrocodeEntryPoint->DataSize == 0) {
|
||||||
CurrentTotalSize = 2048;
|
TargetTotalSize = 2048;
|
||||||
} else {
|
} else {
|
||||||
CurrentTotalSize = CurrentMicrocodeEntryPoint->TotalSize;
|
TargetTotalSize = TargetMicrocodeEntryPoint->TotalSize;
|
||||||
}
|
}
|
||||||
DEBUG((DEBUG_INFO, " CurrentTotalSize - 0x%x\n", CurrentTotalSize));
|
DEBUG((DEBUG_INFO, " TargetTotalSize - 0x%x\n", TargetTotalSize));
|
||||||
NextMicrocodeEntryPoint = GetNextMicrocode(MicrocodeFmpPrivate, CurrentMicrocodeEntryPoint);
|
NextMicrocodeEntryPoint = GetNextMicrocode(MicrocodeFmpPrivate, TargetMicrocodeEntryPoint);
|
||||||
DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", NextMicrocodeEntryPoint));
|
DEBUG((DEBUG_INFO, " NextMicrocodeEntryPoint - 0x%x\n", NextMicrocodeEntryPoint));
|
||||||
if (NextMicrocodeEntryPoint != NULL) {
|
if (NextMicrocodeEntryPoint != NULL) {
|
||||||
ASSERT ((UINTN)NextMicrocodeEntryPoint >= ((UINTN)CurrentMicrocodeEntryPoint + CurrentTotalSize));
|
ASSERT ((UINTN)NextMicrocodeEntryPoint >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));
|
||||||
AvailableSize = (UINTN)NextMicrocodeEntryPoint - (UINTN)CurrentMicrocodeEntryPoint;
|
AvailableSize = (UINTN)NextMicrocodeEntryPoint - (UINTN)TargetMicrocodeEntryPoint;
|
||||||
} else {
|
} else {
|
||||||
AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)CurrentMicrocodeEntryPoint;
|
AvailableSize = (UINTN)MicrocodePatchAddress + MicrocodePatchRegionSize - (UINTN)TargetMicrocodeEntryPoint;
|
||||||
}
|
}
|
||||||
DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
|
DEBUG((DEBUG_INFO, " AvailableSize - 0x%x\n", AvailableSize));
|
||||||
}
|
}
|
||||||
ASSERT (AvailableSize >= CurrentTotalSize);
|
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 >= CurrentTotalSize);
|
ASSERT (UsedRegionSize >= TargetTotalSize);
|
||||||
if (CurrentMicrocodeEntryPoint != NULL) {
|
if (TargetMicrocodeEntryPoint != NULL) {
|
||||||
ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)CurrentMicrocodeEntryPoint + CurrentTotalSize));
|
ASSERT ((UINTN)MicrocodePatchAddress + UsedRegionSize >= ((UINTN)TargetMicrocodeEntryPoint + TargetTotalSize));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Total Size means the Microcode data size.
|
// Total Size means the Microcode data size.
|
||||||
// Available Size means the Microcode data size plus the pad till next (1) Microcode or (2) the end.
|
// Available Size means the Microcode data size plus the pad till (1) next Microcode or (2) the end.
|
||||||
//
|
//
|
||||||
// (1)
|
// (1)
|
||||||
// +------+-----------+-----+------+===================+
|
// +------+-----------+-----+------+===================+
|
||||||
|
@ -740,23 +783,23 @@ UpdateMicrocodeFlashRegion (
|
||||||
// 1.1. Copy new image
|
// 1.1. Copy new image
|
||||||
CopyMem (ScratchBufferPtr, Image, ImageSize);
|
CopyMem (ScratchBufferPtr, Image, ImageSize);
|
||||||
ScratchBufferSize += ImageSize;
|
ScratchBufferSize += ImageSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
// 1.2. Pad 0xFF
|
// 1.2. Pad 0xFF
|
||||||
RestSize = AvailableSize - ImageSize;
|
RestSize = AvailableSize - ImageSize;
|
||||||
if (RestSize > 0) {
|
if (RestSize > 0) {
|
||||||
SetMem (ScratchBufferPtr, RestSize, 0xFF);
|
SetMem (ScratchBufferPtr, RestSize, 0xFF);
|
||||||
ScratchBufferSize += RestSize;
|
ScratchBufferSize += RestSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
}
|
}
|
||||||
Status = UpdateMicrocode((UINTN)CurrentMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
|
Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 2. If there is enough space to remove old one and add new one, reorg and replace old microcode.
|
// 2. If there is enough space to remove old one and add new one, reorg and replace old microcode.
|
||||||
//
|
//
|
||||||
if (MicrocodePatchRegionSize - (UsedRegionSize - CurrentTotalSize) >= ImageSize) {
|
if (MicrocodePatchRegionSize - (UsedRegionSize - TargetTotalSize) >= ImageSize) {
|
||||||
if (CurrentMicrocodeEntryPoint == NULL) {
|
if (TargetMicrocodeEntryPoint == NULL) {
|
||||||
DEBUG((DEBUG_INFO, "Append new microcode\n"));
|
DEBUG((DEBUG_INFO, "Append new microcode\n"));
|
||||||
//
|
//
|
||||||
// +------+------------+------+===================+
|
// +------+------------+------+===================+
|
||||||
|
@ -780,17 +823,17 @@ UpdateMicrocodeFlashRegion (
|
||||||
// +------+---------------+------+================+
|
// +------+---------------+------+================+
|
||||||
//
|
//
|
||||||
// 2.1. Copy new image
|
// 2.1. Copy new image
|
||||||
CopyMem (MicrocodePatchScratchBuffer, Image, ImageSize);
|
CopyMem (ScratchBufferPtr, Image, ImageSize);
|
||||||
ScratchBufferSize += ImageSize;
|
ScratchBufferSize += ImageSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
// 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 *)CurrentMicrocodeEntryPoint + CurrentTotalSize, RestSize);
|
CopyMem (ScratchBufferPtr, (UINT8 *)TargetMicrocodeEntryPoint + TargetTotalSize, RestSize);
|
||||||
ScratchBufferSize += RestSize;
|
ScratchBufferSize += RestSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
}
|
}
|
||||||
Status = UpdateMicrocode((UINTN)CurrentMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
|
Status = UpdateMicrocode((UINTN)TargetMicrocodeEntryPoint, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
|
||||||
}
|
}
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -815,21 +858,21 @@ UpdateMicrocodeFlashRegion (
|
||||||
MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;
|
MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;
|
||||||
|
|
||||||
// 3.1. Copy new image
|
// 3.1. Copy new image
|
||||||
CopyMem (MicrocodePatchScratchBuffer, Image, ImageSize);
|
CopyMem (ScratchBufferPtr, Image, ImageSize);
|
||||||
ScratchBufferSize += ImageSize;
|
ScratchBufferSize += ImageSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
// 3.2. Copy some others to rest buffer
|
// 3.2. Copy some others to rest buffer
|
||||||
for (Index = 0; Index < MicrocodeCount; Index++) {
|
for (Index = 0; Index < MicrocodeCount; Index++) {
|
||||||
if (!MicrocodeInfo[Index].InUse) {
|
if (!MicrocodeInfo[Index].InUse) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (MicrocodeInfo[Index].MicrocodeEntryPoint == CurrentMicrocodeEntryPoint) {
|
if (MicrocodeInfo[Index].MicrocodeEntryPoint == TargetMicrocodeEntryPoint) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (MicrocodeInfo[Index].TotalSize <= MicrocodePatchRegionSize - ScratchBufferSize) {
|
if (MicrocodeInfo[Index].TotalSize <= MicrocodePatchRegionSize - ScratchBufferSize) {
|
||||||
CopyMem (ScratchBufferPtr, MicrocodeInfo[Index].MicrocodeEntryPoint, MicrocodeInfo[Index].TotalSize);
|
CopyMem (ScratchBufferPtr, MicrocodeInfo[Index].MicrocodeEntryPoint, MicrocodeInfo[Index].TotalSize);
|
||||||
ScratchBufferSize += MicrocodeInfo[Index].TotalSize;
|
ScratchBufferSize += MicrocodeInfo[Index].TotalSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 3.3. Pad 0xFF
|
// 3.3. Pad 0xFF
|
||||||
|
@ -837,7 +880,7 @@ UpdateMicrocodeFlashRegion (
|
||||||
if (RestSize > 0) {
|
if (RestSize > 0) {
|
||||||
SetMem (ScratchBufferPtr, RestSize, 0xFF);
|
SetMem (ScratchBufferPtr, RestSize, 0xFF);
|
||||||
ScratchBufferSize += RestSize;
|
ScratchBufferSize += RestSize;
|
||||||
ScratchBufferPtr = (UINT8 *)ScratchBufferPtr + ScratchBufferSize;
|
ScratchBufferPtr = (UINT8 *)MicrocodePatchScratchBuffer + ScratchBufferSize;
|
||||||
}
|
}
|
||||||
Status = UpdateMicrocode((UINTN)MicrocodePatchAddress, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
|
Status = UpdateMicrocode((UINTN)MicrocodePatchAddress, MicrocodePatchScratchBuffer, ScratchBufferSize, LastAttemptStatus);
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -886,14 +929,9 @@ MicrocodeWrite (
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
VOID *AlignedImage;
|
VOID *AlignedImage;
|
||||||
CPU_MICROCODE_HEADER *CurrentMicrocodeEntryPoint;
|
CPU_MICROCODE_HEADER *TargetMicrocodeEntryPoint;
|
||||||
|
UINTN TargetCpuIndex;
|
||||||
//
|
UINTN TargetMicrcodeIndex;
|
||||||
// We must get Current MicrocodeEntrypoint *before* VerifyMicrocode,
|
|
||||||
// because the MicrocodeSignature might be updated in VerifyMicrocode.
|
|
||||||
//
|
|
||||||
CurrentMicrocodeEntryPoint = GetCurrentMicrocodeInUse(MicrocodeFmpPrivate);
|
|
||||||
DEBUG((DEBUG_INFO, " CurrentMicrocodeEntryPoint - 0x%x\n", CurrentMicrocodeEntryPoint));
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// MCU must be 16 bytes aligned
|
// MCU must be 16 bytes aligned
|
||||||
|
@ -906,7 +944,8 @@ MicrocodeWrite (
|
||||||
}
|
}
|
||||||
|
|
||||||
*LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
|
*LastAttemptVersion = ((CPU_MICROCODE_HEADER *)Image)->UpdateRevision;
|
||||||
Status = VerifyMicrocode(AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason);
|
TargetCpuIndex = (UINTN)-1;
|
||||||
|
Status = VerifyMicrocode(MicrocodeFmpPrivate, AlignedImage, ImageSize, TRUE, LastAttemptStatus, AbortReason, &TargetCpuIndex);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
DEBUG((DEBUG_ERROR, "Fail to verify Microcode Region\n"));
|
DEBUG((DEBUG_ERROR, "Fail to verify Microcode Region\n"));
|
||||||
FreePool(AlignedImage);
|
FreePool(AlignedImage);
|
||||||
|
@ -914,9 +953,21 @@ MicrocodeWrite (
|
||||||
}
|
}
|
||||||
DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));
|
DEBUG((DEBUG_INFO, "Pass VerifyMicrocode\n"));
|
||||||
|
|
||||||
|
DEBUG((DEBUG_INFO, " TargetCpuIndex - 0x%x\n", TargetCpuIndex));
|
||||||
|
ASSERT (TargetCpuIndex < MicrocodeFmpPrivate->ProcessorCount);
|
||||||
|
TargetMicrcodeIndex = MicrocodeFmpPrivate->ProcessorInfo[TargetCpuIndex].MicrocodeIndex;
|
||||||
|
DEBUG((DEBUG_INFO, " TargetMicrcodeIndex - 0x%x\n", TargetMicrcodeIndex));
|
||||||
|
if (TargetMicrcodeIndex != (UINTN)-1) {
|
||||||
|
ASSERT (TargetMicrcodeIndex < MicrocodeFmpPrivate->DescriptorCount);
|
||||||
|
TargetMicrocodeEntryPoint = MicrocodeFmpPrivate->MicrocodeInfo[TargetMicrcodeIndex].MicrocodeEntryPoint;
|
||||||
|
} else {
|
||||||
|
TargetMicrocodeEntryPoint = NULL;
|
||||||
|
}
|
||||||
|
DEBUG((DEBUG_INFO, " TargetMicrocodeEntryPoint - 0x%x\n", TargetMicrocodeEntryPoint));
|
||||||
|
|
||||||
Status = UpdateMicrocodeFlashRegion(
|
Status = UpdateMicrocodeFlashRegion(
|
||||||
MicrocodeFmpPrivate,
|
MicrocodeFmpPrivate,
|
||||||
CurrentMicrocodeEntryPoint,
|
TargetMicrocodeEntryPoint,
|
||||||
AlignedImage,
|
AlignedImage,
|
||||||
ImageSize,
|
ImageSize,
|
||||||
LastAttemptStatus
|
LastAttemptStatus
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <Guid/MicrocodeFmp.h>
|
#include <Guid/MicrocodeFmp.h>
|
||||||
|
|
||||||
#include <Protocol/FirmwareManagement.h>
|
#include <Protocol/FirmwareManagement.h>
|
||||||
|
#include <Protocol/MpService.h>
|
||||||
|
|
||||||
#include <Library/BaseLib.h>
|
#include <Library/BaseLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
@ -56,6 +57,19 @@ typedef struct {
|
||||||
BOOLEAN InUse;
|
BOOLEAN InUse;
|
||||||
} MICROCODE_INFO;
|
} MICROCODE_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN CpuIndex;
|
||||||
|
UINT32 ProcessorSignature;
|
||||||
|
UINT8 PlatformId;
|
||||||
|
UINT32 MicrocodeRevision;
|
||||||
|
UINTN MicrocodeIndex;
|
||||||
|
} PROCESSOR_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Address;
|
||||||
|
UINT32 Revision;
|
||||||
|
} MICROCODE_LOAD_BUFFER;
|
||||||
|
|
||||||
struct _MICROCODE_FMP_PRIVATE_DATA {
|
struct _MICROCODE_FMP_PRIVATE_DATA {
|
||||||
UINT32 Signature;
|
UINT32 Signature;
|
||||||
EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp;
|
EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp;
|
||||||
|
@ -68,6 +82,10 @@ struct _MICROCODE_FMP_PRIVATE_DATA {
|
||||||
UINT32 PackageVersion;
|
UINT32 PackageVersion;
|
||||||
CHAR16 *PackageVersionName;
|
CHAR16 *PackageVersionName;
|
||||||
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE LastAttempt;
|
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE LastAttempt;
|
||||||
|
EFI_MP_SERVICES_PROTOCOL *MpService;
|
||||||
|
UINTN BspIndex;
|
||||||
|
UINTN ProcessorCount;
|
||||||
|
PROCESSOR_INFO *ProcessorInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _MICROCODE_FMP_PRIVATE_DATA MICROCODE_FMP_PRIVATE_DATA;
|
typedef struct _MICROCODE_FMP_PRIVATE_DATA MICROCODE_FMP_PRIVATE_DATA;
|
||||||
|
@ -107,11 +125,26 @@ GetMicrocodeRegion (
|
||||||
OUT UINTN *MicrocodePatchRegionSize
|
OUT UINTN *MicrocodePatchRegionSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Collect processor information.
|
||||||
|
The function prototype for invoking a function on an Application Processor.
|
||||||
|
|
||||||
|
@param[in,out] Buffer The pointer to private data buffer.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
CollectProcessorInfo (
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get current Microcode information.
|
Get current Microcode information.
|
||||||
|
|
||||||
NOTE: The DescriptorCount/ImageDescriptor/MicrocodeInfo in MicrocodeFmpPrivate
|
The ProcessorInformation (BspIndex/ProcessorCount/ProcessorInfo)
|
||||||
are not avaiable in this function.
|
in MicrocodeFmpPrivate must be initialized.
|
||||||
|
|
||||||
|
The MicrocodeInformation (DescriptorCount/ImageDescriptor/MicrocodeInfo)
|
||||||
|
in MicrocodeFmpPrivate may not be avaiable in this function.
|
||||||
|
|
||||||
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
@param[in] DescriptorCount The count of Microcode ImageDescriptor allocated.
|
@param[in] DescriptorCount The count of Microcode ImageDescriptor allocated.
|
||||||
|
@ -128,6 +161,40 @@ GetMicrocodeInfo (
|
||||||
OUT MICROCODE_INFO *MicrocodeInfo OPTIONAL
|
OUT MICROCODE_INFO *MicrocodeInfo OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify Microcode.
|
||||||
|
|
||||||
|
Caution: This function may receive untrusted input.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate The Microcode driver private data
|
||||||
|
@param[in] Image The Microcode image buffer.
|
||||||
|
@param[in] ImageSize The size of Microcode image buffer in bytes.
|
||||||
|
@param[in] TryLoad Try to load Microcode or not.
|
||||||
|
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
|
||||||
|
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
|
||||||
|
details for the aborted operation. The buffer is allocated by this function
|
||||||
|
with AllocatePool(), and it is the caller's responsibility to free it with a
|
||||||
|
call to FreePool().
|
||||||
|
@param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.
|
||||||
|
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_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.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
VerifyMicrocode (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
|
||||||
|
IN VOID *Image,
|
||||||
|
IN UINTN ImageSize,
|
||||||
|
IN BOOLEAN TryLoad,
|
||||||
|
OUT UINT32 *LastAttemptStatus,
|
||||||
|
OUT CHAR16 **AbortReason, OPTIONAL
|
||||||
|
IN OUT UINTN *TargetCpuIndex OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write Microcode.
|
Write Microcode.
|
||||||
|
|
||||||
|
@ -157,6 +224,16 @@ MicrocodeWrite (
|
||||||
OUT CHAR16 **AbortReason
|
OUT CHAR16 **AbortReason
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump private information.
|
||||||
|
|
||||||
|
@param[in] MicrocodeFmpPrivate private data structure.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpPrivateInfo (
|
||||||
|
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns information about the current firmware image(s) of the device.
|
Returns information about the current firmware image(s) of the device.
|
||||||
|
|
||||||
|
|
|
@ -56,13 +56,15 @@
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiFirmwareManagementProtocolGuid ## PRODUCES
|
gEfiFirmwareManagementProtocolGuid ## PRODUCES
|
||||||
|
gEfiMpServiceProtocolGuid ## CONSUMES
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
|
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
|
||||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
|
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiVariableArchProtocolGuid
|
gEfiVariableArchProtocolGuid AND
|
||||||
|
gEfiMpServiceProtocolGuid
|
||||||
|
|
||||||
[UserExtensions.TianoCore."ExtraFiles"]
|
[UserExtensions.TianoCore."ExtraFiles"]
|
||||||
MicrocodeUpdateDxeExtra.uni
|
MicrocodeUpdateDxeExtra.uni
|
||||||
|
|
Loading…
Reference in New Issue