2 Implementation of loading microcode on processors.
4 Copyright (c) 2015 - 2019, 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
;
88 UINT32 CurrentRevision
;
89 UINT32 LatestRevision
;
92 UINT32 InCompleteCheckSum32
;
93 BOOLEAN CorrectMicrocode
;
95 MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr
;
96 UINT32 ProcessorFlags
;
101 // set ProcessorFlags to suppress incorrect compiler/analyzer warnings
105 if (CpuMpData
->MicrocodePatchRegionSize
== 0) {
107 // There is no microcode patches
112 CurrentRevision
= GetCurrentMicrocodeSignature ();
113 IsBspCallIn
= (ProcessorNumber
== (UINTN
)CpuMpData
->BspNumber
) ? TRUE
: FALSE
;
114 if (CurrentRevision
!= 0 && !IsBspCallIn
) {
116 // Skip loading microcode if it has been loaded successfully
121 GetProcessorLocationByApicId (GetInitialApicId (), NULL
, NULL
, &ThreadId
);
124 // Skip loading microcode if it is not the first thread in one core.
129 ExtendedTableLength
= 0;
131 // Here data of CPUID leafs have not been collected into context buffer, so
132 // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
134 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, NULL
, NULL
);
137 // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
139 PlatformIdMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_PLATFORM_ID
);
140 PlatformId
= (UINT8
) PlatformIdMsr
.Bits
.PlatformId
;
143 // Check whether AP has same processor with BSP.
144 // If yes, direct use microcode info saved by BSP.
147 if ((CpuMpData
->ProcessorSignature
== Eax
.Uint32
) &&
148 (CpuMpData
->ProcessorFlags
& (1 << PlatformId
)) != 0) {
149 MicrocodeData
= (VOID
*)(UINTN
) CpuMpData
->MicrocodeDataAddress
;
150 LatestRevision
= CpuMpData
->MicrocodeRevision
;
156 MicrocodeData
= NULL
;
157 MicrocodeEnd
= (UINTN
) (CpuMpData
->MicrocodePatchAddress
+ CpuMpData
->MicrocodePatchRegionSize
);
158 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
162 // Check if the microcode is for the Cpu and the version is newer
163 // and the update can be processed on the platform
165 CorrectMicrocode
= FALSE
;
167 if (MicrocodeEntryPoint
->DataSize
== 0) {
168 TotalSize
= sizeof (CPU_MICROCODE_HEADER
) + 2000;
170 TotalSize
= sizeof (CPU_MICROCODE_HEADER
) + MicrocodeEntryPoint
->DataSize
;
174 /// 0x0 MicrocodeBegin MicrocodeEntry MicrocodeEnd 0xffffffff
175 /// |--------------|---------------|---------------|---------------|
177 /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEntry).
178 /// And it should be aligned with 4 bytes.
179 /// If the TotalSize is invalid, skip 1KB to check next entry.
181 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
182 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
183 (TotalSize
& 0x3) != 0
185 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
190 // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
192 InCompleteCheckSum32
= CalculateSum32 (
193 (UINT32
*) MicrocodeEntryPoint
,
196 InCompleteCheckSum32
-= MicrocodeEntryPoint
->ProcessorSignature
.Uint32
;
197 InCompleteCheckSum32
-= MicrocodeEntryPoint
->ProcessorFlags
;
198 InCompleteCheckSum32
-= MicrocodeEntryPoint
->Checksum
;
200 if (MicrocodeEntryPoint
->HeaderVersion
== 0x1) {
202 // It is the microcode header. It is not the padding data between microcode patches
203 // because the padding data should not include 0x00000001 and it should be the repeated
204 // byte format (like 0xXYXYXYXY....).
206 if (MicrocodeEntryPoint
->ProcessorSignature
.Uint32
== Eax
.Uint32
&&
207 MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
&&
208 (MicrocodeEntryPoint
->ProcessorFlags
& (1 << PlatformId
))
211 // Calculate CheckSum Part1.
213 CheckSum32
= InCompleteCheckSum32
;
214 CheckSum32
+= MicrocodeEntryPoint
->ProcessorSignature
.Uint32
;
215 CheckSum32
+= MicrocodeEntryPoint
->ProcessorFlags
;
216 CheckSum32
+= MicrocodeEntryPoint
->Checksum
;
217 if (CheckSum32
== 0) {
218 CorrectMicrocode
= TRUE
;
219 ProcessorFlags
= MicrocodeEntryPoint
->ProcessorFlags
;
221 } else if ((MicrocodeEntryPoint
->DataSize
!= 0) &&
222 (MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
)) {
223 ExtendedTableLength
= MicrocodeEntryPoint
->TotalSize
- (MicrocodeEntryPoint
->DataSize
+
224 sizeof (CPU_MICROCODE_HEADER
));
225 if (ExtendedTableLength
!= 0) {
227 // Extended Table exist, check if the CPU in support list
229 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
230 + MicrocodeEntryPoint
->DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
232 // Calculate Extended Checksum
234 if ((ExtendedTableLength
% 4) == 0) {
236 // Calculate CheckSum Part2.
238 CheckSum32
= CalculateSum32 ((UINT32
*) ExtendedTableHeader
, ExtendedTableLength
);
239 if (CheckSum32
== 0) {
243 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
244 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
245 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
247 // Calculate CheckSum Part3.
249 CheckSum32
= InCompleteCheckSum32
;
250 CheckSum32
+= ExtendedTable
->ProcessorSignature
.Uint32
;
251 CheckSum32
+= ExtendedTable
->ProcessorFlag
;
252 CheckSum32
+= ExtendedTable
->Checksum
;
253 if (CheckSum32
== 0) {
257 if ((ExtendedTable
->ProcessorSignature
.Uint32
== Eax
.Uint32
) &&
258 (ExtendedTable
->ProcessorFlag
& (1 << PlatformId
)) ) {
262 CorrectMicrocode
= TRUE
;
263 ProcessorFlags
= ExtendedTable
->ProcessorFlag
;
275 // It is the padding data between the microcode patches for microcode patches alignment.
276 // Because the microcode patch is the multiple of 1-KByte, the padding data should not
277 // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
278 // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
279 // find the next possible microcode patch header.
281 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
285 // Get the next patch.
287 if (MicrocodeEntryPoint
->DataSize
== 0) {
290 TotalSize
= MicrocodeEntryPoint
->TotalSize
;
293 if (CorrectMicrocode
) {
294 LatestRevision
= MicrocodeEntryPoint
->UpdateRevision
;
295 MicrocodeData
= (VOID
*) ((UINTN
) MicrocodeEntryPoint
+ sizeof (CPU_MICROCODE_HEADER
));
298 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
299 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
302 if (LatestRevision
!= 0) {
304 // Save the detected microcode patch entry address (including the
305 // microcode patch header) for each processor.
306 // It will be used when building the microcode patch cache HOB.
308 CpuMpData
->CpuData
[ProcessorNumber
].MicrocodeEntryAddr
=
309 (UINTN
) MicrocodeData
- sizeof (CPU_MICROCODE_HEADER
);
312 if (LatestRevision
> CurrentRevision
) {
314 // BIOS only authenticate updates that contain a numerically larger revision
315 // than the currently loaded revision, where Current Signature < New Update
316 // Revision. A processor with no loaded update is considered to have a
317 // revision equal to zero.
319 ASSERT (MicrocodeData
!= NULL
);
321 MSR_IA32_BIOS_UPDT_TRIG
,
322 (UINT64
) (UINTN
) MicrocodeData
325 // Get and check new microcode signature
327 CurrentRevision
= GetCurrentMicrocodeSignature ();
328 if (CurrentRevision
!= LatestRevision
) {
329 AcquireSpinLock(&CpuMpData
->MpLock
);
330 DEBUG ((EFI_D_ERROR
, "Updated microcode signature [0x%08x] does not match \
331 loaded microcode signature [0x%08x]\n", CurrentRevision
, LatestRevision
));
332 ReleaseSpinLock(&CpuMpData
->MpLock
);
336 if (IsBspCallIn
&& (LatestRevision
!= 0)) {
338 // Save BSP processor info and microcode info for later AP use.
340 CpuMpData
->ProcessorSignature
= Eax
.Uint32
;
341 CpuMpData
->ProcessorFlags
= ProcessorFlags
;
342 CpuMpData
->MicrocodeDataAddress
= (UINTN
) MicrocodeData
;
343 CpuMpData
->MicrocodeRevision
= LatestRevision
;
344 DEBUG ((DEBUG_INFO
, "BSP Microcode:: signature [0x%08x], ProcessorFlags [0x%08x], \
345 MicroData [0x%08x], Revision [0x%08x]\n", Eax
.Uint32
, ProcessorFlags
, (UINTN
) MicrocodeData
, LatestRevision
));
350 Determine if a microcode patch will be loaded into memory.
352 @param[in] CpuMpData The pointer to CPU MP Data structure.
353 @param[in] ProcessorSignature The processor signature field value
354 supported by a microcode patch.
355 @param[in] ProcessorFlags The prcessor flags field value supported by
358 @retval TRUE The specified microcode patch will be loaded.
359 @retval FALSE The specified microcode patch will not be loaded.
362 IsMicrocodePatchNeedLoad (
363 IN CPU_MP_DATA
*CpuMpData
,
364 IN UINT32 ProcessorSignature
,
365 IN UINT32 ProcessorFlags
369 CPU_AP_DATA
*CpuData
;
371 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
372 CpuData
= &CpuMpData
->CpuData
[Index
];
373 if ((ProcessorSignature
== CpuData
->ProcessorSignature
) &&
374 (ProcessorFlags
& (1 << CpuData
->PlatformId
)) != 0) {
383 Actual worker function that loads the required microcode patches into memory.
385 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
386 @param[in] Patches The pointer to an array of information on
387 the microcode patches that will be loaded
389 @param[in] PatchCount The number of microcode patches that will
390 be loaded into memory.
391 @param[in] TotalLoadSize The total size of all the microcode patches
395 LoadMicrocodePatchWorker (
396 IN OUT CPU_MP_DATA
*CpuMpData
,
397 IN MICROCODE_PATCH_INFO
*Patches
,
399 IN UINTN TotalLoadSize
403 VOID
*MicrocodePatchInRam
;
406 ASSERT ((Patches
!= NULL
) && (PatchCount
!= 0));
408 MicrocodePatchInRam
= AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize
));
409 if (MicrocodePatchInRam
== NULL
) {
414 // Load all the required microcode patches into memory
416 for (Walker
= MicrocodePatchInRam
, Index
= 0; Index
< PatchCount
; Index
++) {
419 (VOID
*) Patches
[Index
].Address
,
424 // Zero-fill the padding area
425 // Please note that AlignedSize will be no less than Size
428 Walker
+ Patches
[Index
].Size
,
429 Patches
[Index
].AlignedSize
- Patches
[Index
].Size
432 Walker
+= Patches
[Index
].AlignedSize
;
436 // Update the microcode patch related fields in CpuMpData
438 CpuMpData
->MicrocodePatchAddress
= (UINTN
) MicrocodePatchInRam
;
439 CpuMpData
->MicrocodePatchRegionSize
= TotalLoadSize
;
443 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
444 __FUNCTION__
, CpuMpData
->MicrocodePatchAddress
, CpuMpData
->MicrocodePatchRegionSize
451 Load the required microcode patches data into memory.
453 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
457 IN OUT CPU_MP_DATA
*CpuMpData
460 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
464 CPU_MICROCODE_EXTENDED_TABLE_HEADER
*ExtendedTableHeader
;
465 UINT32 ExtendedTableCount
;
466 CPU_MICROCODE_EXTENDED_TABLE
*ExtendedTable
;
467 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
468 UINTN MaxPatchNumber
;
475 // Initialize the microcode patch related fields in CpuMpData as the values
476 // specified by the PCD pair. If the microcode patches are loaded into memory,
477 // these fields will be updated.
479 CpuMpData
->MicrocodePatchAddress
= PcdGet64 (PcdCpuMicrocodePatchAddress
);
480 CpuMpData
->MicrocodePatchRegionSize
= PcdGet64 (PcdCpuMicrocodePatchRegionSize
);
482 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
483 MicrocodeEnd
= (UINTN
) MicrocodeEntryPoint
+
484 (UINTN
) CpuMpData
->MicrocodePatchRegionSize
;
485 if ((MicrocodeEntryPoint
== NULL
) || ((UINTN
) MicrocodeEntryPoint
== MicrocodeEnd
)) {
487 // There is no microcode patches
493 MaxPatchNumber
= DEFAULT_MAX_MICROCODE_PATCH_NUM
;
495 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
496 if (PatchInfoBuffer
== NULL
) {
501 // Process the header of each microcode patch within the region.
502 // The purpose is to decide which microcode patch(es) will be loaded into memory.
505 if (MicrocodeEntryPoint
->HeaderVersion
!= 0x1) {
507 // Padding data between the microcode patches, skip 1KB to check next entry.
509 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
513 DataSize
= MicrocodeEntryPoint
->DataSize
;
514 TotalSize
= (DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
515 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
516 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
517 (DataSize
& 0x3) != 0 ||
518 (TotalSize
& (SIZE_1KB
- 1)) != 0 ||
522 // Not a valid microcode header, skip 1KB to check next entry.
524 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
529 // Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
530 // patch header with the CPUID and PlatformID of the processors within
531 // system to decide if it will be copied into memory
533 NeedLoad
= IsMicrocodePatchNeedLoad (
535 MicrocodeEntryPoint
->ProcessorSignature
.Uint32
,
536 MicrocodeEntryPoint
->ProcessorFlags
540 // If the Extended Signature Table exists, check if the processor is in the
543 if ((!NeedLoad
) && (DataSize
!= 0) &&
544 (TotalSize
- DataSize
> sizeof (CPU_MICROCODE_HEADER
) +
545 sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER
))) {
546 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
547 + DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
548 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
549 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
551 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
553 // Avoid access content beyond MicrocodeEnd
555 if ((UINTN
) ExtendedTable
> MicrocodeEnd
- sizeof (CPU_MICROCODE_EXTENDED_TABLE
)) {
560 // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
561 // Signature Table entry with the CPUID and PlatformID of the processors
562 // within system to decide if it will be copied into memory
564 NeedLoad
= IsMicrocodePatchNeedLoad (
566 ExtendedTable
->ProcessorSignature
.Uint32
,
567 ExtendedTable
->ProcessorFlag
578 if (PatchCount
> MaxPatchNumber
) {
580 // Current 'PatchInfoBuffer' cannot hold the information, double the size
581 // and allocate a new buffer.
583 if (MaxPatchNumber
> MAX_UINTN
/ 2 / sizeof (MICROCODE_PATCH_INFO
)) {
585 // Overflow check for MaxPatchNumber
590 PatchInfoBuffer
= ReallocatePool (
591 MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
592 2 * MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
595 if (PatchInfoBuffer
== NULL
) {
598 MaxPatchNumber
= MaxPatchNumber
* 2;
602 // Store the information of this microcode patch
604 if (TotalSize
> ALIGN_VALUE (TotalSize
, SIZE_1KB
) ||
605 ALIGN_VALUE (TotalSize
, SIZE_1KB
) > MAX_UINTN
- TotalLoadSize
) {
608 PatchInfoBuffer
[PatchCount
- 1].Address
= (UINTN
) MicrocodeEntryPoint
;
609 PatchInfoBuffer
[PatchCount
- 1].Size
= TotalSize
;
610 PatchInfoBuffer
[PatchCount
- 1].AlignedSize
= ALIGN_VALUE (TotalSize
, SIZE_1KB
);
611 TotalLoadSize
+= PatchInfoBuffer
[PatchCount
- 1].AlignedSize
;
615 // Process the next microcode patch
617 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
618 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
620 if (PatchCount
!= 0) {
623 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
624 __FUNCTION__
, PatchCount
, TotalLoadSize
627 LoadMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
631 if (PatchInfoBuffer
!= NULL
) {
632 FreePool (PatchInfoBuffer
);