1 /** @file
2   Implementation of loading microcode on processors.
3 
4   Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "MpLib.h"
10 
11 /**
12   Get microcode update signature of currently loaded microcode update.
13 
14   @return  Microcode signature.
15 **/
16 UINT32
GetCurrentMicrocodeSignature(VOID)17 GetCurrentMicrocodeSignature (
18   VOID
19   )
20 {
21   MSR_IA32_BIOS_SIGN_ID_REGISTER   BiosSignIdMsr;
22 
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;
27 }
28 
29 /**
30   Detect whether specified processor can find matching microcode patch and load it.
31 
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      |                  |
41   |                   ...                  |                  |
42   +----------------------------------------+------------------+
43 
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.
47 
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
52   it as CheckSum Part3.
53 
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.
57 
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.
63 
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.
67 
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
71                                minus 1.
72 **/
73 VOID
MicrocodeDetect(IN CPU_MP_DATA * CpuMpData,IN UINTN ProcessorNumber)74 MicrocodeDetect (
75   IN CPU_MP_DATA             *CpuMpData,
76   IN UINTN                   ProcessorNumber
77   )
78 {
79   UINT32                                  ExtendedTableLength;
80   UINT32                                  ExtendedTableCount;
81   CPU_MICROCODE_EXTENDED_TABLE            *ExtendedTable;
82   CPU_MICROCODE_EXTENDED_TABLE_HEADER     *ExtendedTableHeader;
83   CPU_MICROCODE_HEADER                    *MicrocodeEntryPoint;
84   UINTN                                   MicrocodeEnd;
85   UINTN                                   Index;
86   UINT8                                   PlatformId;
87   CPUID_VERSION_INFO_EAX                  Eax;
88   CPU_AP_DATA                             *CpuData;
89   UINT32                                  CurrentRevision;
90   UINT32                                  LatestRevision;
91   UINTN                                   TotalSize;
92   UINT32                                  CheckSum32;
93   UINT32                                  InCompleteCheckSum32;
94   BOOLEAN                                 CorrectMicrocode;
95   VOID                                    *MicrocodeData;
96   MSR_IA32_PLATFORM_ID_REGISTER           PlatformIdMsr;
97   UINT32                                  ThreadId;
98   BOOLEAN                                 IsBspCallIn;
99 
100   if (CpuMpData->MicrocodePatchRegionSize == 0) {
101     //
102     // There is no microcode patches
103     //
104     return;
105   }
106 
107   CurrentRevision = GetCurrentMicrocodeSignature ();
108   IsBspCallIn     = (ProcessorNumber == (UINTN)CpuMpData->BspNumber) ? TRUE : FALSE;
109 
110   GetProcessorLocationByApicId (GetInitialApicId (), NULL, NULL, &ThreadId);
111   if (ThreadId != 0) {
112     //
113     // Skip loading microcode if it is not the first thread in one core.
114     //
115     return;
116   }
117 
118   ExtendedTableLength = 0;
119   //
120   // Here data of CPUID leafs have not been collected into context buffer, so
121   // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
122   //
123   AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
124 
125   //
126   // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
127   //
128   PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
129   PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;
130 
131 
132   //
133   // Check whether AP has same processor with BSP.
134   // If yes, direct use microcode info saved by BSP.
135   //
136   if (!IsBspCallIn) {
137     //
138     // Get the CPU data for BSP
139     //
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;
147       goto Done;
148     }
149   }
150 
151   LatestRevision = 0;
152   MicrocodeData  = NULL;
153   MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize);
154   MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;
155 
156   do {
157     //
158     // Check if the microcode is for the Cpu and the version is newer
159     // and the update can be processed on the platform
160     //
161     CorrectMicrocode = FALSE;
162 
163     if (MicrocodeEntryPoint->DataSize == 0) {
164       TotalSize = sizeof (CPU_MICROCODE_HEADER) + 2000;
165     } else {
166       TotalSize = sizeof (CPU_MICROCODE_HEADER) + MicrocodeEntryPoint->DataSize;
167     }
168 
169     ///
170     /// 0x0       MicrocodeBegin  MicrocodeEntry  MicrocodeEnd      0xffffffff
171     /// |--------------|---------------|---------------|---------------|
172     ///                                 valid TotalSize
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.
176     ///
177     if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||
178          ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||
179          (TotalSize & 0x3) != 0
180        ) {
181       MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
182       continue;
183     }
184 
185     //
186     // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
187     //
188     InCompleteCheckSum32 = CalculateSum32 (
189                              (UINT32 *) MicrocodeEntryPoint,
190                              TotalSize
191                              );
192     InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorSignature.Uint32;
193     InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags;
194     InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum;
195 
196     if (MicrocodeEntryPoint->HeaderVersion == 0x1) {
197       //
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....).
201       //
202       if (MicrocodeEntryPoint->ProcessorSignature.Uint32 == Eax.Uint32 &&
203           MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
204           (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
205           ) {
206         //
207         // Calculate CheckSum Part1.
208         //
209         CheckSum32 = InCompleteCheckSum32;
210         CheckSum32 += MicrocodeEntryPoint->ProcessorSignature.Uint32;
211         CheckSum32 += MicrocodeEntryPoint->ProcessorFlags;
212         CheckSum32 += MicrocodeEntryPoint->Checksum;
213         if (CheckSum32 == 0) {
214           CorrectMicrocode = TRUE;
215         }
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) {
221           //
222           // Extended Table exist, check if the CPU in support list
223           //
224           ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
225                                   + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));
226           //
227           // Calculate Extended Checksum
228           //
229           if ((ExtendedTableLength % 4) == 0) {
230             //
231             // Calculate CheckSum Part2.
232             //
233             CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength);
234             if (CheckSum32 == 0) {
235               //
236               // Checksum correct
237               //
238               ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
239               ExtendedTable      = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
240               for (Index = 0; Index < ExtendedTableCount; Index ++) {
241                 //
242                 // Calculate CheckSum Part3.
243                 //
244                 CheckSum32 = InCompleteCheckSum32;
245                 CheckSum32 += ExtendedTable->ProcessorSignature.Uint32;
246                 CheckSum32 += ExtendedTable->ProcessorFlag;
247                 CheckSum32 += ExtendedTable->Checksum;
248                 if (CheckSum32 == 0) {
249                   //
250                   // Verify Header
251                   //
252                   if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) &&
253                       (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {
254                     //
255                     // Find one
256                     //
257                     CorrectMicrocode = TRUE;
258                     break;
259                   }
260                 }
261                 ExtendedTable ++;
262               }
263             }
264           }
265         }
266       }
267     } else {
268       //
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.
274       //
275       MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
276       continue;
277     }
278     //
279     // Get the next patch.
280     //
281     if (MicrocodeEntryPoint->DataSize == 0) {
282       TotalSize = 2048;
283     } else {
284       TotalSize = MicrocodeEntryPoint->TotalSize;
285     }
286 
287     if (CorrectMicrocode) {
288       LatestRevision = MicrocodeEntryPoint->UpdateRevision;
289       MicrocodeData = (VOID *) ((UINTN) MicrocodeEntryPoint + sizeof (CPU_MICROCODE_HEADER));
290     }
291 
292     MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
293   } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
294 
295 Done:
296   if (LatestRevision != 0) {
297     //
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.
301     //
302     CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =
303       (UINTN) MicrocodeData -  sizeof (CPU_MICROCODE_HEADER);
304   }
305 
306   if (LatestRevision > CurrentRevision) {
307     //
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.
312     //
313     ASSERT (MicrocodeData != NULL);
314     AsmWriteMsr64 (
315         MSR_IA32_BIOS_UPDT_TRIG,
316         (UINT64) (UINTN) MicrocodeData
317         );
318     //
319     // Get and check new microcode signature
320     //
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);
327     }
328   }
329 }
330 
331 /**
332   Determine if a microcode patch matchs the specific processor signature and flag.
333 
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
338                                     a microcode patch.
339 
340   @retval TRUE     The specified microcode patch will be loaded.
341   @retval FALSE    The specified microcode patch will not be loaded.
342 **/
343 BOOLEAN
IsProcessorMatchedMicrocodePatch(IN CPU_MP_DATA * CpuMpData,IN UINT32 ProcessorSignature,IN UINT32 ProcessorFlags)344 IsProcessorMatchedMicrocodePatch (
345   IN CPU_MP_DATA                 *CpuMpData,
346   IN UINT32                      ProcessorSignature,
347   IN UINT32                      ProcessorFlags
348   )
349 {
350   UINTN          Index;
351   CPU_AP_DATA    *CpuData;
352 
353   for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
354     CpuData = &CpuMpData->CpuData[Index];
355     if ((ProcessorSignature == CpuData->ProcessorSignature) &&
356         (ProcessorFlags & (1 << CpuData->PlatformId)) != 0) {
357       return TRUE;
358     }
359   }
360 
361   return FALSE;
362 }
363 
364 /**
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.
368 
369   @param[in]  CpuMpData             The pointer to CPU MP Data structure.
370   @param[in]  MicrocodeEntryPoint   The pointer to the microcode patch header.
371 
372   @retval TRUE     The specified microcode patch need to be loaded.
373   @retval FALSE    The specified microcode patch dosen't need to be loaded.
374 **/
375 BOOLEAN
IsMicrocodePatchNeedLoad(IN CPU_MP_DATA * CpuMpData,CPU_MICROCODE_HEADER * MicrocodeEntryPoint)376 IsMicrocodePatchNeedLoad (
377   IN CPU_MP_DATA                 *CpuMpData,
378   CPU_MICROCODE_HEADER           *MicrocodeEntryPoint
379   )
380 {
381   BOOLEAN                                NeedLoad;
382   UINTN                                  DataSize;
383   UINTN                                  TotalSize;
384   CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;
385   UINT32                                 ExtendedTableCount;
386   CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;
387   UINTN                                  Index;
388 
389   //
390   // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.
391   //
392   NeedLoad = IsProcessorMatchedMicrocodePatch (
393                CpuMpData,
394                MicrocodeEntryPoint->ProcessorSignature.Uint32,
395                MicrocodeEntryPoint->ProcessorFlags
396                );
397 
398   //
399   // If the Extended Signature Table exists, check if the processor is in the
400   // support list
401   //
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);
411 
412     for (Index = 0; Index < ExtendedTableCount; Index ++) {
413       //
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
417       //
418       NeedLoad = IsProcessorMatchedMicrocodePatch (
419                    CpuMpData,
420                    ExtendedTable->ProcessorSignature.Uint32,
421                    ExtendedTable->ProcessorFlag
422                    );
423       if (NeedLoad) {
424         break;
425       }
426       ExtendedTable ++;
427     }
428   }
429 
430   return NeedLoad;
431 }
432 
433 
434 /**
435   Actual worker function that shadows the required microcode patches into memory.
436 
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
440                                     into memory.
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
444                                     to be loaded.
445 **/
446 VOID
ShadowMicrocodePatchWorker(IN OUT CPU_MP_DATA * CpuMpData,IN MICROCODE_PATCH_INFO * Patches,IN UINTN PatchCount,IN UINTN TotalLoadSize)447 ShadowMicrocodePatchWorker (
448   IN OUT CPU_MP_DATA             *CpuMpData,
449   IN     MICROCODE_PATCH_INFO    *Patches,
450   IN     UINTN                   PatchCount,
451   IN     UINTN                   TotalLoadSize
452   )
453 {
454   UINTN    Index;
455   VOID     *MicrocodePatchInRam;
456   UINT8    *Walker;
457 
458   ASSERT ((Patches != NULL) && (PatchCount != 0));
459 
460   MicrocodePatchInRam = AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize));
461   if (MicrocodePatchInRam == NULL) {
462     return;
463   }
464 
465   //
466   // Load all the required microcode patches into memory
467   //
468   for (Walker = MicrocodePatchInRam, Index = 0; Index < PatchCount; Index++) {
469     CopyMem (
470       Walker,
471       (VOID *) Patches[Index].Address,
472       Patches[Index].Size
473       );
474     Walker += Patches[Index].Size;
475   }
476 
477   //
478   // Update the microcode patch related fields in CpuMpData
479   //
480   CpuMpData->MicrocodePatchAddress    = (UINTN) MicrocodePatchInRam;
481   CpuMpData->MicrocodePatchRegionSize = TotalLoadSize;
482 
483   DEBUG ((
484     DEBUG_INFO,
485     "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
486     __FUNCTION__, CpuMpData->MicrocodePatchAddress, CpuMpData->MicrocodePatchRegionSize
487     ));
488 
489   return;
490 }
491 
492 /**
493   Shadow the required microcode patches data into memory according to PCD
494   PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.
495 
496   @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.
497 **/
498 VOID
ShadowMicrocodePatchByPcd(IN OUT CPU_MP_DATA * CpuMpData)499 ShadowMicrocodePatchByPcd (
500   IN OUT CPU_MP_DATA             *CpuMpData
501   )
502 {
503   CPU_MICROCODE_HEADER                   *MicrocodeEntryPoint;
504   UINTN                                  MicrocodeEnd;
505   UINTN                                  DataSize;
506   UINTN                                  TotalSize;
507   MICROCODE_PATCH_INFO                   *PatchInfoBuffer;
508   UINTN                                  MaxPatchNumber;
509   UINTN                                  PatchCount;
510   UINTN                                  TotalLoadSize;
511 
512   //
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.
516   //
517   CpuMpData->MicrocodePatchAddress    = PcdGet64 (PcdCpuMicrocodePatchAddress);
518   CpuMpData->MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize);
519 
520   MicrocodeEntryPoint    = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;
521   MicrocodeEnd           = (UINTN) MicrocodeEntryPoint +
522                            (UINTN) CpuMpData->MicrocodePatchRegionSize;
523   if ((MicrocodeEntryPoint == NULL) || ((UINTN) MicrocodeEntryPoint == MicrocodeEnd)) {
524     //
525     // There is no microcode patches
526     //
527     return;
528   }
529 
530   PatchCount      = 0;
531   MaxPatchNumber  = DEFAULT_MAX_MICROCODE_PATCH_NUM;
532   TotalLoadSize   = 0;
533   PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));
534   if (PatchInfoBuffer == NULL) {
535     return;
536   }
537 
538   //
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.
541   //
542   do {
543     if (MicrocodeEntryPoint->HeaderVersion != 0x1) {
544       //
545       // Padding data between the microcode patches, skip 1KB to check next entry.
546       //
547       MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
548       continue;
549     }
550 
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 ||
557          TotalSize < DataSize
558        ) {
559       //
560       // Not a valid microcode header, skip 1KB to check next entry.
561       //
562       MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
563       continue;
564     }
565 
566     if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {
567       PatchCount++;
568       if (PatchCount > MaxPatchNumber) {
569         //
570         // Current 'PatchInfoBuffer' cannot hold the information, double the size
571         // and allocate a new buffer.
572         //
573         if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {
574           //
575           // Overflow check for MaxPatchNumber
576           //
577           goto OnExit;
578         }
579 
580         PatchInfoBuffer = ReallocatePool (
581                             MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),
582                             2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),
583                             PatchInfoBuffer
584                             );
585         if (PatchInfoBuffer == NULL) {
586           goto OnExit;
587         }
588         MaxPatchNumber = MaxPatchNumber * 2;
589       }
590 
591       //
592       // Store the information of this microcode patch
593       //
594       PatchInfoBuffer[PatchCount - 1].Address = (UINTN) MicrocodeEntryPoint;
595       PatchInfoBuffer[PatchCount - 1].Size    = TotalSize;
596       TotalLoadSize += TotalSize;
597     }
598 
599     //
600     // Process the next microcode patch
601     //
602     MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
603   } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
604 
605   if (PatchCount != 0) {
606     DEBUG ((
607       DEBUG_INFO,
608       "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
609       __FUNCTION__, PatchCount, TotalLoadSize
610       ));
611 
612     ShadowMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);
613   }
614 
615 OnExit:
616   if (PatchInfoBuffer != NULL) {
617     FreePool (PatchInfoBuffer);
618   }
619   return;
620 }
621 
622 /**
623   Shadow the required microcode patches data into memory.
624 
625   @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.
626 **/
627 VOID
ShadowMicrocodeUpdatePatch(IN OUT CPU_MP_DATA * CpuMpData)628 ShadowMicrocodeUpdatePatch (
629   IN OUT CPU_MP_DATA             *CpuMpData
630   )
631 {
632   EFI_STATUS     Status;
633 
634   Status = PlatformShadowMicrocode (CpuMpData);
635   if (EFI_ERROR (Status)) {
636     ShadowMicrocodePatchByPcd (CpuMpData);
637   }
638 }
639 
640 /**
641   Get the cached microcode patch base address and size from the microcode patch
642   information cache HOB.
643 
644   @param[out] Address       Base address of the microcode patches data.
645                             It will be updated if the microcode patch
646                             information cache HOB is found.
647   @param[out] RegionSize    Size of the microcode patches data.
648                             It will be updated if the microcode patch
649                             information cache HOB is found.
650 
651   @retval  TRUE     The microcode patch information cache HOB is found.
652   @retval  FALSE    The microcode patch information cache HOB is not found.
653 
654 **/
655 BOOLEAN
GetMicrocodePatchInfoFromHob(UINT64 * Address,UINT64 * RegionSize)656 GetMicrocodePatchInfoFromHob (
657   UINT64                         *Address,
658   UINT64                         *RegionSize
659   )
660 {
661   EFI_HOB_GUID_TYPE            *GuidHob;
662   EDKII_MICROCODE_PATCH_HOB    *MicrocodePathHob;
663 
664   GuidHob = GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid);
665   if (GuidHob == NULL) {
666     DEBUG((DEBUG_INFO, "%a: Microcode patch cache HOB is not found.\n", __FUNCTION__));
667     return FALSE;
668   }
669 
670   MicrocodePathHob = GET_GUID_HOB_DATA (GuidHob);
671 
672   *Address    = MicrocodePathHob->MicrocodePatchAddress;
673   *RegionSize = MicrocodePathHob->MicrocodePatchRegionSize;
674 
675   DEBUG((
676     DEBUG_INFO, "%a: MicrocodeBase = 0x%lx, MicrocodeSize = 0x%lx\n",
677     __FUNCTION__, *Address, *RegionSize
678     ));
679 
680   return TRUE;
681 }
682