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] IsBspCallIn Indicate whether the caller is BSP or not.
73 IN CPU_MP_DATA
*CpuMpData
,
74 IN BOOLEAN IsBspCallIn
77 UINT32 ExtendedTableLength
;
78 UINT32 ExtendedTableCount
;
79 CPU_MICROCODE_EXTENDED_TABLE
*ExtendedTable
;
80 CPU_MICROCODE_EXTENDED_TABLE_HEADER
*ExtendedTableHeader
;
81 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
85 CPUID_VERSION_INFO_EAX Eax
;
86 UINT32 CurrentRevision
;
87 UINT32 LatestRevision
;
90 UINT32 InCompleteCheckSum32
;
91 BOOLEAN CorrectMicrocode
;
93 MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr
;
94 UINT32 ProcessorFlags
;
98 // set ProcessorFlags to suppress incorrect compiler/analyzer warnings
102 if (CpuMpData
->MicrocodePatchRegionSize
== 0) {
104 // There is no microcode patches
109 CurrentRevision
= GetCurrentMicrocodeSignature ();
110 if (CurrentRevision
!= 0 && !IsBspCallIn
) {
112 // Skip loading microcode if it has been loaded successfully
117 GetProcessorLocationByApicId (GetInitialApicId (), NULL
, NULL
, &ThreadId
);
120 // Skip loading microcode if it is not the first thread in one core.
125 ExtendedTableLength
= 0;
127 // Here data of CPUID leafs have not been collected into context buffer, so
128 // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
130 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, NULL
, NULL
);
133 // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
135 PlatformIdMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_PLATFORM_ID
);
136 PlatformId
= (UINT8
) PlatformIdMsr
.Bits
.PlatformId
;
139 // Check whether AP has same processor with BSP.
140 // If yes, direct use microcode info saved by BSP.
143 if ((CpuMpData
->ProcessorSignature
== Eax
.Uint32
) &&
144 (CpuMpData
->ProcessorFlags
& (1 << PlatformId
)) != 0) {
145 MicrocodeData
= (VOID
*)(UINTN
) CpuMpData
->MicrocodeDataAddress
;
146 LatestRevision
= CpuMpData
->MicrocodeRevision
;
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
;
215 ProcessorFlags
= MicrocodeEntryPoint
->ProcessorFlags
;
217 } else if ((MicrocodeEntryPoint
->DataSize
!= 0) &&
218 (MicrocodeEntryPoint
->UpdateRevision
> LatestRevision
)) {
219 ExtendedTableLength
= MicrocodeEntryPoint
->TotalSize
- (MicrocodeEntryPoint
->DataSize
+
220 sizeof (CPU_MICROCODE_HEADER
));
221 if (ExtendedTableLength
!= 0) {
223 // Extended Table exist, check if the CPU in support list
225 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
226 + MicrocodeEntryPoint
->DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
228 // Calculate Extended Checksum
230 if ((ExtendedTableLength
% 4) == 0) {
232 // Calculate CheckSum Part2.
234 CheckSum32
= CalculateSum32 ((UINT32
*) ExtendedTableHeader
, ExtendedTableLength
);
235 if (CheckSum32
== 0) {
239 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
240 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
241 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
243 // Calculate CheckSum Part3.
245 CheckSum32
= InCompleteCheckSum32
;
246 CheckSum32
+= ExtendedTable
->ProcessorSignature
.Uint32
;
247 CheckSum32
+= ExtendedTable
->ProcessorFlag
;
248 CheckSum32
+= ExtendedTable
->Checksum
;
249 if (CheckSum32
== 0) {
253 if ((ExtendedTable
->ProcessorSignature
.Uint32
== Eax
.Uint32
) &&
254 (ExtendedTable
->ProcessorFlag
& (1 << PlatformId
)) ) {
258 CorrectMicrocode
= TRUE
;
259 ProcessorFlags
= ExtendedTable
->ProcessorFlag
;
271 // It is the padding data between the microcode patches for microcode patches alignment.
272 // Because the microcode patch is the multiple of 1-KByte, the padding data should not
273 // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
274 // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
275 // find the next possible microcode patch header.
277 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
281 // Get the next patch.
283 if (MicrocodeEntryPoint
->DataSize
== 0) {
286 TotalSize
= MicrocodeEntryPoint
->TotalSize
;
289 if (CorrectMicrocode
) {
290 LatestRevision
= MicrocodeEntryPoint
->UpdateRevision
;
291 MicrocodeData
= (VOID
*) ((UINTN
) MicrocodeEntryPoint
+ sizeof (CPU_MICROCODE_HEADER
));
294 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
295 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
298 if (LatestRevision
> CurrentRevision
) {
300 // BIOS only authenticate updates that contain a numerically larger revision
301 // than the currently loaded revision, where Current Signature < New Update
302 // Revision. A processor with no loaded update is considered to have a
303 // revision equal to zero.
305 ASSERT (MicrocodeData
!= NULL
);
307 MSR_IA32_BIOS_UPDT_TRIG
,
308 (UINT64
) (UINTN
) MicrocodeData
311 // Get and check new microcode signature
313 CurrentRevision
= GetCurrentMicrocodeSignature ();
314 if (CurrentRevision
!= LatestRevision
) {
315 AcquireSpinLock(&CpuMpData
->MpLock
);
316 DEBUG ((EFI_D_ERROR
, "Updated microcode signature [0x%08x] does not match \
317 loaded microcode signature [0x%08x]\n", CurrentRevision
, LatestRevision
));
318 ReleaseSpinLock(&CpuMpData
->MpLock
);
322 if (IsBspCallIn
&& (LatestRevision
!= 0)) {
324 // Save BSP processor info and microcode info for later AP use.
326 CpuMpData
->ProcessorSignature
= Eax
.Uint32
;
327 CpuMpData
->ProcessorFlags
= ProcessorFlags
;
328 CpuMpData
->MicrocodeDataAddress
= (UINTN
) MicrocodeData
;
329 CpuMpData
->MicrocodeRevision
= LatestRevision
;
330 DEBUG ((DEBUG_INFO
, "BSP Microcode:: signature [0x%08x], ProcessorFlags [0x%08x], \
331 MicroData [0x%08x], Revision [0x%08x]\n", Eax
.Uint32
, ProcessorFlags
, (UINTN
) MicrocodeData
, LatestRevision
));
336 Determine if a microcode patch will be loaded into memory.
338 @param[in] CpuMpData The pointer to CPU MP Data structure.
339 @param[in] ProcessorSignature The processor signature field value
340 supported by a microcode patch.
341 @param[in] ProcessorFlags The prcessor flags field value supported by
344 @retval TRUE The specified microcode patch will be loaded.
345 @retval FALSE The specified microcode patch will not be loaded.
348 IsMicrocodePatchNeedLoad (
349 IN CPU_MP_DATA
*CpuMpData
,
350 IN UINT32 ProcessorSignature
,
351 IN UINT32 ProcessorFlags
355 CPU_AP_DATA
*CpuData
;
357 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
358 CpuData
= &CpuMpData
->CpuData
[Index
];
359 if ((ProcessorSignature
== CpuData
->ProcessorSignature
) &&
360 (ProcessorFlags
& (1 << CpuData
->PlatformId
)) != 0) {
369 Actual worker function that loads the required microcode patches into memory.
371 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
372 @param[in] Patches The pointer to an array of information on
373 the microcode patches that will be loaded
375 @param[in] PatchCount The number of microcode patches that will
376 be loaded into memory.
377 @param[in] TotalLoadSize The total size of all the microcode patches
381 LoadMicrocodePatchWorker (
382 IN OUT CPU_MP_DATA
*CpuMpData
,
383 IN MICROCODE_PATCH_INFO
*Patches
,
385 IN UINTN TotalLoadSize
389 VOID
*MicrocodePatchInRam
;
392 ASSERT ((Patches
!= NULL
) && (PatchCount
!= 0));
394 MicrocodePatchInRam
= AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize
));
395 if (MicrocodePatchInRam
== NULL
) {
400 // Load all the required microcode patches into memory
402 for (Walker
= MicrocodePatchInRam
, Index
= 0; Index
< PatchCount
; Index
++) {
405 (VOID
*) Patches
[Index
].Address
,
410 // Zero-fill the padding area
411 // Please note that AlignedSize will be no less than Size
414 Walker
+ Patches
[Index
].Size
,
415 Patches
[Index
].AlignedSize
- Patches
[Index
].Size
418 Walker
+= Patches
[Index
].AlignedSize
;
422 // Update the microcode patch related fields in CpuMpData
424 CpuMpData
->MicrocodePatchAddress
= (UINTN
) MicrocodePatchInRam
;
425 CpuMpData
->MicrocodePatchRegionSize
= TotalLoadSize
;
429 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
430 __FUNCTION__
, CpuMpData
->MicrocodePatchAddress
, CpuMpData
->MicrocodePatchRegionSize
437 Load the required microcode patches data into memory.
439 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
443 IN OUT CPU_MP_DATA
*CpuMpData
446 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
450 CPU_MICROCODE_EXTENDED_TABLE_HEADER
*ExtendedTableHeader
;
451 UINT32 ExtendedTableCount
;
452 CPU_MICROCODE_EXTENDED_TABLE
*ExtendedTable
;
453 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
454 UINTN MaxPatchNumber
;
461 // Initialize the microcode patch related fields in CpuMpData as the values
462 // specified by the PCD pair. If the microcode patches are loaded into memory,
463 // these fields will be updated.
465 CpuMpData
->MicrocodePatchAddress
= PcdGet64 (PcdCpuMicrocodePatchAddress
);
466 CpuMpData
->MicrocodePatchRegionSize
= PcdGet64 (PcdCpuMicrocodePatchRegionSize
);
468 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (UINTN
) CpuMpData
->MicrocodePatchAddress
;
469 MicrocodeEnd
= (UINTN
) MicrocodeEntryPoint
+
470 (UINTN
) CpuMpData
->MicrocodePatchRegionSize
;
471 if ((MicrocodeEntryPoint
== NULL
) || ((UINTN
) MicrocodeEntryPoint
== MicrocodeEnd
)) {
473 // There is no microcode patches
479 MaxPatchNumber
= DEFAULT_MAX_MICROCODE_PATCH_NUM
;
481 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
482 if (PatchInfoBuffer
== NULL
) {
487 // Process the header of each microcode patch within the region.
488 // The purpose is to decide which microcode patch(es) will be loaded into memory.
491 if (MicrocodeEntryPoint
->HeaderVersion
!= 0x1) {
493 // Padding data between the microcode patches, skip 1KB to check next entry.
495 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
499 DataSize
= MicrocodeEntryPoint
->DataSize
;
500 TotalSize
= (DataSize
== 0) ? 2048 : MicrocodeEntryPoint
->TotalSize
;
501 if ( (UINTN
)MicrocodeEntryPoint
> (MAX_ADDRESS
- TotalSize
) ||
502 ((UINTN
)MicrocodeEntryPoint
+ TotalSize
) > MicrocodeEnd
||
503 (DataSize
& 0x3) != 0 ||
504 (TotalSize
& (SIZE_1KB
- 1)) != 0 ||
508 // Not a valid microcode header, skip 1KB to check next entry.
510 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + SIZE_1KB
);
515 // Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
516 // patch header with the CPUID and PlatformID of the processors within
517 // system to decide if it will be copied into memory
519 NeedLoad
= IsMicrocodePatchNeedLoad (
521 MicrocodeEntryPoint
->ProcessorSignature
.Uint32
,
522 MicrocodeEntryPoint
->ProcessorFlags
526 // If the Extended Signature Table exists, check if the processor is in the
529 if ((!NeedLoad
) && (DataSize
!= 0) &&
530 (TotalSize
- DataSize
> sizeof (CPU_MICROCODE_HEADER
) +
531 sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER
))) {
532 ExtendedTableHeader
= (CPU_MICROCODE_EXTENDED_TABLE_HEADER
*) ((UINT8
*) (MicrocodeEntryPoint
)
533 + DataSize
+ sizeof (CPU_MICROCODE_HEADER
));
534 ExtendedTableCount
= ExtendedTableHeader
->ExtendedSignatureCount
;
535 ExtendedTable
= (CPU_MICROCODE_EXTENDED_TABLE
*) (ExtendedTableHeader
+ 1);
537 for (Index
= 0; Index
< ExtendedTableCount
; Index
++) {
539 // Avoid access content beyond MicrocodeEnd
541 if ((UINTN
) ExtendedTable
> MicrocodeEnd
- sizeof (CPU_MICROCODE_EXTENDED_TABLE
)) {
546 // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
547 // Signature Table entry with the CPUID and PlatformID of the processors
548 // within system to decide if it will be copied into memory
550 NeedLoad
= IsMicrocodePatchNeedLoad (
552 ExtendedTable
->ProcessorSignature
.Uint32
,
553 ExtendedTable
->ProcessorFlag
564 if (PatchCount
> MaxPatchNumber
) {
566 // Current 'PatchInfoBuffer' cannot hold the information, double the size
567 // and allocate a new buffer.
569 if (MaxPatchNumber
> MAX_UINTN
/ 2 / sizeof (MICROCODE_PATCH_INFO
)) {
571 // Overflow check for MaxPatchNumber
576 PatchInfoBuffer
= ReallocatePool (
577 MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
578 2 * MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
581 if (PatchInfoBuffer
== NULL
) {
584 MaxPatchNumber
= MaxPatchNumber
* 2;
588 // Store the information of this microcode patch
590 if (TotalSize
> ALIGN_VALUE (TotalSize
, SIZE_1KB
) ||
591 ALIGN_VALUE (TotalSize
, SIZE_1KB
) > MAX_UINTN
- TotalLoadSize
) {
594 PatchInfoBuffer
[PatchCount
- 1].Address
= (UINTN
) MicrocodeEntryPoint
;
595 PatchInfoBuffer
[PatchCount
- 1].Size
= TotalSize
;
596 PatchInfoBuffer
[PatchCount
- 1].AlignedSize
= ALIGN_VALUE (TotalSize
, SIZE_1KB
);
597 TotalLoadSize
+= PatchInfoBuffer
[PatchCount
- 1].AlignedSize
;
601 // Process the next microcode patch
603 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) (((UINTN
) MicrocodeEntryPoint
) + TotalSize
);
604 } while (((UINTN
) MicrocodeEntryPoint
< MicrocodeEnd
));
606 if (PatchCount
!= 0) {
609 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
610 __FUNCTION__
, PatchCount
, TotalLoadSize
613 LoadMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
617 if (PatchInfoBuffer
!= NULL
) {
618 FreePool (PatchInfoBuffer
);