2 Implementation of loading microcode on processors.
4 Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Get microcode update signature of currently loaded microcode update.
14 @return Microcode signature.
17 GetCurrentMicrocodeSignature (
21 MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr
;
23 AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID
, 0);
24 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, NULL
);
25 BiosSignIdMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID
);
26 return BiosSignIdMsr
.Bits
.MicrocodeUpdateSignature
;
30 Detect whether specified processor can find matching microcode patch and load it.
32 Microcode Payload as the following format:
33 +----------------------------------------+------------------+
34 | CPU_MICROCODE_HEADER | |
35 +----------------------------------------+ CheckSum Part1 |
36 | Microcode Binary | |
37 +----------------------------------------+------------------+
38 | CPU_MICROCODE_EXTENDED_TABLE_HEADER | |
39 +----------------------------------------+ CheckSum Part2 |
40 | CPU_MICROCODE_EXTENDED_TABLE | |
42 +----------------------------------------+------------------+
44 There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.
45 The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignatureCount
46 of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.
48 When we are trying to verify the CheckSum32 with extended table.
49 We should use the fields of exnteded table to replace the corresponding
50 fields in CPU_MICROCODE_HEADER structure, and recalculate the
51 CheckSum32 with CPU_MICROCODE_HEADER + Microcode Binary. We named
54 The CheckSum Part2 is used to verify the CPU_MICROCODE_EXTENDED_TABLE_HEADER
55 and CPU_MICROCODE_EXTENDED_TABLE parts. We should make sure CheckSum Part2
56 is correct before we are going to verify each CPU_MICROCODE_EXTENDED_TABLE.
58 Only ProcessorSignature, ProcessorFlag and CheckSum are different between
59 CheckSum Part1 and CheckSum Part3. To avoid multiple computing CheckSum Part3.
60 Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
61 When we are going to calculate CheckSum32, just should use the corresponding part
62 of the ProcessorSignature, ProcessorFlag and CheckSum with in-complete CheckSum32.
64 Notes: CheckSum32 is not a strong verification.
65 It does not guarantee that the data has not been modified.
66 CPU has its own mechanism to verify Microcode Binary part.
68 @param[in] CpuMpData The pointer to CPU MP Data structure.
69 @param[in] ProcessorNumber The handle number of the processor. The range is
70 from 0 to the total number of logical processors
75 IN CPU_MP_DATA
*CpuMpData
,
76 IN UINTN ProcessorNumber
79 UINT32 ExtendedTableLength
;
80 UINT32 ExtendedTableCount
;
81 CPU_MICROCODE_EXTENDED_TABLE
*ExtendedTable
;
82 CPU_MICROCODE_EXTENDED_TABLE_HEADER
*ExtendedTableHeader
;
83 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
87 CPUID_VERSION_INFO_EAX Eax
;
89 UINT32 CurrentRevision
;
90 UINT32 LatestRevision
;
93 UINT32 InCompleteCheckSum32
;
94 BOOLEAN CorrectMicrocode
;
96 MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr
;
100 if (CpuMpData
->MicrocodePatchRegionSize
== 0) {
102 // There is no microcode patches
107 CurrentRevision
= GetCurrentMicrocodeSignature ();
108 IsBspCallIn
= (ProcessorNumber
== (UINTN
)CpuMpData
->BspNumber
) ? TRUE
: FALSE
;
110 GetProcessorLocationByApicId (GetInitialApicId (), NULL
, NULL
, &ThreadId
);
113 // Skip loading microcode if it is not the first thread in one core.
118 ExtendedTableLength
= 0;
120 // Here data of CPUID leafs have not been collected into context buffer, so
121 // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
123 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, NULL
, NULL
);
126 // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
128 PlatformIdMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_PLATFORM_ID
);
129 PlatformId
= (UINT8
) PlatformIdMsr
.Bits
.PlatformId
;
133 // Check whether AP has same processor with BSP.
134 // If yes, direct use microcode info saved by BSP.
138 // Get the CPU data for BSP
140 CpuData
= &(CpuMpData
->CpuData
[CpuMpData
->BspNumber
]);
141 if ((CpuData
->ProcessorSignature
== Eax
.Uint32
) &&
142 (CpuData
->PlatformId
== PlatformId
) &&
143 (CpuData
->MicrocodeEntryAddr
!= 0)) {
144 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*)(UINTN
) CpuData
->MicrocodeEntryAddr
;
145 MicrocodeData
= (VOID
*) (MicrocodeEntryPoint
+ 1);
146 LatestRevision
= MicrocodeEntryPoint
->UpdateRevision
;
152 MicrocodeData
= NULL
;
153 MicrocodeEnd
= (UINTN
) (CpuMpData
->MicrocodePatchAddress
+ CpuMpData
->MicrocodePatchRegionSize
);
154 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
158 // Check if the microcode is for the Cpu and the version is newer
159 // and the update can be processed on the platform
161 CorrectMicrocode
= FALSE
;
163 if (MicrocodeEntryPoint
->DataSize
== 0) {
164 TotalSize
= sizeof (CPU_MICROCODE_HEADER
) + 2000;
166 TotalSize
= sizeof (CPU_MICROCODE_HEADER
) + MicrocodeEntryPoint
->DataSize
;
170 /// 0x0 MicrocodeBegin MicrocodeEntry MicrocodeEnd 0xffffffff
171 /// |--------------|---------------|---------------|---------------|
173 /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEntry).
174 /// And it should be aligned with 4 bytes.
175 /// If the TotalSize is invalid, skip 1KB to check next entry.
177 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
178 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
179 (TotalSize
& 0x3) != 0
181 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
186 // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
188 InCompleteCheckSum32
= CalculateSum32 (
189 (UINT32
*) MicrocodeEntryPoint
,
192 InCompleteCheckSum32
-= MicrocodeEntryPoint
->ProcessorSignature
.Uint32
;
193 InCompleteCheckSum32
-= MicrocodeEntryPoint
->ProcessorFlags
;
194 InCompleteCheckSum32
-= MicrocodeEntryPoint
->Checksum
;
196 if (MicrocodeEntryPoint
->HeaderVersion
== 0x1) {
198 // It is the microcode header. It is not the padding data between microcode patches
199 // because the padding data should not include 0x00000001 and it should be the repeated
200 // byte format (like 0xXYXYXYXY....).
202 if (MicrocodeEntryPoint
->ProcessorSignature
.Uint32
== Eax
.Uint32
&&
203 MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
&&
204 (MicrocodeEntryPoint
->ProcessorFlags
& (1 << PlatformId
))
207 // Calculate CheckSum Part1.
209 CheckSum32
= InCompleteCheckSum32
;
210 CheckSum32
+= MicrocodeEntryPoint
->ProcessorSignature
.Uint32
;
211 CheckSum32
+= MicrocodeEntryPoint
->ProcessorFlags
;
212 CheckSum32
+= MicrocodeEntryPoint
->Checksum
;
213 if (CheckSum32
== 0) {
214 CorrectMicrocode
= TRUE
;
216 } else if ((MicrocodeEntryPoint
->DataSize
!= 0) &&
217 (MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
)) {
218 ExtendedTableLength
= MicrocodeEntryPoint
->TotalSize
- (MicrocodeEntryPoint
->DataSize
+
219 sizeof (CPU_MICROCODE_HEADER
));
220 if (ExtendedTableLength
!= 0) {
222 // Extended Table exist, check if the CPU in support list
224 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
225 + MicrocodeEntryPoint
->DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
227 // Calculate Extended Checksum
229 if ((ExtendedTableLength
% 4) == 0) {
231 // Calculate CheckSum Part2.
233 CheckSum32
= CalculateSum32 ((UINT32
*) ExtendedTableHeader
, ExtendedTableLength
);
234 if (CheckSum32
== 0) {
238 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
239 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
240 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
242 // Calculate CheckSum Part3.
244 CheckSum32
= InCompleteCheckSum32
;
245 CheckSum32
+= ExtendedTable
->ProcessorSignature
.Uint32
;
246 CheckSum32
+= ExtendedTable
->ProcessorFlag
;
247 CheckSum32
+= ExtendedTable
->Checksum
;
248 if (CheckSum32
== 0) {
252 if ((ExtendedTable
->ProcessorSignature
.Uint32
== Eax
.Uint32
) &&
253 (ExtendedTable
->ProcessorFlag
& (1 << PlatformId
)) ) {
257 CorrectMicrocode
= TRUE
;
269 // It is the padding data between the microcode patches for microcode patches alignment.
270 // Because the microcode patch is the multiple of 1-KByte, the padding data should not
271 // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
272 // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
273 // find the next possible microcode patch header.
275 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
279 // Get the next patch.
281 if (MicrocodeEntryPoint
->DataSize
== 0) {
284 TotalSize
= MicrocodeEntryPoint
->TotalSize
;
287 if (CorrectMicrocode
) {
288 LatestRevision
= MicrocodeEntryPoint
->UpdateRevision
;
289 MicrocodeData
= (VOID
*) ((UINTN
) MicrocodeEntryPoint
+ sizeof (CPU_MICROCODE_HEADER
));
292 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
293 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
296 if (LatestRevision
!= 0) {
298 // Save the detected microcode patch entry address (including the
299 // microcode patch header) for each processor.
300 // It will be used when building the microcode patch cache HOB.
302 CpuMpData
->CpuData
[ProcessorNumber
].MicrocodeEntryAddr
=
303 (UINTN
) MicrocodeData
- sizeof (CPU_MICROCODE_HEADER
);
306 if (LatestRevision
> CurrentRevision
) {
308 // BIOS only authenticate updates that contain a numerically larger revision
309 // than the currently loaded revision, where Current Signature < New Update
310 // Revision. A processor with no loaded update is considered to have a
311 // revision equal to zero.
313 ASSERT (MicrocodeData
!= NULL
);
315 MSR_IA32_BIOS_UPDT_TRIG
,
316 (UINT64
) (UINTN
) MicrocodeData
319 // Get and check new microcode signature
321 CurrentRevision
= GetCurrentMicrocodeSignature ();
322 if (CurrentRevision
!= LatestRevision
) {
323 AcquireSpinLock(&CpuMpData
->MpLock
);
324 DEBUG ((EFI_D_ERROR
, "Updated microcode signature [0x%08x] does not match \
325 loaded microcode signature [0x%08x]\n", CurrentRevision
, LatestRevision
));
326 ReleaseSpinLock(&CpuMpData
->MpLock
);
332 Determine if a microcode patch matchs the specific processor signature and flag.
334 @param[in] CpuMpData The pointer to CPU MP Data structure.
335 @param[in] ProcessorSignature The processor signature field value
336 supported by a microcode patch.
337 @param[in] ProcessorFlags The prcessor flags field value supported by
340 @retval TRUE The specified microcode patch will be loaded.
341 @retval FALSE The specified microcode patch will not be loaded.
344 IsProcessorMatchedMicrocodePatch (
345 IN CPU_MP_DATA
*CpuMpData
,
346 IN UINT32 ProcessorSignature
,
347 IN UINT32 ProcessorFlags
351 CPU_AP_DATA
*CpuData
;
353 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
354 CpuData
= &CpuMpData
->CpuData
[Index
];
355 if ((ProcessorSignature
== CpuData
->ProcessorSignature
) &&
356 (ProcessorFlags
& (1 << CpuData
->PlatformId
)) != 0) {
365 Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
366 patch header with the CPUID and PlatformID of the processors within
367 system to decide if it will be copied into memory.
369 @param[in] CpuMpData The pointer to CPU MP Data structure.
370 @param[in] MicrocodeEntryPoint The pointer to the microcode patch header.
372 @retval TRUE The specified microcode patch need to be loaded.
373 @retval FALSE The specified microcode patch dosen't need to be loaded.
376 IsMicrocodePatchNeedLoad (
377 IN CPU_MP_DATA
*CpuMpData
,
378 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
384 CPU_MICROCODE_EXTENDED_TABLE_HEADER
*ExtendedTableHeader
;
385 UINT32 ExtendedTableCount
;
386 CPU_MICROCODE_EXTENDED_TABLE
*ExtendedTable
;
390 // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.
392 NeedLoad
= IsProcessorMatchedMicrocodePatch (
394 MicrocodeEntryPoint
->ProcessorSignature
.Uint32
,
395 MicrocodeEntryPoint
->ProcessorFlags
399 // If the Extended Signature Table exists, check if the processor is in the
402 DataSize
= MicrocodeEntryPoint
->DataSize
;
403 TotalSize
= (DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
404 if ((!NeedLoad
) && (DataSize
!= 0) &&
405 (TotalSize
- DataSize
> sizeof (CPU_MICROCODE_HEADER
) +
406 sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER
))) {
407 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
408 + DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
409 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
410 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
412 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
414 // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
415 // Signature Table entry with the CPUID and PlatformID of the processors
416 // within system to decide if it will be copied into memory
418 NeedLoad
= IsProcessorMatchedMicrocodePatch (
420 ExtendedTable
->ProcessorSignature
.Uint32
,
421 ExtendedTable
->ProcessorFlag
435 Actual worker function that shadows the required microcode patches into memory.
437 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
438 @param[in] Patches The pointer to an array of information on
439 the microcode patches that will be loaded
441 @param[in] PatchCount The number of microcode patches that will
442 be loaded into memory.
443 @param[in] TotalLoadSize The total size of all the microcode patches
447 ShadowMicrocodePatchWorker (
448 IN OUT CPU_MP_DATA
*CpuMpData
,
449 IN MICROCODE_PATCH_INFO
*Patches
,
451 IN UINTN TotalLoadSize
455 VOID
*MicrocodePatchInRam
;
458 ASSERT ((Patches
!= NULL
) && (PatchCount
!= 0));
460 MicrocodePatchInRam
= AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize
));
461 if (MicrocodePatchInRam
== NULL
) {
466 // Load all the required microcode patches into memory
468 for (Walker
= MicrocodePatchInRam
, Index
= 0; Index
< PatchCount
; Index
++) {
471 (VOID
*) Patches
[Index
].Address
,
474 Walker
+= Patches
[Index
].Size
;
478 // Update the microcode patch related fields in CpuMpData
480 CpuMpData
->MicrocodePatchAddress
= (UINTN
) MicrocodePatchInRam
;
481 CpuMpData
->MicrocodePatchRegionSize
= TotalLoadSize
;
485 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
486 __FUNCTION__
, CpuMpData
->MicrocodePatchAddress
, CpuMpData
->MicrocodePatchRegionSize
493 Shadow the required microcode patches data into memory according to PCD
494 PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.
496 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
499 ShadowMicrocodePatchByPcd (
500 IN OUT CPU_MP_DATA
*CpuMpData
503 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
507 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
508 UINTN MaxPatchNumber
;
513 // Initialize the microcode patch related fields in CpuMpData as the values
514 // specified by the PCD pair. If the microcode patches are loaded into memory,
515 // these fields will be updated.
517 CpuMpData
->MicrocodePatchAddress
= PcdGet64 (PcdCpuMicrocodePatchAddress
);
518 CpuMpData
->MicrocodePatchRegionSize
= PcdGet64 (PcdCpuMicrocodePatchRegionSize
);
520 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
521 MicrocodeEnd
= (UINTN
) MicrocodeEntryPoint
+
522 (UINTN
) CpuMpData
->MicrocodePatchRegionSize
;
523 if ((MicrocodeEntryPoint
== NULL
) || ((UINTN
) MicrocodeEntryPoint
== MicrocodeEnd
)) {
525 // There is no microcode patches
531 MaxPatchNumber
= DEFAULT_MAX_MICROCODE_PATCH_NUM
;
533 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
534 if (PatchInfoBuffer
== NULL
) {
539 // Process the header of each microcode patch within the region.
540 // The purpose is to decide which microcode patch(es) will be loaded into memory.
543 if (MicrocodeEntryPoint
->HeaderVersion
!= 0x1) {
545 // Padding data between the microcode patches, skip 1KB to check next entry.
547 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
551 DataSize
= MicrocodeEntryPoint
->DataSize
;
552 TotalSize
= (DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
553 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
554 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
555 (DataSize
& 0x3) != 0 ||
556 (TotalSize
& (SIZE_1KB
- 1)) != 0 ||
560 // Not a valid microcode header, skip 1KB to check next entry.
562 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
566 if (IsMicrocodePatchNeedLoad (CpuMpData
, MicrocodeEntryPoint
)) {
568 if (PatchCount
> MaxPatchNumber
) {
570 // Current 'PatchInfoBuffer' cannot hold the information, double the size
571 // and allocate a new buffer.
573 if (MaxPatchNumber
> MAX_UINTN
/ 2 / sizeof (MICROCODE_PATCH_INFO
)) {
575 // Overflow check for MaxPatchNumber
580 PatchInfoBuffer
= ReallocatePool (
581 MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
582 2 * MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
585 if (PatchInfoBuffer
== NULL
) {
588 MaxPatchNumber
= MaxPatchNumber
* 2;
592 // Store the information of this microcode patch
594 PatchInfoBuffer
[PatchCount
- 1].Address
= (UINTN
) MicrocodeEntryPoint
;
595 PatchInfoBuffer
[PatchCount
- 1].Size
= TotalSize
;
596 TotalLoadSize
+= TotalSize
;
600 // Process the next microcode patch
602 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
603 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
605 if (PatchCount
!= 0) {
608 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
609 __FUNCTION__
, PatchCount
, TotalLoadSize
612 ShadowMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
616 if (PatchInfoBuffer
!= NULL
) {
617 FreePool (PatchInfoBuffer
);
623 Shadow the required microcode patches data into memory according to FIT microcode entry.
625 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
627 @return EFI_SUCCESS Microcode patch is shadowed into memory.
628 @return EFI_UNSUPPORTED FIT based microcode shadowing is not supported.
629 @return EFI_OUT_OF_RESOURCES No enough memory resource.
630 @return EFI_NOT_FOUND There is something wrong in FIT microcode entry.
634 ShadowMicrocodePatchByFit (
635 IN OUT CPU_MP_DATA
*CpuMpData
639 FIRMWARE_INTERFACE_TABLE_ENTRY
*FitEntry
;
642 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
643 UINTN MaxPatchNumber
;
644 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
649 if (!FeaturePcdGet (PcdCpuShadowMicrocodeByFit
)) {
650 return EFI_UNSUPPORTED
;
653 FitPointer
= *(UINT64
*) (UINTN
) FIT_POINTER_ADDRESS
;
654 if ((FitPointer
== 0) ||
655 (FitPointer
== 0xFFFFFFFFFFFFFFFF) ||
656 (FitPointer
== 0xEEEEEEEEEEEEEEEE)) {
661 return EFI_NOT_FOUND
;
663 FitEntry
= (FIRMWARE_INTERFACE_TABLE_ENTRY
*) (UINTN
) FitPointer
;
664 if ((FitEntry
[0].Type
!= FIT_TYPE_00_HEADER
) ||
665 (FitEntry
[0].Address
!= FIT_TYPE_00_SIGNATURE
)) {
667 // Invalid FIT table, treat it as no FIT table.
670 return EFI_NOT_FOUND
;
673 EntryNum
= *(UINT32
*)(&FitEntry
[0].Size
[0]) & 0xFFFFFF;
676 // Calculate microcode entry number
679 for (Index
= 0; Index
< EntryNum
; Index
++) {
680 if (FitEntry
[Index
].Type
== FIT_TYPE_01_MICROCODE
) {
684 if (MaxPatchNumber
== 0) {
685 return EFI_NOT_FOUND
;
688 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
689 if (PatchInfoBuffer
== NULL
) {
690 return EFI_OUT_OF_RESOURCES
;
694 // Fill up microcode patch info buffer according to FIT table.
698 for (Index
= 0; Index
< EntryNum
; Index
++) {
699 if (FitEntry
[Index
].Type
== FIT_TYPE_01_MICROCODE
) {
700 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) FitEntry
[Index
].Address
;
701 TotalSize
= (MicrocodeEntryPoint
->DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
702 if (IsMicrocodePatchNeedLoad (CpuMpData
, MicrocodeEntryPoint
)) {
703 PatchInfoBuffer
[PatchCount
].Address
= (UINTN
) MicrocodeEntryPoint
;
704 PatchInfoBuffer
[PatchCount
].Size
= TotalSize
;
705 TotalLoadSize
+= TotalSize
;
711 if (PatchCount
!= 0) {
714 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
715 __FUNCTION__
, PatchCount
, TotalLoadSize
718 ShadowMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
721 FreePool (PatchInfoBuffer
);
726 Shadow the required microcode patches data into memory.
728 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
731 ShadowMicrocodeUpdatePatch (
732 IN OUT CPU_MP_DATA
*CpuMpData
737 Status
= ShadowMicrocodePatchByFit (CpuMpData
);
738 if (EFI_ERROR (Status
)) {
739 ShadowMicrocodePatchByPcd (CpuMpData
);
744 Get the cached microcode patch base address and size from the microcode patch
745 information cache HOB.
747 @param[out] Address Base address of the microcode patches data.
748 It will be updated if the microcode patch
749 information cache HOB is found.
750 @param[out] RegionSize Size of the microcode patches data.
751 It will be updated if the microcode patch
752 information cache HOB is found.
754 @retval TRUE The microcode patch information cache HOB is found.
755 @retval FALSE The microcode patch information cache HOB is not found.
759 GetMicrocodePatchInfoFromHob (
764 EFI_HOB_GUID_TYPE
*GuidHob
;
765 EDKII_MICROCODE_PATCH_HOB
*MicrocodePathHob
;
767 GuidHob
= GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid
);
768 if (GuidHob
== NULL
) {
769 DEBUG((DEBUG_INFO
, "%a: Microcode patch cache HOB is not found.\n", __FUNCTION__
));
773 MicrocodePathHob
= GET_GUID_HOB_DATA (GuidHob
);
775 *Address
= MicrocodePathHob
->MicrocodePatchAddress
;
776 *RegionSize
= MicrocodePathHob
->MicrocodePatchRegionSize
;
779 DEBUG_INFO
, "%a: MicrocodeBase = 0x%lx, MicrocodeSize = 0x%lx\n",
780 __FUNCTION__
, *Address
, *RegionSize