]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/Microcode.c
UefiCpuPkg/PiSmmCpuDxeSmm: improve the coding style
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Microcode.c
index 643a6f94f4a5fb1d0aee99f1da954bf12f8f96be..3da5bfb9cf2f9a4a4293a0967b80323e6480474c 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Implementation of loading microcode on processors.\r
 \r
 /** @file\r
   Implementation of loading microcode on processors.\r
 \r
-  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 \r
 **/\r
 \r
@@ -71,13 +65,15 @@ GetCurrentMicrocodeSignature (
          It does not guarantee that the data has not been modified.\r
          CPU has its own mechanism to verify Microcode Binary part.\r
 \r
          It does not guarantee that the data has not been modified.\r
          CPU has its own mechanism to verify Microcode Binary part.\r
 \r
-  @param[in]  CpuMpData    The pointer to CPU MP Data structure.\r
-  @param[in]  IsBspCallIn  Indicate whether the caller is BSP or not.\r
+  @param[in]  CpuMpData        The pointer to CPU MP Data structure.\r
+  @param[in]  ProcessorNumber  The handle number of the processor. The range is\r
+                               from 0 to the total number of logical processors\r
+                               minus 1.\r
 **/\r
 VOID\r
 MicrocodeDetect (\r
   IN CPU_MP_DATA             *CpuMpData,\r
 **/\r
 VOID\r
 MicrocodeDetect (\r
   IN CPU_MP_DATA             *CpuMpData,\r
-  IN BOOLEAN                 IsBspCallIn\r
+  IN UINTN                   ProcessorNumber\r
   )\r
 {\r
   UINT32                                  ExtendedTableLength;\r
   )\r
 {\r
   UINT32                                  ExtendedTableLength;\r
@@ -89,6 +85,7 @@ MicrocodeDetect (
   UINTN                                   Index;\r
   UINT8                                   PlatformId;\r
   CPUID_VERSION_INFO_EAX                  Eax;\r
   UINTN                                   Index;\r
   UINT8                                   PlatformId;\r
   CPUID_VERSION_INFO_EAX                  Eax;\r
+  CPU_AP_DATA                             *CpuData;\r
   UINT32                                  CurrentRevision;\r
   UINT32                                  LatestRevision;\r
   UINTN                                   TotalSize;\r
   UINT32                                  CurrentRevision;\r
   UINT32                                  LatestRevision;\r
   UINTN                                   TotalSize;\r
@@ -96,14 +93,8 @@ MicrocodeDetect (
   UINT32                                  InCompleteCheckSum32;\r
   BOOLEAN                                 CorrectMicrocode;\r
   VOID                                    *MicrocodeData;\r
   UINT32                                  InCompleteCheckSum32;\r
   BOOLEAN                                 CorrectMicrocode;\r
   VOID                                    *MicrocodeData;\r
-  MSR_IA32_PLATFORM_ID_REGISTER           PlatformIdMsr;\r
-  UINT32                                  ProcessorFlags;\r
   UINT32                                  ThreadId;\r
   UINT32                                  ThreadId;\r
-\r
-  //\r
-  // set ProcessorFlags to suppress incorrect compiler/analyzer warnings\r
-  //\r
-  ProcessorFlags = 0;\r
+  BOOLEAN                                 IsBspCallIn;\r
 \r
   if (CpuMpData->MicrocodePatchRegionSize == 0) {\r
     //\r
 \r
   if (CpuMpData->MicrocodePatchRegionSize == 0) {\r
     //\r
@@ -113,6 +104,7 @@ MicrocodeDetect (
   }\r
 \r
   CurrentRevision = GetCurrentMicrocodeSignature ();\r
   }\r
 \r
   CurrentRevision = GetCurrentMicrocodeSignature ();\r
+  IsBspCallIn     = (ProcessorNumber == (UINTN)CpuMpData->BspNumber) ? TRUE : FALSE;\r
   if (CurrentRevision != 0 && !IsBspCallIn) {\r
     //\r
     // Skip loading microcode if it has been loaded successfully\r
   if (CurrentRevision != 0 && !IsBspCallIn) {\r
     //\r
     // Skip loading microcode if it has been loaded successfully\r
@@ -129,28 +121,25 @@ MicrocodeDetect (
   }\r
 \r
   ExtendedTableLength = 0;\r
   }\r
 \r
   ExtendedTableLength = 0;\r
-  //\r
-  // Here data of CPUID leafs have not been collected into context buffer, so\r
-  // GetProcessorCpuid() cannot be used here to retrieve CPUID data.\r
-  //\r
-  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);\r
-\r
-  //\r
-  // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID\r
-  //\r
-  PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);\r
-  PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;\r
+  Eax.Uint32 = CpuMpData->CpuData[ProcessorNumber].ProcessorSignature;\r
+  PlatformId = CpuMpData->CpuData[ProcessorNumber].PlatformId;\r
 \r
   //\r
   // Check whether AP has same processor with BSP.\r
   // If yes, direct use microcode info saved by BSP.\r
   //\r
   if (!IsBspCallIn) {\r
 \r
   //\r
   // Check whether AP has same processor with BSP.\r
   // If yes, direct use microcode info saved by BSP.\r
   //\r
   if (!IsBspCallIn) {\r
-    if ((CpuMpData->ProcessorSignature == Eax.Uint32) &&\r
-        (CpuMpData->ProcessorFlags & (1 << PlatformId)) != 0) {\r
-        MicrocodeData = (VOID *)(UINTN) CpuMpData->MicrocodeDataAddress;\r
-        LatestRevision = CpuMpData->MicrocodeRevision;\r
-        goto Done;\r
+    //\r
+    // Get the CPU data for BSP\r
+    //\r
+    CpuData = &(CpuMpData->CpuData[CpuMpData->BspNumber]);\r
+    if ((CpuData->ProcessorSignature == Eax.Uint32) &&\r
+        (CpuData->PlatformId == PlatformId) &&\r
+        (CpuData->MicrocodeEntryAddr != 0)) {\r
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN) CpuData->MicrocodeEntryAddr;\r
+      MicrocodeData       = (VOID *) (MicrocodeEntryPoint + 1);\r
+      LatestRevision      = MicrocodeEntryPoint->UpdateRevision;\r
+      goto Done;\r
     }\r
   }\r
 \r
     }\r
   }\r
 \r
@@ -173,9 +162,15 @@ MicrocodeDetect (
     }\r
 \r
     ///\r
     }\r
 \r
     ///\r
-    /// Check overflow and whether TotalSize is aligned with 4 bytes.\r
+    /// 0x0       MicrocodeBegin  MicrocodeEntry  MicrocodeEnd      0xffffffff\r
+    /// |--------------|---------------|---------------|---------------|\r
+    ///                                 valid TotalSize\r
+    /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEntry).\r
+    /// And it should be aligned with 4 bytes.\r
+    /// If the TotalSize is invalid, skip 1KB to check next entry.\r
     ///\r
     ///\r
-    if ( ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||\r
+    if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||\r
+         ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||\r
          (TotalSize & 0x3) != 0\r
        ) {\r
       MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
          (TotalSize & 0x3) != 0\r
        ) {\r
       MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
@@ -212,7 +207,6 @@ MicrocodeDetect (
         CheckSum32 += MicrocodeEntryPoint->Checksum;\r
         if (CheckSum32 == 0) {\r
           CorrectMicrocode = TRUE;\r
         CheckSum32 += MicrocodeEntryPoint->Checksum;\r
         if (CheckSum32 == 0) {\r
           CorrectMicrocode = TRUE;\r
-          ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags;\r
         }\r
       } else if ((MicrocodeEntryPoint->DataSize != 0) &&\r
                  (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {\r
         }\r
       } else if ((MicrocodeEntryPoint->DataSize != 0) &&\r
                  (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {\r
@@ -256,7 +250,6 @@ MicrocodeDetect (
                     // Find one\r
                     //\r
                     CorrectMicrocode = TRUE;\r
                     // Find one\r
                     //\r
                     CorrectMicrocode = TRUE;\r
-                    ProcessorFlags = ExtendedTable->ProcessorFlag;\r
                     break;\r
                   }\r
                 }\r
                     break;\r
                   }\r
                 }\r
@@ -295,6 +288,16 @@ MicrocodeDetect (
   } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
 \r
 Done:\r
   } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
 \r
 Done:\r
+  if (LatestRevision != 0) {\r
+    //\r
+    // Save the detected microcode patch entry address (including the\r
+    // microcode patch header) for each processor.\r
+    // It will be used when building the microcode patch cache HOB.\r
+    //\r
+    CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =\r
+      (UINTN) MicrocodeData -  sizeof (CPU_MICROCODE_HEADER);\r
+  }\r
+\r
   if (LatestRevision > CurrentRevision) {\r
     //\r
     // BIOS only authenticate updates that contain a numerically larger revision\r
   if (LatestRevision > CurrentRevision) {\r
     //\r
     // BIOS only authenticate updates that contain a numerically larger revision\r
@@ -318,16 +321,292 @@ Done:
       ReleaseSpinLock(&CpuMpData->MpLock);\r
     }\r
   }\r
       ReleaseSpinLock(&CpuMpData->MpLock);\r
     }\r
   }\r
+}\r
 \r
 \r
-  if (IsBspCallIn && (LatestRevision != 0)) {\r
+/**\r
+  Determine if a microcode patch will be loaded into memory.\r
+\r
+  @param[in]  CpuMpData             The pointer to CPU MP Data structure.\r
+  @param[in]  ProcessorSignature    The processor signature field value\r
+                                    supported by a microcode patch.\r
+  @param[in]  ProcessorFlags        The prcessor flags field value supported by\r
+                                    a microcode patch.\r
+\r
+  @retval TRUE     The specified microcode patch will be loaded.\r
+  @retval FALSE    The specified microcode patch will not be loaded.\r
+**/\r
+BOOLEAN\r
+IsMicrocodePatchNeedLoad (\r
+  IN CPU_MP_DATA                 *CpuMpData,\r
+  IN UINT32                      ProcessorSignature,\r
+  IN UINT32                      ProcessorFlags\r
+  )\r
+{\r
+  UINTN          Index;\r
+  CPU_AP_DATA    *CpuData;\r
+\r
+  for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+    CpuData = &CpuMpData->CpuData[Index];\r
+    if ((ProcessorSignature == CpuData->ProcessorSignature) &&\r
+        (ProcessorFlags & (1 << CpuData->PlatformId)) != 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Actual worker function that loads the required microcode patches into memory.\r
+\r
+  @param[in, out]  CpuMpData        The pointer to CPU MP Data structure.\r
+  @param[in]       Patches          The pointer to an array of information on\r
+                                    the microcode patches that will be loaded\r
+                                    into memory.\r
+  @param[in]       PatchCount       The number of microcode patches that will\r
+                                    be loaded into memory.\r
+  @param[in]       TotalLoadSize    The total size of all the microcode patches\r
+                                    to be loaded.\r
+**/\r
+VOID\r
+LoadMicrocodePatchWorker (\r
+  IN OUT CPU_MP_DATA             *CpuMpData,\r
+  IN     MICROCODE_PATCH_INFO    *Patches,\r
+  IN     UINTN                   PatchCount,\r
+  IN     UINTN                   TotalLoadSize\r
+  )\r
+{\r
+  UINTN    Index;\r
+  VOID     *MicrocodePatchInRam;\r
+  UINT8    *Walker;\r
+\r
+  ASSERT ((Patches != NULL) && (PatchCount != 0));\r
+\r
+  MicrocodePatchInRam = AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize));\r
+  if (MicrocodePatchInRam == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Load all the required microcode patches into memory\r
+  //\r
+  for (Walker = MicrocodePatchInRam, Index = 0; Index < PatchCount; Index++) {\r
+    CopyMem (\r
+      Walker,\r
+      (VOID *) Patches[Index].Address,\r
+      Patches[Index].Size\r
+      );\r
+\r
+    //\r
+    // Zero-fill the padding area\r
+    // Please note that AlignedSize will be no less than Size\r
     //\r
     //\r
-    // Save BSP processor info and microcode info for later AP use.\r
+    ZeroMem (\r
+      Walker + Patches[Index].Size,\r
+      Patches[Index].AlignedSize - Patches[Index].Size\r
+      );\r
+\r
+    Walker += Patches[Index].AlignedSize;\r
+  }\r
+\r
+  //\r
+  // Update the microcode patch related fields in CpuMpData\r
+  //\r
+  CpuMpData->MicrocodePatchAddress    = (UINTN) MicrocodePatchInRam;\r
+  CpuMpData->MicrocodePatchRegionSize = TotalLoadSize;\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",\r
+    __FUNCTION__, CpuMpData->MicrocodePatchAddress, CpuMpData->MicrocodePatchRegionSize\r
+    ));\r
+\r
+  return;\r
+}\r
+\r
+/**\r
+  Load the required microcode patches data into memory.\r
+\r
+  @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+LoadMicrocodePatch (\r
+  IN OUT CPU_MP_DATA             *CpuMpData\r
+  )\r
+{\r
+  CPU_MICROCODE_HEADER                   *MicrocodeEntryPoint;\r
+  UINTN                                  MicrocodeEnd;\r
+  UINTN                                  DataSize;\r
+  UINTN                                  TotalSize;\r
+  CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;\r
+  UINT32                                 ExtendedTableCount;\r
+  CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;\r
+  MICROCODE_PATCH_INFO                   *PatchInfoBuffer;\r
+  UINTN                                  MaxPatchNumber;\r
+  UINTN                                  PatchCount;\r
+  UINTN                                  TotalLoadSize;\r
+  UINTN                                  Index;\r
+  BOOLEAN                                NeedLoad;\r
+\r
+  //\r
+  // Initialize the microcode patch related fields in CpuMpData as the values\r
+  // specified by the PCD pair. If the microcode patches are loaded into memory,\r
+  // these fields will be updated.\r
+  //\r
+  CpuMpData->MicrocodePatchAddress    = PcdGet64 (PcdCpuMicrocodePatchAddress);\r
+  CpuMpData->MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize);\r
+\r
+  MicrocodeEntryPoint    = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;\r
+  MicrocodeEnd           = (UINTN) MicrocodeEntryPoint +\r
+                           (UINTN) CpuMpData->MicrocodePatchRegionSize;\r
+  if ((MicrocodeEntryPoint == NULL) || ((UINTN) MicrocodeEntryPoint == MicrocodeEnd)) {\r
     //\r
     //\r
-    CpuMpData->ProcessorSignature   = Eax.Uint32;\r
-    CpuMpData->ProcessorFlags       = ProcessorFlags;\r
-    CpuMpData->MicrocodeDataAddress = (UINTN) MicrocodeData;\r
-    CpuMpData->MicrocodeRevision    = LatestRevision;\r
-    DEBUG ((DEBUG_INFO, "BSP Microcode:: signature [0x%08x], ProcessorFlags [0x%08x], \\r
-       MicroData [0x%08x], Revision [0x%08x]\n", Eax.Uint32, ProcessorFlags, (UINTN) MicrocodeData, LatestRevision));\r
+    // There is no microcode patches\r
+    //\r
+    return;\r
+  }\r
+\r
+  PatchCount      = 0;\r
+  MaxPatchNumber  = DEFAULT_MAX_MICROCODE_PATCH_NUM;\r
+  TotalLoadSize   = 0;\r
+  PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));\r
+  if (PatchInfoBuffer == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Process the header of each microcode patch within the region.\r
+  // The purpose is to decide which microcode patch(es) will be loaded into memory.\r
+  //\r
+  do {\r
+    if (MicrocodeEntryPoint->HeaderVersion != 0x1) {\r
+      //\r
+      // Padding data between the microcode patches, skip 1KB to check next entry.\r
+      //\r
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
+      continue;\r
+    }\r
+\r
+    DataSize  = MicrocodeEntryPoint->DataSize;\r
+    TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
+    if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||\r
+         ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||\r
+         (DataSize & 0x3) != 0 ||\r
+         (TotalSize & (SIZE_1KB - 1)) != 0 ||\r
+         TotalSize < DataSize\r
+       ) {\r
+      //\r
+      // Not a valid microcode header, skip 1KB to check next entry.\r
+      //\r
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode\r
+    // patch header with the CPUID and PlatformID of the processors within\r
+    // system to decide if it will be copied into memory\r
+    //\r
+    NeedLoad = IsMicrocodePatchNeedLoad (\r
+                 CpuMpData,\r
+                 MicrocodeEntryPoint->ProcessorSignature.Uint32,\r
+                 MicrocodeEntryPoint->ProcessorFlags\r
+                 );\r
+\r
+    //\r
+    // If the Extended Signature Table exists, check if the processor is in the\r
+    // support list\r
+    //\r
+    if ((!NeedLoad) && (DataSize != 0) &&\r
+        (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +\r
+                                sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {\r
+      ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
+                              + DataSize + sizeof (CPU_MICROCODE_HEADER));\r
+      ExtendedTableCount  = ExtendedTableHeader->ExtendedSignatureCount;\r
+      ExtendedTable       = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
+\r
+      for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
+        //\r
+        // Avoid access content beyond MicrocodeEnd\r
+        //\r
+        if ((UINTN) ExtendedTable > MicrocodeEnd - sizeof (CPU_MICROCODE_EXTENDED_TABLE)) {\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended\r
+        // Signature Table entry with the CPUID and PlatformID of the processors\r
+        // within system to decide if it will be copied into memory\r
+        //\r
+        NeedLoad = IsMicrocodePatchNeedLoad (\r
+                     CpuMpData,\r
+                     ExtendedTable->ProcessorSignature.Uint32,\r
+                     ExtendedTable->ProcessorFlag\r
+                     );\r
+        if (NeedLoad) {\r
+          break;\r
+        }\r
+        ExtendedTable ++;\r
+      }\r
+    }\r
+\r
+    if (NeedLoad) {\r
+      PatchCount++;\r
+      if (PatchCount > MaxPatchNumber) {\r
+        //\r
+        // Current 'PatchInfoBuffer' cannot hold the information, double the size\r
+        // and allocate a new buffer.\r
+        //\r
+        if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {\r
+          //\r
+          // Overflow check for MaxPatchNumber\r
+          //\r
+          goto OnExit;\r
+        }\r
+\r
+        PatchInfoBuffer = ReallocatePool (\r
+                            MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
+                            2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),\r
+                            PatchInfoBuffer\r
+                            );\r
+        if (PatchInfoBuffer == NULL) {\r
+          goto OnExit;\r
+        }\r
+        MaxPatchNumber = MaxPatchNumber * 2;\r
+      }\r
+\r
+      //\r
+      // Store the information of this microcode patch\r
+      //\r
+      if (TotalSize > ALIGN_VALUE (TotalSize, SIZE_1KB) ||\r
+          ALIGN_VALUE (TotalSize, SIZE_1KB) > MAX_UINTN - TotalLoadSize) {\r
+        goto OnExit;\r
+      }\r
+      PatchInfoBuffer[PatchCount - 1].Address     = (UINTN) MicrocodeEntryPoint;\r
+      PatchInfoBuffer[PatchCount - 1].Size        = TotalSize;\r
+      PatchInfoBuffer[PatchCount - 1].AlignedSize = ALIGN_VALUE (TotalSize, SIZE_1KB);\r
+      TotalLoadSize += PatchInfoBuffer[PatchCount - 1].AlignedSize;\r
+    }\r
+\r
+    //\r
+    // Process the next microcode patch\r
+    //\r
+    MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);\r
+  } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
+\r
+  if (PatchCount != 0) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",\r
+      __FUNCTION__, PatchCount, TotalLoadSize\r
+      ));\r
+\r
+    LoadMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
+  }\r
+\r
+OnExit:\r
+  if (PatchInfoBuffer != NULL) {\r
+    FreePool (PatchInfoBuffer);\r
   }\r
   }\r
+  return;\r
 }\r
 }\r