}\r
\r
/**\r
- Determine if a microcode patch will be loaded into memory.\r
+ Determine if a microcode patch matchs the specific processor signature and flag.\r
\r
@param[in] CpuMpData The pointer to CPU MP Data structure.\r
@param[in] ProcessorSignature The processor signature field value\r
@retval FALSE The specified microcode patch will not be loaded.\r
**/\r
BOOLEAN\r
-IsMicrocodePatchNeedLoad (\r
+IsProcessorMatchedMicrocodePatch (\r
IN CPU_MP_DATA *CpuMpData,\r
IN UINT32 ProcessorSignature,\r
IN UINT32 ProcessorFlags\r
}\r
\r
/**\r
- Actual worker function that loads the required microcode patches into memory.\r
+ Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode\r
+ patch header with the CPUID and PlatformID of the processors within\r
+ system to decide if it will be copied into memory.\r
+\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+ @param[in] MicrocodeEntryPoint The pointer to the microcode patch header.\r
+\r
+ @retval TRUE The specified microcode patch need to be loaded.\r
+ @retval FALSE The specified microcode patch dosen't need to be loaded.\r
+**/\r
+BOOLEAN\r
+IsMicrocodePatchNeedLoad (\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ CPU_MICROCODE_HEADER *MicrocodeEntryPoint\r
+ )\r
+{\r
+ BOOLEAN NeedLoad;\r
+ UINTN DataSize;\r
+ UINTN TotalSize;\r
+ CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;\r
+ UINT32 ExtendedTableCount;\r
+ CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.\r
+ //\r
+ NeedLoad = IsProcessorMatchedMicrocodePatch (\r
+ CpuMpData,\r
+ MicrocodeEntryPoint->ProcessorSignature.Uint32,\r
+ MicrocodeEntryPoint->ProcessorFlags\r
+ );\r
+\r
+ //\r
+ // If the Extended Signature Table exists, check if the processor is in the\r
+ // support list\r
+ //\r
+ DataSize = MicrocodeEntryPoint->DataSize;\r
+ TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
+ if ((!NeedLoad) && (DataSize != 0) &&\r
+ (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +\r
+ sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {\r
+ ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
+ + DataSize + sizeof (CPU_MICROCODE_HEADER));\r
+ ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;\r
+ ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
+\r
+ for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
+ //\r
+ // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended\r
+ // Signature Table entry with the CPUID and PlatformID of the processors\r
+ // within system to decide if it will be copied into memory\r
+ //\r
+ NeedLoad = IsProcessorMatchedMicrocodePatch (\r
+ CpuMpData,\r
+ ExtendedTable->ProcessorSignature.Uint32,\r
+ ExtendedTable->ProcessorFlag\r
+ );\r
+ if (NeedLoad) {\r
+ break;\r
+ }\r
+ ExtendedTable ++;\r
+ }\r
+ }\r
+\r
+ return NeedLoad;\r
+}\r
+\r
+\r
+/**\r
+ Actual worker function that shadows the required microcode patches into memory.\r
\r
@param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
@param[in] Patches The pointer to an array of information on\r
to be loaded.\r
**/\r
VOID\r
-LoadMicrocodePatchWorker (\r
+ShadowMicrocodePatchWorker (\r
IN OUT CPU_MP_DATA *CpuMpData,\r
IN MICROCODE_PATCH_INFO *Patches,\r
IN UINTN PatchCount,\r
(VOID *) Patches[Index].Address,\r
Patches[Index].Size\r
);\r
-\r
Walker += Patches[Index].Size;\r
}\r
\r
}\r
\r
/**\r
- Load the required microcode patches data into memory.\r
+ Shadow the required microcode patches data into memory according to PCD\r
+ PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.\r
\r
@param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
**/\r
VOID\r
-LoadMicrocodePatch (\r
+ShadowMicrocodePatchByPcd (\r
IN OUT CPU_MP_DATA *CpuMpData\r
)\r
{\r
UINTN MicrocodeEnd;\r
UINTN DataSize;\r
UINTN TotalSize;\r
- CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;\r
- UINT32 ExtendedTableCount;\r
- CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;\r
MICROCODE_PATCH_INFO *PatchInfoBuffer;\r
UINTN MaxPatchNumber;\r
UINTN PatchCount;\r
UINTN TotalLoadSize;\r
- UINTN Index;\r
- BOOLEAN NeedLoad;\r
\r
//\r
// Initialize the microcode patch related fields in CpuMpData as the values\r
continue;\r
}\r
\r
- //\r
- // Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode\r
- // patch header with the CPUID and PlatformID of the processors within\r
- // system to decide if it will be copied into memory\r
- //\r
- NeedLoad = IsMicrocodePatchNeedLoad (\r
- CpuMpData,\r
- MicrocodeEntryPoint->ProcessorSignature.Uint32,\r
- MicrocodeEntryPoint->ProcessorFlags\r
- );\r
-\r
- //\r
- // If the Extended Signature Table exists, check if the processor is in the\r
- // support list\r
- //\r
- if ((!NeedLoad) && (DataSize != 0) &&\r
- (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +\r
- sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {\r
- ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
- + DataSize + sizeof (CPU_MICROCODE_HEADER));\r
- ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;\r
- ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
-\r
- for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
- //\r
- // Avoid access content beyond MicrocodeEnd\r
- //\r
- if ((UINTN) ExtendedTable > MicrocodeEnd - sizeof (CPU_MICROCODE_EXTENDED_TABLE)) {\r
- break;\r
- }\r
-\r
- //\r
- // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended\r
- // Signature Table entry with the CPUID and PlatformID of the processors\r
- // within system to decide if it will be copied into memory\r
- //\r
- NeedLoad = IsMicrocodePatchNeedLoad (\r
- CpuMpData,\r
- ExtendedTable->ProcessorSignature.Uint32,\r
- ExtendedTable->ProcessorFlag\r
- );\r
- if (NeedLoad) {\r
- break;\r
- }\r
- ExtendedTable ++;\r
- }\r
- }\r
-\r
- if (NeedLoad) {\r
+ if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {\r
PatchCount++;\r
if (PatchCount > MaxPatchNumber) {\r
//\r
__FUNCTION__, PatchCount, TotalLoadSize\r
));\r
\r
- LoadMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
+ ShadowMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
}\r
\r
OnExit:\r
}\r
return;\r
}\r
+\r
+/**\r
+ Shadow the required microcode patches data into memory according to FIT microcode entry.\r
+\r
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+\r
+ @return EFI_SUCCESS Microcode patch is shadowed into memory.\r
+ @return EFI_UNSUPPORTED FIT based microcode shadowing is not supported.\r
+ @return EFI_OUT_OF_RESOURCES No enough memory resource.\r
+ @return EFI_NOT_FOUND There is something wrong in FIT microcode entry.\r
+\r
+**/\r
+EFI_STATUS\r
+ShadowMicrocodePatchByFit (\r
+ IN OUT CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ UINT64 FitPointer;\r
+ FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;\r
+ UINT32 EntryNum;\r
+ UINT32 Index;\r
+ MICROCODE_PATCH_INFO *PatchInfoBuffer;\r
+ UINTN MaxPatchNumber;\r
+ CPU_MICROCODE_HEADER *MicrocodeEntryPoint;\r
+ UINTN PatchCount;\r
+ UINTN TotalSize;\r
+ UINTN TotalLoadSize;\r
+\r
+ if (!FeaturePcdGet (PcdCpuShadowMicrocodeByFit)) {\r
+ return EFI_UNSUPPORTED;\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
+ ASSERT (FALSE);\r
+ return EFI_NOT_FOUND;\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
+ ASSERT (FALSE);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;\r
+\r
+ //\r
+ // Calculate microcode entry number\r
+ //\r
+ MaxPatchNumber = 0;\r
+ for (Index = 0; Index < EntryNum; Index++) {\r
+ if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+ MaxPatchNumber++;\r
+ }\r
+ }\r
+ if (MaxPatchNumber == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));\r
+ if (PatchInfoBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Fill up microcode patch info buffer according to FIT table.\r
+ //\r
+ PatchCount = 0;\r
+ TotalLoadSize = 0;\r
+ for (Index = 0; Index < EntryNum; Index++) {\r
+ if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+ MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) FitEntry[Index].Address;\r
+ TotalSize = (MicrocodeEntryPoint->DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
+ if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {\r
+ PatchInfoBuffer[PatchCount].Address = (UINTN) MicrocodeEntryPoint;\r
+ PatchInfoBuffer[PatchCount].Size = TotalSize;\r
+ TotalLoadSize += TotalSize;\r
+ PatchCount++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (PatchCount != 0) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",\r
+ __FUNCTION__, PatchCount, TotalLoadSize\r
+ ));\r
+\r
+ ShadowMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
+ }\r
+\r
+ FreePool (PatchInfoBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Shadow the required microcode patches data into memory.\r
+\r
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+ShadowMicrocodeUpdatePatch (\r
+ IN OUT CPU_MP_DATA *CpuMpData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = ShadowMicrocodePatchByFit (CpuMpData);\r
+ if (EFI_ERROR (Status)) {\r
+ ShadowMicrocodePatchByPcd (CpuMpData);\r
+ }\r
+}\r