+ // There is no microcode patches\r
+ //\r
+ return;\r
+ }\r
+\r
+ PatchCount = 0;\r
+ MaxPatchNumber = DEFAULT_MAX_MICROCODE_PATCH_NUM;\r
+ TotalLoadSize = 0;\r
+ PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));\r
+ if (PatchInfoBuffer == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Process the header of each microcode patch within the region.\r
+ // The purpose is to decide which microcode patch(es) will be loaded into memory.\r
+ //\r
+ do {\r
+ if (MicrocodeEntryPoint->HeaderVersion != 0x1) {\r
+ //\r
+ // Padding data between the microcode patches, skip 1KB to check next entry.\r
+ //\r
+ MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
+ continue;\r
+ }\r
+\r
+ DataSize = MicrocodeEntryPoint->DataSize;\r
+ TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
+ if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||\r
+ ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||\r
+ (DataSize & 0x3) != 0 ||\r
+ (TotalSize & (SIZE_1KB - 1)) != 0 ||\r
+ TotalSize < DataSize\r
+ ) {\r
+ //\r
+ // Not a valid microcode header, skip 1KB to check next entry.\r
+ //\r
+ MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\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
+ PatchCount++;\r
+ if (PatchCount > MaxPatchNumber) {\r
+ //\r
+ // Current 'PatchInfoBuffer' cannot hold the information, double the size\r
+ // and allocate a new buffer.\r
+ //\r
+ if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {\r
+ //\r
+ // Overflow check for MaxPatchNumber\r
+ //\r
+ goto OnExit;\r
+ }\r
+\r
+ PatchInfoBuffer = ReallocatePool (\r
+ MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
+ 2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
+ PatchInfoBuffer\r
+ );\r
+ if (PatchInfoBuffer == NULL) {\r
+ goto OnExit;\r
+ }\r
+ MaxPatchNumber = MaxPatchNumber * 2;\r
+ }\r
+\r
+ //\r
+ // Store the information of this microcode patch\r
+ //\r
+ if (TotalSize > ALIGN_VALUE (TotalSize, SIZE_1KB) ||\r
+ ALIGN_VALUE (TotalSize, SIZE_1KB) > MAX_UINTN - TotalLoadSize) {\r
+ goto OnExit;\r
+ }\r
+ PatchInfoBuffer[PatchCount - 1].Address = (UINTN) MicrocodeEntryPoint;\r
+ PatchInfoBuffer[PatchCount - 1].Size = TotalSize;\r
+ PatchInfoBuffer[PatchCount - 1].AlignedSize = ALIGN_VALUE (TotalSize, SIZE_1KB);\r
+ TotalLoadSize += PatchInfoBuffer[PatchCount - 1].AlignedSize;\r
+ }\r
+\r
+ //\r
+ // Process the next microcode patch\r
+ //\r
+ MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);\r
+ } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\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
+ LoadMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
+ }\r
+\r
+OnExit:\r
+ if (PatchInfoBuffer != NULL) {\r
+ FreePool (PatchInfoBuffer);\r