/** @file\r
Produce FMP instance for Microcode.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
@retval EFI_INVALID_PARAMETER The Image was NULL.\r
@retval EFI_NOT_FOUND The current image is not copied to the buffer.\r
@retval EFI_UNSUPPORTED The operation is not supported.\r
- @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.\r
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
\r
**/\r
EFI_STATUS\r
@retval EFI_ABORTED The operation is aborted.\r
@retval EFI_INVALID_PARAMETER The Image was NULL.\r
@retval EFI_UNSUPPORTED The operation is not supported.\r
- @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.\r
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
\r
**/\r
EFI_STATUS\r
}\r
\r
Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);\r
- DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
+ DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, Status - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
VarStatus = gRT->SetVariable(\r
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,\r
&gEfiCallerIdGuid,\r
sizeof(MicrocodeFmpPrivate->LastAttempt),\r
&MicrocodeFmpPrivate->LastAttempt\r
);\r
- DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));\r
+ DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));\r
\r
if (!EFI_ERROR(Status)) {\r
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
@retval EFI_SUCCESS The image was successfully checked.\r
@retval EFI_INVALID_PARAMETER The Image was NULL.\r
@retval EFI_UNSUPPORTED The operation is not supported.\r
- @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.\r
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
\r
**/\r
EFI_STATUS\r
@retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value\r
returned in PackageVersionNameMaxLen.\r
@retval EFI_UNSUPPORTED The operation is not supported.\r
- @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.\r
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
\r
**/\r
EFI_STATUS\r
return EFI_UNSUPPORTED;\r
}\r
\r
+/**\r
+ Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.\r
+\r
+ @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
+\r
+**/\r
+VOID\r
+SortFitMicrocodeInfo (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
+ )\r
+{\r
+ FIT_MICROCODE_INFO *FitMicrocodeEntry;\r
+ FIT_MICROCODE_INFO *NextFitMicrocodeEntry;\r
+ FIT_MICROCODE_INFO TempFitMicrocodeEntry;\r
+ FIT_MICROCODE_INFO *FitMicrocodeEntryEnd;\r
+\r
+ FitMicrocodeEntry = MicrocodeFmpPrivate->FitMicrocodeInfo;\r
+ NextFitMicrocodeEntry = FitMicrocodeEntry + 1;\r
+ FitMicrocodeEntryEnd = MicrocodeFmpPrivate->FitMicrocodeInfo + MicrocodeFmpPrivate->FitMicrocodeEntryCount;\r
+ while (FitMicrocodeEntry < FitMicrocodeEntryEnd) {\r
+ while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) {\r
+ if (FitMicrocodeEntry->MicrocodeEntryPoint > NextFitMicrocodeEntry->MicrocodeEntryPoint) {\r
+ CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
+ CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
+ CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
+ }\r
+\r
+ NextFitMicrocodeEntry = NextFitMicrocodeEntry + 1;\r
+ }\r
+\r
+ FitMicrocodeEntry = FitMicrocodeEntry + 1;\r
+ NextFitMicrocodeEntry = FitMicrocodeEntry + 1;\r
+ }\r
+}\r
+\r
+/**\r
+ Initialize FIT microcode information.\r
+\r
+ @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
+\r
+ @return EFI_SUCCESS FIT microcode information is initialized.\r
+ @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.\r
+ @return EFI_DEVICE_ERROR There is something wrong in FIT microcode entry.\r
+**/\r
+EFI_STATUS\r
+InitializeFitMicrocodeInfo (\r
+ IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
+ )\r
+{\r
+ UINT64 FitPointer;\r
+ FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;\r
+ UINT32 EntryNum;\r
+ UINT32 MicrocodeEntryNum;\r
+ UINT32 Index;\r
+ UINTN Address;\r
+ VOID *MicrocodePatchAddress;\r
+ UINTN MicrocodePatchRegionSize;\r
+ FIT_MICROCODE_INFO *FitMicrocodeInfo;\r
+ FIT_MICROCODE_INFO *FitMicrocodeInfoNext;\r
+ CPU_MICROCODE_HEADER *MicrocodeEntryPoint;\r
+ CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;\r
+ UINTN FitMicrocodeIndex;\r
+ MICROCODE_INFO *MicrocodeInfo;\r
+ UINTN MicrocodeIndex;\r
+\r
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
+ FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);\r
+ MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;\r
+ MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;\r
+ }\r
+\r
+ FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;\r
+ if ((FitPointer == 0) ||\r
+ (FitPointer == 0xFFFFFFFFFFFFFFFF) ||\r
+ (FitPointer == 0xEEEEEEEEEEEEEEEE)) {\r
+ //\r
+ // No FIT table.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;\r
+ if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||\r
+ (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {\r
+ //\r
+ // Invalid FIT table, treat it as no FIT table.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;\r
+\r
+ //\r
+ // Calculate microcode entry number.\r
+ //\r
+ MicrocodeEntryNum = 0;\r
+ for (Index = 0; Index < EntryNum; Index++) {\r
+ if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+ MicrocodeEntryNum++;\r
+ }\r
+ }\r
+ if (MicrocodeEntryNum == 0) {\r
+ //\r
+ // No FIT microcode entry.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer.\r
+ //\r
+ MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));\r
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;\r
+\r
+ MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
+ MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
+\r
+ //\r
+ // Collect microcode entry info.\r
+ //\r
+ MicrocodeEntryNum = 0;\r
+ for (Index = 0; Index < EntryNum; Index++) {\r
+ if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+ Address = (UINTN) FitEntry[Index].Address;\r
+ if ((Address < (UINTN) MicrocodePatchAddress) ||\r
+ (Address >= ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",\r
+ Address\r
+ ));\r
+ goto ErrorExit;\r
+ }\r
+ FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];\r
+ FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) Address;\r
+ if ((*(UINT32 *) Address) == 0xFFFFFFFF) {\r
+ //\r
+ // It is the empty slot as long as the first dword is 0xFFFF_FFFF.\r
+ //\r
+ FitMicrocodeInfo->Empty = TRUE;\r
+ } else {\r
+ FitMicrocodeInfo->Empty = FALSE;\r
+ }\r
+ MicrocodeEntryNum++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Every microcode should have a FIT microcode entry.\r
+ //\r
+ for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {\r
+ MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];\r
+ for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {\r
+ FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];\r
+ if (MicrocodeInfo->MicrocodeEntryPoint == FitMicrocodeInfo->MicrocodeEntryPoint) {\r
+ FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;\r
+ FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;\r
+ break;\r
+ }\r
+ }\r
+ if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",\r
+ MicrocodeInfo->MicrocodeEntryPoint\r
+ ));\r
+ goto ErrorExit;\r
+ }\r
+ }\r
+\r
+ SortFitMicrocodeInfo (MicrocodeFmpPrivate);\r
+\r
+ //\r
+ // Check overlap.\r
+ //\r
+ for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {\r
+ FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];\r
+ MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;\r
+ FitMicrocodeInfoNext = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];\r
+ MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;\r
+ if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||\r
+ ((FitMicrocodeInfo->TotalSize != 0) &&\r
+ ((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >\r
+ (UINTN) MicrocodeEntryPointNext)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",\r
+ MicrocodeEntryPoint,\r
+ MicrocodeEntryPointNext\r
+ ));\r
+ goto ErrorExit;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+ FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);\r
+ MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;\r
+ MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;\r
+ return EFI_DEVICE_ERROR;\r
+}\r
+\r
/**\r
Initialize Processor Microcode Index.\r
\r
\r
@param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
\r
- @return EFI_SUCCESS Microcode Descriptor is initialized.\r
+ @return EFI_SUCCESS Microcode Descriptor is initialized.\r
+ @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.\r
**/\r
EFI_STATUS\r
InitializeMicrocodeDescriptor (\r
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
)\r
{\r
- UINT8 CurrentMicrocodeCount;\r
+ EFI_STATUS Status;\r
+ UINT8 CurrentMicrocodeCount;\r
\r
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);\r
\r
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {\r
MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));\r
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {\r
+ FreePool (MicrocodeFmpPrivate->ImageDescriptor);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
}\r
\r
InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);\r
\r
+ Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool (MicrocodeFmpPrivate->ImageDescriptor);\r
+ FreePool (MicrocodeFmpPrivate->MicrocodeInfo);\r
+ DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));\r
+ return Status;\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
\r
@param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
\r
- @return EFI_SUCCESS private data is initialized.\r
+ @return EFI_SUCCESS Processor information is initialized.\r
+ @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.\r
**/\r
EFI_STATUS\r
InitializeProcessorInfo (\r
PROCESSOR_INFO *ProcessorInfo;\r
MICROCODE_INFO *MicrocodeInfo;\r
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;\r
+ FIT_MICROCODE_INFO *FitMicrocodeInfo;\r
\r
DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));\r
DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));\r
DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));\r
DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));\r
}\r
+\r
+ if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
+ DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));\r
+ FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;\r
+ DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate->FitMicrocodeEntryCount));\r
+ for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",\r
+ Index,\r
+ FitMicrocodeInfo[Index].MicrocodeEntryPoint,\r
+ FitMicrocodeInfo[Index].TotalSize,\r
+ FitMicrocodeInfo[Index].InUse,\r
+ FitMicrocodeInfo[Index].Empty\r
+ ));\r
+ }\r
+ }\r
}\r
\r
/**\r
&VarSize,\r
&MicrocodeFmpPrivate->LastAttempt\r
);\r
- DEBUG((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));\r
- DEBUG((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
+ DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));\r
+ DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
\r
Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);\r
if (!Result) {\r
\r
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
if (EFI_ERROR(Status)) {\r
+ FreePool (MicrocodeFmpPrivate->ProcessorInfo);\r
DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));\r
return Status;\r
}\r