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
;
99 if (CpuMpData
->MicrocodePatchRegionSize
== 0) {
101 // There is no microcode patches
106 CurrentRevision
= GetCurrentMicrocodeSignature ();
107 IsBspCallIn
= (ProcessorNumber
== (UINTN
)CpuMpData
->BspNumber
) ? TRUE
: FALSE
;
109 GetProcessorLocationByApicId (GetInitialApicId (), NULL
, NULL
, &ThreadId
);
112 // Skip loading microcode if it is not the first thread in one core.
117 ExtendedTableLength
= 0;
118 Eax
.Uint32
= CpuMpData
->CpuData
[ProcessorNumber
].ProcessorSignature
;
119 PlatformId
= CpuMpData
->CpuData
[ProcessorNumber
].PlatformId
;
122 // Check whether AP has same processor with BSP.
123 // If yes, direct use microcode info saved by BSP.
127 // Get the CPU data for BSP
129 CpuData
= &(CpuMpData
->CpuData
[CpuMpData
->BspNumber
]);
130 if ((CpuData
->ProcessorSignature
== Eax
.Uint32
) &&
131 (CpuData
->PlatformId
== PlatformId
) &&
132 (CpuData
->MicrocodeEntryAddr
!= 0)) {
133 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*)(UINTN
) CpuData
->MicrocodeEntryAddr
;
134 MicrocodeData
= (VOID
*) (MicrocodeEntryPoint
+ 1);
135 LatestRevision
= MicrocodeEntryPoint
->UpdateRevision
;
141 MicrocodeData
= NULL
;
142 MicrocodeEnd
= (UINTN
) (CpuMpData
->MicrocodePatchAddress
+ CpuMpData
->MicrocodePatchRegionSize
);
143 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
147 // Check if the microcode is for the Cpu and the version is newer
148 // and the update can be processed on the platform
150 CorrectMicrocode
= FALSE
;
152 if (MicrocodeEntryPoint
->DataSize
== 0) {
153 TotalSize
= sizeof (CPU_MICROCODE_HEADER
) + 2000;
155 TotalSize
= sizeof (CPU_MICROCODE_HEADER
) + MicrocodeEntryPoint
->DataSize
;
159 /// 0x0 MicrocodeBegin MicrocodeEntry MicrocodeEnd 0xffffffff
160 /// |--------------|---------------|---------------|---------------|
162 /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEntry).
163 /// And it should be aligned with 4 bytes.
164 /// If the TotalSize is invalid, skip 1KB to check next entry.
166 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
167 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
168 (TotalSize
& 0x3) != 0
170 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
175 // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
177 InCompleteCheckSum32
= CalculateSum32 (
178 (UINT32
*) MicrocodeEntryPoint
,
181 InCompleteCheckSum32
-= MicrocodeEntryPoint
->ProcessorSignature
.Uint32
;
182 InCompleteCheckSum32
-= MicrocodeEntryPoint
->ProcessorFlags
;
183 InCompleteCheckSum32
-= MicrocodeEntryPoint
->Checksum
;
185 if (MicrocodeEntryPoint
->HeaderVersion
== 0x1) {
187 // It is the microcode header. It is not the padding data between microcode patches
188 // because the padding data should not include 0x00000001 and it should be the repeated
189 // byte format (like 0xXYXYXYXY....).
191 if (MicrocodeEntryPoint
->ProcessorSignature
.Uint32
== Eax
.Uint32
&&
192 MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
&&
193 (MicrocodeEntryPoint
->ProcessorFlags
& (1 << PlatformId
))
196 // Calculate CheckSum Part1.
198 CheckSum32
= InCompleteCheckSum32
;
199 CheckSum32
+= MicrocodeEntryPoint
->ProcessorSignature
.Uint32
;
200 CheckSum32
+= MicrocodeEntryPoint
->ProcessorFlags
;
201 CheckSum32
+= MicrocodeEntryPoint
->Checksum
;
202 if (CheckSum32
== 0) {
203 CorrectMicrocode
= TRUE
;
205 } else if ((MicrocodeEntryPoint
->DataSize
!= 0) &&
206 (MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
)) {
207 ExtendedTableLength
= MicrocodeEntryPoint
->TotalSize
- (MicrocodeEntryPoint
->DataSize
+
208 sizeof (CPU_MICROCODE_HEADER
));
209 if (ExtendedTableLength
!= 0) {
211 // Extended Table exist, check if the CPU in support list
213 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
214 + MicrocodeEntryPoint
->DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
216 // Calculate Extended Checksum
218 if ((ExtendedTableLength
% 4) == 0) {
220 // Calculate CheckSum Part2.
222 CheckSum32
= CalculateSum32 ((UINT32
*) ExtendedTableHeader
, ExtendedTableLength
);
223 if (CheckSum32
== 0) {
227 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
228 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
229 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
231 // Calculate CheckSum Part3.
233 CheckSum32
= InCompleteCheckSum32
;
234 CheckSum32
+= ExtendedTable
->ProcessorSignature
.Uint32
;
235 CheckSum32
+= ExtendedTable
->ProcessorFlag
;
236 CheckSum32
+= ExtendedTable
->Checksum
;
237 if (CheckSum32
== 0) {
241 if ((ExtendedTable
->ProcessorSignature
.Uint32
== Eax
.Uint32
) &&
242 (ExtendedTable
->ProcessorFlag
& (1 << PlatformId
)) ) {
246 CorrectMicrocode
= TRUE
;
258 // It is the padding data between the microcode patches for microcode patches alignment.
259 // Because the microcode patch is the multiple of 1-KByte, the padding data should not
260 // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
261 // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
262 // find the next possible microcode patch header.
264 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
268 // Get the next patch.
270 if (MicrocodeEntryPoint
->DataSize
== 0) {
273 TotalSize
= MicrocodeEntryPoint
->TotalSize
;
276 if (CorrectMicrocode
) {
277 LatestRevision
= MicrocodeEntryPoint
->UpdateRevision
;
278 MicrocodeData
= (VOID
*) ((UINTN
) MicrocodeEntryPoint
+ sizeof (CPU_MICROCODE_HEADER
));
281 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
282 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
285 if (LatestRevision
!= 0) {
287 // Save the detected microcode patch entry address (including the
288 // microcode patch header) for each processor.
289 // It will be used when building the microcode patch cache HOB.
291 CpuMpData
->CpuData
[ProcessorNumber
].MicrocodeEntryAddr
=
292 (UINTN
) MicrocodeData
- sizeof (CPU_MICROCODE_HEADER
);
295 if (LatestRevision
> CurrentRevision
) {
297 // BIOS only authenticate updates that contain a numerically larger revision
298 // than the currently loaded revision, where Current Signature < New Update
299 // Revision. A processor with no loaded update is considered to have a
300 // revision equal to zero.
302 ASSERT (MicrocodeData
!= NULL
);
304 MSR_IA32_BIOS_UPDT_TRIG
,
305 (UINT64
) (UINTN
) MicrocodeData
308 // Get and check new microcode signature
310 CurrentRevision
= GetCurrentMicrocodeSignature ();
311 if (CurrentRevision
!= LatestRevision
) {
312 AcquireSpinLock(&CpuMpData
->MpLock
);
313 DEBUG ((EFI_D_ERROR
, "Updated microcode signature [0x%08x] does not match \
314 loaded microcode signature [0x%08x]\n", CurrentRevision
, LatestRevision
));
315 ReleaseSpinLock(&CpuMpData
->MpLock
);
321 Determine if a microcode patch matchs the specific processor signature and flag.
323 @param[in] CpuMpData The pointer to CPU MP Data structure.
324 @param[in] ProcessorSignature The processor signature field value
325 supported by a microcode patch.
326 @param[in] ProcessorFlags The prcessor flags field value supported by
329 @retval TRUE The specified microcode patch will be loaded.
330 @retval FALSE The specified microcode patch will not be loaded.
333 IsProcessorMatchedMicrocodePatch (
334 IN CPU_MP_DATA
*CpuMpData
,
335 IN UINT32 ProcessorSignature
,
336 IN UINT32 ProcessorFlags
340 CPU_AP_DATA
*CpuData
;
342 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
343 CpuData
= &CpuMpData
->CpuData
[Index
];
344 if ((ProcessorSignature
== CpuData
->ProcessorSignature
) &&
345 (ProcessorFlags
& (1 << CpuData
->PlatformId
)) != 0) {
354 Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
355 patch header with the CPUID and PlatformID of the processors within
356 system to decide if it will be copied into memory.
358 @param[in] CpuMpData The pointer to CPU MP Data structure.
359 @param[in] MicrocodeEntryPoint The pointer to the microcode patch header.
361 @retval TRUE The specified microcode patch need to be loaded.
362 @retval FALSE The specified microcode patch dosen't need to be loaded.
365 IsMicrocodePatchNeedLoad (
366 IN CPU_MP_DATA
*CpuMpData
,
367 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
373 CPU_MICROCODE_EXTENDED_TABLE_HEADER
*ExtendedTableHeader
;
374 UINT32 ExtendedTableCount
;
375 CPU_MICROCODE_EXTENDED_TABLE
*ExtendedTable
;
379 // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.
381 NeedLoad
= IsProcessorMatchedMicrocodePatch (
383 MicrocodeEntryPoint
->ProcessorSignature
.Uint32
,
384 MicrocodeEntryPoint
->ProcessorFlags
388 // If the Extended Signature Table exists, check if the processor is in the
391 DataSize
= MicrocodeEntryPoint
->DataSize
;
392 TotalSize
= (DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
393 if ((!NeedLoad
) && (DataSize
!= 0) &&
394 (TotalSize
- DataSize
> sizeof (CPU_MICROCODE_HEADER
) +
395 sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER
))) {
396 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
397 + DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
398 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
399 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
401 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
403 // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
404 // Signature Table entry with the CPUID and PlatformID of the processors
405 // within system to decide if it will be copied into memory
407 NeedLoad
= IsProcessorMatchedMicrocodePatch (
409 ExtendedTable
->ProcessorSignature
.Uint32
,
410 ExtendedTable
->ProcessorFlag
424 Actual worker function that shadows the required microcode patches into memory.
426 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
427 @param[in] Patches The pointer to an array of information on
428 the microcode patches that will be loaded
430 @param[in] PatchCount The number of microcode patches that will
431 be loaded into memory.
432 @param[in] TotalLoadSize The total size of all the microcode patches
436 ShadowMicrocodePatchWorker (
437 IN OUT CPU_MP_DATA
*CpuMpData
,
438 IN MICROCODE_PATCH_INFO
*Patches
,
440 IN UINTN TotalLoadSize
444 VOID
*MicrocodePatchInRam
;
447 ASSERT ((Patches
!= NULL
) && (PatchCount
!= 0));
449 MicrocodePatchInRam
= AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize
));
450 if (MicrocodePatchInRam
== NULL
) {
455 // Load all the required microcode patches into memory
457 for (Walker
= MicrocodePatchInRam
, Index
= 0; Index
< PatchCount
; Index
++) {
460 (VOID
*) Patches
[Index
].Address
,
463 Walker
+= Patches
[Index
].Size
;
467 // Update the microcode patch related fields in CpuMpData
469 CpuMpData
->MicrocodePatchAddress
= (UINTN
) MicrocodePatchInRam
;
470 CpuMpData
->MicrocodePatchRegionSize
= TotalLoadSize
;
474 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
475 __FUNCTION__
, CpuMpData
->MicrocodePatchAddress
, CpuMpData
->MicrocodePatchRegionSize
482 Shadow the required microcode patches data into memory according to PCD
483 PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.
485 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
488 ShadowMicrocodePatchByPcd (
489 IN OUT CPU_MP_DATA
*CpuMpData
492 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
496 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
497 UINTN MaxPatchNumber
;
502 // Initialize the microcode patch related fields in CpuMpData as the values
503 // specified by the PCD pair. If the microcode patches are loaded into memory,
504 // these fields will be updated.
506 CpuMpData
->MicrocodePatchAddress
= PcdGet64 (PcdCpuMicrocodePatchAddress
);
507 CpuMpData
->MicrocodePatchRegionSize
= PcdGet64 (PcdCpuMicrocodePatchRegionSize
);
509 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
510 MicrocodeEnd
= (UINTN
) MicrocodeEntryPoint
+
511 (UINTN
) CpuMpData
->MicrocodePatchRegionSize
;
512 if ((MicrocodeEntryPoint
== NULL
) || ((UINTN
) MicrocodeEntryPoint
== MicrocodeEnd
)) {
514 // There is no microcode patches
520 MaxPatchNumber
= DEFAULT_MAX_MICROCODE_PATCH_NUM
;
522 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
523 if (PatchInfoBuffer
== NULL
) {
528 // Process the header of each microcode patch within the region.
529 // The purpose is to decide which microcode patch(es) will be loaded into memory.
532 if (MicrocodeEntryPoint
->HeaderVersion
!= 0x1) {
534 // Padding data between the microcode patches, skip 1KB to check next entry.
536 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
540 DataSize
= MicrocodeEntryPoint
->DataSize
;
541 TotalSize
= (DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
542 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
543 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
544 (DataSize
& 0x3) != 0 ||
545 (TotalSize
& (SIZE_1KB
- 1)) != 0 ||
549 // Not a valid microcode header, skip 1KB to check next entry.
551 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
555 if (IsMicrocodePatchNeedLoad (CpuMpData
, MicrocodeEntryPoint
)) {
557 if (PatchCount
> MaxPatchNumber
) {
559 // Current 'PatchInfoBuffer' cannot hold the information, double the size
560 // and allocate a new buffer.
562 if (MaxPatchNumber
> MAX_UINTN
/ 2 / sizeof (MICROCODE_PATCH_INFO
)) {
564 // Overflow check for MaxPatchNumber
569 PatchInfoBuffer
= ReallocatePool (
570 MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
571 2 * MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
574 if (PatchInfoBuffer
== NULL
) {
577 MaxPatchNumber
= MaxPatchNumber
* 2;
581 // Store the information of this microcode patch
583 PatchInfoBuffer
[PatchCount
- 1].Address
= (UINTN
) MicrocodeEntryPoint
;
584 PatchInfoBuffer
[PatchCount
- 1].Size
= TotalSize
;
585 TotalLoadSize
+= TotalSize
;
589 // Process the next microcode patch
591 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
592 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
594 if (PatchCount
!= 0) {
597 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
598 __FUNCTION__
, PatchCount
, TotalLoadSize
601 ShadowMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
605 if (PatchInfoBuffer
!= NULL
) {
606 FreePool (PatchInfoBuffer
);
612 Shadow the required microcode patches data into memory according to FIT microcode entry.
614 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
616 @return EFI_SUCCESS Microcode patch is shadowed into memory.
617 @return EFI_UNSUPPORTED FIT based microcode shadowing is not supported.
618 @return EFI_OUT_OF_RESOURCES No enough memory resource.
619 @return EFI_NOT_FOUND There is something wrong in FIT microcode entry.
623 ShadowMicrocodePatchByFit (
624 IN OUT CPU_MP_DATA
*CpuMpData
628 FIRMWARE_INTERFACE_TABLE_ENTRY
*FitEntry
;
631 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
632 UINTN MaxPatchNumber
;
633 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
638 if (!FeaturePcdGet (PcdCpuShadowMicrocodeByFit
)) {
639 return EFI_UNSUPPORTED
;
642 FitPointer
= *(UINT64
*) (UINTN
) FIT_POINTER_ADDRESS
;
643 if ((FitPointer
== 0) ||
644 (FitPointer
== 0xFFFFFFFFFFFFFFFF) ||
645 (FitPointer
== 0xEEEEEEEEEEEEEEEE)) {
650 return EFI_NOT_FOUND
;
652 FitEntry
= (FIRMWARE_INTERFACE_TABLE_ENTRY
*) (UINTN
) FitPointer
;
653 if ((FitEntry
[0].Type
!= FIT_TYPE_00_HEADER
) ||
654 (FitEntry
[0].Address
!= FIT_TYPE_00_SIGNATURE
)) {
656 // Invalid FIT table, treat it as no FIT table.
659 return EFI_NOT_FOUND
;
662 EntryNum
= *(UINT32
*)(&FitEntry
[0].Size
[0]) & 0xFFFFFF;
665 // Calculate microcode entry number
668 for (Index
= 0; Index
< EntryNum
; Index
++) {
669 if (FitEntry
[Index
].Type
== FIT_TYPE_01_MICROCODE
) {
673 if (MaxPatchNumber
== 0) {
674 return EFI_NOT_FOUND
;
677 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
678 if (PatchInfoBuffer
== NULL
) {
679 return EFI_OUT_OF_RESOURCES
;
683 // Fill up microcode patch info buffer according to FIT table.
687 for (Index
= 0; Index
< EntryNum
; Index
++) {
688 if (FitEntry
[Index
].Type
== FIT_TYPE_01_MICROCODE
) {
689 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) FitEntry
[Index
].Address
;
690 TotalSize
= (MicrocodeEntryPoint
->DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
691 if (IsMicrocodePatchNeedLoad (CpuMpData
, MicrocodeEntryPoint
)) {
692 PatchInfoBuffer
[PatchCount
].Address
= (UINTN
) MicrocodeEntryPoint
;
693 PatchInfoBuffer
[PatchCount
].Size
= TotalSize
;
694 TotalLoadSize
+= TotalSize
;
700 if (PatchCount
!= 0) {
703 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
704 __FUNCTION__
, PatchCount
, TotalLoadSize
707 ShadowMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
710 FreePool (PatchInfoBuffer
);
715 Shadow the required microcode patches data into memory.
717 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
720 ShadowMicrocodeUpdatePatch (
721 IN OUT CPU_MP_DATA
*CpuMpData
726 Status
= ShadowMicrocodePatchByFit (CpuMpData
);
727 if (EFI_ERROR (Status
)) {
728 ShadowMicrocodePatchByPcd (CpuMpData
);