]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
Revert "UefiCpuPkg: Check invalid RegisterCpuFeature parameter"
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / PeiRegisterCpuFeaturesLib.c
index 12a516a107207eb7799999636d7b5c54ddfa956f..6804eddf65d9f3c4affc97dbae02faca2fdb1b67 100644 (file)
-/** @file
-  CPU Register Table Library functions.
-
-  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-  This program and the accompanying materials
-  are licensed and made available under the terms and conditions of the BSD License
-  which accompanies this distribution.  The full text of the license may be found at
-  http://opensource.org/licenses/bsd-license.php
-
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <PiPei.h>
-
-#include <Library/HobLib.h>
-#include <Library/PeiServicesLib.h>
-#include <Library/PeiServicesTablePointerLib.h>
-#include <Ppi/MpServices.h>
-#include "RegisterCpuFeatures.h"
-
-#define REGISTER_CPU_FEATURES_GUID \
-  { \
-    0xa694c467, 0x697a, 0x446b, { 0xb9, 0x29, 0x5b, 0x14, 0xa0, 0xcf, 0x39, 0xf } \
-  }
-
-EFI_GUID mRegisterCpuFeaturesHobGuid = REGISTER_CPU_FEATURES_GUID;
-
-/**
-  Worker function to get CPU_FEATURES_DATA pointer.
-
-  @return Pointer to CPU_FEATURES_DATA.
-**/
-CPU_FEATURES_DATA *
-GetCpuFeaturesData (
-  VOID
-  )
-{
-  CPU_FEATURES_DATA       *CpuInitData;
-  EFI_HOB_GUID_TYPE       *GuidHob;
-  VOID                    *DataInHob;
-  UINT64                  Data64;
-
-  CpuInitData = NULL;
-  GuidHob = GetFirstGuidHob (&mRegisterCpuFeaturesHobGuid);
-  if (GuidHob != NULL) {
-    DataInHob = GET_GUID_HOB_DATA (GuidHob);
-    CpuInitData = (CPU_FEATURES_DATA *) (*(UINTN *) DataInHob);
-    ASSERT (CpuInitData != NULL);
-  } else {
-    CpuInitData = AllocateZeroPool (sizeof (CPU_FEATURES_DATA));
-    ASSERT (CpuInitData != NULL);
-    //
-    // Build location of CPU MP DATA buffer in HOB
-    //
-    Data64 = (UINT64) (UINTN) CpuInitData;
-    BuildGuidDataHob (
-      &mRegisterCpuFeaturesHobGuid,
-      (VOID *) &Data64,
-      sizeof (UINT64)
-      );
-  }
-
-  return CpuInitData;
-}
-
-/**
-  Worker function to get MP PPI service pointer.
-
-  @return PEI PPI service pointer.
-**/
-EFI_PEI_MP_SERVICES_PPI *
-GetMpPpi (
-  VOID
-  )
-{
-  EFI_STATUS                 Status;
-  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
-
-  //
-  // Get MP Services Protocol
-  //
-  Status = PeiServicesLocatePpi (
-             &gEfiPeiMpServicesPpiGuid,
-             0,
-             NULL,
-             (VOID **)&CpuMpPpi
-             );
-  ASSERT_EFI_ERROR (Status);
-  return CpuMpPpi;
-}
-
-/**
-  Worker function to return processor index.
-
-  @return  The processor index.
-**/
-UINTN
-GetProcessorIndex (
-  VOID
-  )
-{
-  EFI_STATUS                 Status;
-  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
-  UINTN                      ProcessorIndex;
-
-  CpuMpPpi = GetMpPpi ();
-
-  Status = CpuMpPpi->WhoAmI(GetPeiServicesTablePointer (), CpuMpPpi, &ProcessorIndex);
-  ASSERT_EFI_ERROR (Status);
-  return ProcessorIndex;
-}
-
-/**
-  Worker function to MP-related information on the requested processor at the
-  instant this call is made.
-
-  @param[in]  ProcessorNumber       The handle number of processor.
-  @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for
-                                    the requested processor is deposited.
-
-  @return Status of MpServices->GetProcessorInfo().
-**/
-EFI_STATUS
-GetProcessorInformation (
-  IN  UINTN                            ProcessorNumber,
-  OUT EFI_PROCESSOR_INFORMATION        *ProcessorInfoBuffer
-  )
-{
-  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
-  EFI_STATUS                 Status;
-
-  CpuMpPpi = GetMpPpi ();
-  Status = CpuMpPpi->GetProcessorInfo (
-               GetPeiServicesTablePointer(),
-               CpuMpPpi,
-               ProcessorNumber,
-               ProcessorInfoBuffer
-               );
-  return Status;
-}
-
-/**
-  Worker function to execute a caller provided function on all enabled APs.
-
-  @param[in]  Procedure               A pointer to the function to be run on
-                                      enabled APs of the system.
-**/
-VOID
-StartupAPsWorker (
-  IN  EFI_AP_PROCEDURE                 Procedure
-  )
-{
-  EFI_STATUS                           Status;
-  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;
-
-  //
-  // Get MP Services Protocol
-  //
-  Status = PeiServicesLocatePpi (
-             &gEfiPeiMpServicesPpiGuid,
-             0,
-             NULL,
-             (VOID **)&CpuMpPpi
-             );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Wakeup all APs for data collection.
-  //
-  Status = CpuMpPpi->StartupAllAPs (
-                 GetPeiServicesTablePointer (),
-                 CpuMpPpi,
-                 Procedure,
-                 FALSE,
-                 0,
-                 NULL
-                 );
-  ASSERT_EFI_ERROR (Status);
-}
-
-/**
-  Worker function to switch the requested AP to be the BSP from that point onward.
-
-  @param[in] ProcessorNumber   The handle number of AP that is to become the new BSP.
-**/
-VOID
-SwitchNewBsp (
-  IN  UINTN                            ProcessorNumber
-  )
-{
-  EFI_STATUS                           Status;
-  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;
-
-  //
-  // Get MP Services Protocol
-  //
-  Status = PeiServicesLocatePpi (
-             &gEfiPeiMpServicesPpiGuid,
-             0,
-             NULL,
-             (VOID **)&CpuMpPpi
-             );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Wakeup all APs for data collection.
-  //
-  Status = CpuMpPpi->SwitchBSP (
-                 GetPeiServicesTablePointer (),
-                 CpuMpPpi,
-                 ProcessorNumber,
-                 TRUE
-                 );
-  ASSERT_EFI_ERROR (Status);
-}
-
-/**
-  Worker function to retrieve the number of logical processor in the platform.
-
-  @param[out] NumberOfProcessors          Pointer to the total number of logical
-                                          processors in the system, including the BSP
-                                          and disabled APs.
-  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical
-                                          processors that exist in system, including
-                                          the BSP.
-**/
-VOID
-GetNumberOfProcessor (
-  OUT UINTN                            *NumberOfCpus,
-  OUT UINTN                            *NumberOfEnabledProcessors
-  )
-{
-  EFI_STATUS                 Status;
-  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;
-
-  //
-  // Get MP Services Protocol
-  //
-  Status = PeiServicesLocatePpi (
-             &gEfiPeiMpServicesPpiGuid,
-             0,
-             NULL,
-             (VOID **)&CpuMpPpi
-             );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Get the number of CPUs
-  //
-  Status = CpuMpPpi->GetNumberOfProcessors (
-                         GetPeiServicesTablePointer (),
-                         CpuMpPpi,
-                         NumberOfCpus,
-                         NumberOfEnabledProcessors
-                         );
-  ASSERT_EFI_ERROR (Status);
-}
-
-/**
-  Allocates ACPI NVS memory to save ACPI_CPU_DATA.
-
-  @return  Pointer to allocated ACPI_CPU_DATA.
-**/
-ACPI_CPU_DATA *
-AllocateAcpiCpuData (
-  VOID
-  )
-{
-  EFI_STATUS                           Status;
-  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;
-  UINTN                                NumberOfCpus;
-  UINTN                                NumberOfEnabledProcessors;
-  ACPI_CPU_DATA                        *AcpiCpuData;
-  EFI_PHYSICAL_ADDRESS                 Address;
-  UINTN                                TableSize;
-  CPU_REGISTER_TABLE                   *RegisterTable;
-  UINTN                                Index;
-  EFI_PROCESSOR_INFORMATION            ProcessorInfoBuffer;
-
-  Status = PeiServicesAllocatePages (
-             EfiACPIMemoryNVS,
-             EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)),
-             &Address
-             );
-  ASSERT_EFI_ERROR (Status);
-  AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) Address;
-  ASSERT (AcpiCpuData != NULL);
-
-  //
-  // Get MP Services Protocol
-  //
-  Status = PeiServicesLocatePpi (
-             &gEfiPeiMpServicesPpiGuid,
-             0,
-             NULL,
-             (VOID **)&CpuMpPpi
-             );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Get the number of CPUs
-  //
-  Status = CpuMpPpi->GetNumberOfProcessors (
-                         GetPeiServicesTablePointer (),
-                         CpuMpPpi,
-                         &NumberOfCpus,
-                         &NumberOfEnabledProcessors
-                         );
-  ASSERT_EFI_ERROR (Status);
-  AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
-
-  //
-  // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
-  //
-  TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
-  Status = PeiServicesAllocatePages (
-             EfiACPIMemoryNVS,
-             EFI_SIZE_TO_PAGES (TableSize),
-             &Address
-             );
-  ASSERT_EFI_ERROR (Status);
-  RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) Address;
-
-  for (Index = 0; Index < NumberOfCpus; Index++) {
-    Status = CpuMpPpi->GetProcessorInfo (
-                         GetPeiServicesTablePointer (),
-                         CpuMpPpi,
-                         Index,
-                         &ProcessorInfoBuffer
-                         );
-    ASSERT_EFI_ERROR (Status);
-
-    RegisterTable[Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;
-    RegisterTable[Index].TableLength        = 0;
-    RegisterTable[Index].AllocatedSize      = 0;
-    RegisterTable[Index].RegisterTableEntry = 0;
-
-    RegisterTable[NumberOfCpus + Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;
-    RegisterTable[NumberOfCpus + Index].TableLength        = 0;
-    RegisterTable[NumberOfCpus + Index].AllocatedSize      = 0;
-    RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
-  }
-  AcpiCpuData->RegisterTable           = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
-  AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
-
-  return AcpiCpuData;
-}
-
-/**
-  Enlarges CPU register table for each processor.
-
-  @param[in, out]  RegisterTable   Pointer processor's CPU register table
-**/
-VOID
-EnlargeRegisterTable (
-  IN OUT CPU_REGISTER_TABLE            *RegisterTable
-  )
-{
-  EFI_STATUS                           Status;
-  EFI_PHYSICAL_ADDRESS                 Address;
-  UINTN                                AllocatePages;
-
-  AllocatePages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
-  Status = PeiServicesAllocatePages (
-             EfiACPIMemoryNVS,
-             AllocatePages + 1,
-             &Address
-             );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // If there are records existing in the register table, then copy its contents
-  // to new region and free the old one.
-  //
-  if (RegisterTable->AllocatedSize > 0) {
-    CopyMem (
-      (VOID *) (UINTN) Address,
-      (VOID *) (UINTN) RegisterTable->RegisterTableEntry,
-      RegisterTable->AllocatedSize
-      );
-  }
-
-  //
-  // Adjust the allocated size and register table base address.
-  //
-  RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
-  RegisterTable->RegisterTableEntry = Address;
-}
+/** @file\r
+  CPU Register Table Library functions.\r
+\r
+  Copyright (c) 2016, 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
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Library/HobLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Ppi/MpServices.h>\r
+#include "RegisterCpuFeatures.h"\r
+\r
+#define REGISTER_CPU_FEATURES_GUID \\r
+  { \\r
+    0xa694c467, 0x697a, 0x446b, { 0xb9, 0x29, 0x5b, 0x14, 0xa0, 0xcf, 0x39, 0xf } \\r
+  }\r
+\r
+EFI_GUID mRegisterCpuFeaturesHobGuid = REGISTER_CPU_FEATURES_GUID;\r
+\r
+/**\r
+  Worker function to get CPU_FEATURES_DATA pointer.\r
+\r
+  @return Pointer to CPU_FEATURES_DATA.\r
+**/\r
+CPU_FEATURES_DATA *\r
+GetCpuFeaturesData (\r
+  VOID\r
+  )\r
+{\r
+  CPU_FEATURES_DATA       *CpuInitData;\r
+  EFI_HOB_GUID_TYPE       *GuidHob;\r
+  VOID                    *DataInHob;\r
+  UINT64                  Data64;\r
+\r
+  CpuInitData = NULL;\r
+  GuidHob = GetFirstGuidHob (&mRegisterCpuFeaturesHobGuid);\r
+  if (GuidHob != NULL) {\r
+    DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
+    CpuInitData = (CPU_FEATURES_DATA *) (*(UINTN *) DataInHob);\r
+    ASSERT (CpuInitData != NULL);\r
+  } else {\r
+    CpuInitData = AllocateZeroPool (sizeof (CPU_FEATURES_DATA));\r
+    ASSERT (CpuInitData != NULL);\r
+    //\r
+    // Build location of CPU MP DATA buffer in HOB\r
+    //\r
+    Data64 = (UINT64) (UINTN) CpuInitData;\r
+    BuildGuidDataHob (\r
+      &mRegisterCpuFeaturesHobGuid,\r
+      (VOID *) &Data64,\r
+      sizeof (UINT64)\r
+      );\r
+  }\r
+\r
+  return CpuInitData;\r
+}\r
+\r
+/**\r
+  Worker function to get MP PPI service pointer.\r
+\r
+  @return PEI PPI service pointer.\r
+**/\r
+EFI_PEI_MP_SERVICES_PPI *\r
+GetMpPpi (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;\r
+\r
+  //\r
+  // Get MP Services Protocol\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMpServicesPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&CpuMpPpi\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  return CpuMpPpi;\r
+}\r
+\r
+/**\r
+  Worker function to return processor index.\r
+\r
+  @return  The processor index.\r
+**/\r
+UINTN\r
+GetProcessorIndex (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;\r
+  UINTN                      ProcessorIndex;\r
+\r
+  CpuMpPpi = GetMpPpi ();\r
+\r
+  Status = CpuMpPpi->WhoAmI(GetPeiServicesTablePointer (), CpuMpPpi, &ProcessorIndex);\r
+  ASSERT_EFI_ERROR (Status);\r
+  return ProcessorIndex;\r
+}\r
+\r
+/**\r
+  Worker function to MP-related information on the requested processor at the\r
+  instant this call is made.\r
+\r
+  @param[in]  ProcessorNumber       The handle number of processor.\r
+  @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for\r
+                                    the requested processor is deposited.\r
+\r
+  @return Status of MpServices->GetProcessorInfo().\r
+**/\r
+EFI_STATUS\r
+GetProcessorInformation (\r
+  IN  UINTN                            ProcessorNumber,\r
+  OUT EFI_PROCESSOR_INFORMATION        *ProcessorInfoBuffer\r
+  )\r
+{\r
+  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;\r
+  EFI_STATUS                 Status;\r
+\r
+  CpuMpPpi = GetMpPpi ();\r
+  Status = CpuMpPpi->GetProcessorInfo (\r
+               GetPeiServicesTablePointer(),\r
+               CpuMpPpi,\r
+               ProcessorNumber,\r
+               ProcessorInfoBuffer\r
+               );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Worker function to execute a caller provided function on all enabled APs.\r
+\r
+  @param[in]  Procedure               A pointer to the function to be run on\r
+                                      enabled APs of the system.\r
+**/\r
+VOID\r
+StartupAPsWorker (\r
+  IN  EFI_AP_PROCEDURE                 Procedure\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;\r
+\r
+  //\r
+  // Get MP Services Protocol\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMpServicesPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&CpuMpPpi\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Wakeup all APs for data collection.\r
+  //\r
+  Status = CpuMpPpi->StartupAllAPs (\r
+                 GetPeiServicesTablePointer (),\r
+                 CpuMpPpi,\r
+                 Procedure,\r
+                 FALSE,\r
+                 0,\r
+                 NULL\r
+                 );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Worker function to switch the requested AP to be the BSP from that point onward.\r
+\r
+  @param[in] ProcessorNumber   The handle number of AP that is to become the new BSP.\r
+**/\r
+VOID\r
+SwitchNewBsp (\r
+  IN  UINTN                            ProcessorNumber\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;\r
+\r
+  //\r
+  // Get MP Services Protocol\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMpServicesPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&CpuMpPpi\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Wakeup all APs for data collection.\r
+  //\r
+  Status = CpuMpPpi->SwitchBSP (\r
+                 GetPeiServicesTablePointer (),\r
+                 CpuMpPpi,\r
+                 ProcessorNumber,\r
+                 TRUE\r
+                 );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Worker function to retrieve the number of logical processor in the platform.\r
+\r
+  @param[out] NumberOfCpus                Pointer to the total number of logical\r
+                                          processors in the system, including the BSP\r
+                                          and disabled APs.\r
+  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical\r
+                                          processors that exist in system, including\r
+                                          the BSP.\r
+**/\r
+VOID\r
+GetNumberOfProcessor (\r
+  OUT UINTN                            *NumberOfCpus,\r
+  OUT UINTN                            *NumberOfEnabledProcessors\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_PEI_MP_SERVICES_PPI    *CpuMpPpi;\r
+\r
+  //\r
+  // Get MP Services Protocol\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMpServicesPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&CpuMpPpi\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get the number of CPUs\r
+  //\r
+  Status = CpuMpPpi->GetNumberOfProcessors (\r
+                         GetPeiServicesTablePointer (),\r
+                         CpuMpPpi,\r
+                         NumberOfCpus,\r
+                         NumberOfEnabledProcessors\r
+                         );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Allocates ACPI NVS memory to save ACPI_CPU_DATA.\r
+\r
+  @return  Pointer to allocated ACPI_CPU_DATA.\r
+**/\r
+ACPI_CPU_DATA *\r
+AllocateAcpiCpuData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_PEI_MP_SERVICES_PPI              *CpuMpPpi;\r
+  UINTN                                NumberOfCpus;\r
+  UINTN                                NumberOfEnabledProcessors;\r
+  ACPI_CPU_DATA                        *AcpiCpuData;\r
+  EFI_PHYSICAL_ADDRESS                 Address;\r
+  UINTN                                TableSize;\r
+  CPU_REGISTER_TABLE                   *RegisterTable;\r
+  UINTN                                Index;\r
+  EFI_PROCESSOR_INFORMATION            ProcessorInfoBuffer;\r
+\r
+  Status = PeiServicesAllocatePages (\r
+             EfiACPIMemoryNVS,\r
+             EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)),\r
+             &Address\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) Address;\r
+  ASSERT (AcpiCpuData != NULL);\r
+\r
+  //\r
+  // Get MP Services Protocol\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMpServicesPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&CpuMpPpi\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get the number of CPUs\r
+  //\r
+  Status = CpuMpPpi->GetNumberOfProcessors (\r
+                         GetPeiServicesTablePointer (),\r
+                         CpuMpPpi,\r
+                         &NumberOfCpus,\r
+                         &NumberOfEnabledProcessors\r
+                         );\r
+  ASSERT_EFI_ERROR (Status);\r
+  AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;\r
+\r
+  //\r
+  // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs\r
+  //\r
+  TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);\r
+  Status = PeiServicesAllocatePages (\r
+             EfiACPIMemoryNVS,\r
+             EFI_SIZE_TO_PAGES (TableSize),\r
+             &Address\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) Address;\r
+\r
+  for (Index = 0; Index < NumberOfCpus; Index++) {\r
+    Status = CpuMpPpi->GetProcessorInfo (\r
+                         GetPeiServicesTablePointer (),\r
+                         CpuMpPpi,\r
+                         Index,\r
+                         &ProcessorInfoBuffer\r
+                         );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    RegisterTable[Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
+    RegisterTable[Index].TableLength        = 0;\r
+    RegisterTable[Index].AllocatedSize      = 0;\r
+    RegisterTable[Index].RegisterTableEntry = 0;\r
+\r
+    RegisterTable[NumberOfCpus + Index].InitialApicId      = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
+    RegisterTable[NumberOfCpus + Index].TableLength        = 0;\r
+    RegisterTable[NumberOfCpus + Index].AllocatedSize      = 0;\r
+    RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;\r
+  }\r
+  AcpiCpuData->RegisterTable           = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;\r
+  AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);\r
+\r
+  return AcpiCpuData;\r
+}\r
+\r
+/**\r
+  Enlarges CPU register table for each processor.\r
+\r
+  @param[in, out]  RegisterTable   Pointer processor's CPU register table\r
+**/\r
+VOID\r
+EnlargeRegisterTable (\r
+  IN OUT CPU_REGISTER_TABLE            *RegisterTable\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_PHYSICAL_ADDRESS                 Address;\r
+  UINTN                                AllocatePages;\r
+\r
+  AllocatePages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;\r
+  Status = PeiServicesAllocatePages (\r
+             EfiACPIMemoryNVS,\r
+             AllocatePages + 1,\r
+             &Address\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // If there are records existing in the register table, then copy its contents\r
+  // to new region and free the old one.\r
+  //\r
+  if (RegisterTable->AllocatedSize > 0) {\r
+    CopyMem (\r
+      (VOID *) (UINTN) Address,\r
+      (VOID *) (UINTN) RegisterTable->RegisterTableEntry,\r
+      RegisterTable->AllocatedSize\r
+      );\r
+  }\r
+\r
+  //\r
+  // Adjust the allocated size and register table base address.\r
+  //\r
+  RegisterTable->AllocatedSize += EFI_PAGE_SIZE;\r
+  RegisterTable->RegisterTableEntry = Address;\r
+}\r