]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
Revert "UefiCpuPkg: Check invalid RegisterCpuFeature parameter"
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / RegisterCpuFeaturesLib.c
index 7ef015537401b52e77fdcefa0aabbac447414c42..dd6a82be7a5a1c2a2cf1c2e1b0475c496adcc8e6 100644 (file)
-/** @file
-  CPU Register Table Library functions.
-
-  Copyright (c) 2017, 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 "RegisterCpuFeatures.h"
-
-/**
-  Checks if two CPU feature bit masks are equal.
-
-  @param[in]  FirstFeatureMask  The first input CPU feature bit mask
-  @param[in]  SecondFeatureMask The second input CPU feature bit mask
-
-  @retval TRUE  Two CPU feature bit masks are equal.
-  @retval FALSE Two CPU feature bit masks are not equal.
-**/
-BOOLEAN
-IsCpuFeatureMatch (
-  IN UINT8               *FirstFeatureMask,
-  IN UINT8               *SecondFeatureMask
-  )
-{
-  UINT32                 BitMaskSize;
-
-  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
-  if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) {
-    return TRUE;
-  } else {
-    return FALSE;
-  }
-}
-
-/**
-  Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
-
-  @param[in]  FeatureMask  A pointer to the CPU feature bit mask.
-**/
-VOID
-DumpCpuFeatureMask (
-  IN UINT8               *FeatureMask
-  )
-{
-  UINTN                  Index;
-  UINT8                  *Data8;
-  UINT32                 BitMaskSize;
-
-  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
-  Data8       = (UINT8 *) FeatureMask;
-  for (Index = 0; Index < BitMaskSize; Index++) {
-    DEBUG ((DEBUG_INFO, " %02x ", *Data8++));
-  }
-  DEBUG ((DEBUG_INFO, "\n"));
-}
-
-/**
-  Dump CPU feature name or CPU feature bit mask.
-
-  @param[in]  CpuFeature   Pointer to CPU_FEATURES_ENTRY
-**/
-VOID
-DumpCpuFeature (
-  IN CPU_FEATURES_ENTRY  *CpuFeature
-  )
-{
-
-  if (CpuFeature->FeatureName != NULL) {
-    DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName));
-  } else {
-    DEBUG ((DEBUG_INFO, "FeatureMask = "));
-    DumpCpuFeatureMask (CpuFeature->FeatureMask);
-  }
-}
-
-/**
-  Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
-
-  @param[in]  FeatureMask        Pointer to CPU feature bit mask
-  @param[in]  DependentBitMask   Pointer to dependent CPU feature bit mask buffer
-
-  @retval TRUE  The feature bit mask is in dependent CPU feature bit mask buffer.
-  @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
-**/
-BOOLEAN
-IsBitMaskMatchCheck (
-  IN UINT8        *FeatureMask,
-  IN UINT8        *DependentBitMask
-  )
-{
-  UINTN      Index;
-  UINTN      BitMaskSize;
-  UINT8      *Data1;
-  UINT8      *Data2;
-
-  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
-
-  Data1 = FeatureMask;
-  Data2 = DependentBitMask;
-  for (Index = 0; Index < BitMaskSize; Index++) {
-    if (((*(Data1++)) & (*(Data2++))) != 0) {
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-/**
-  Checks and adjusts CPU features order per dependency relationship.
-
-  @param[in]  FeatureList        Pointer to CPU feature list
-**/
-VOID
-CheckCpuFeaturesDependency (
-  IN LIST_ENTRY              *FeatureList
-  )
-{
-  LIST_ENTRY                 *CurrentEntry;
-  CPU_FEATURES_ENTRY         *CpuFeature;
-  LIST_ENTRY                 *CheckEntry;
-  CPU_FEATURES_ENTRY         *CheckFeature;
-  BOOLEAN                    Swapped;
-  LIST_ENTRY                 *TempEntry;
-
-  CurrentEntry = GetFirstNode (FeatureList);
-  while (!IsNull (FeatureList, CurrentEntry)) {
-    Swapped = FALSE;
-    CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
-    if (CpuFeature->BeforeAll) {
-      //
-      // Check all features dispatched before this entry
-      //
-      CheckEntry = GetFirstNode (FeatureList);
-      while (CheckEntry != CurrentEntry) {
-        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
-        if (!CheckFeature->BeforeAll) {
-          //
-          // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
-          // insert currentEntry before Checked feature
-          //
-          RemoveEntryList (CurrentEntry);
-          InsertTailList (CheckEntry, CurrentEntry);
-          Swapped = TRUE;
-          break;
-        }
-        CheckEntry = CheckEntry->ForwardLink;
-      }
-      if (Swapped) {
-        continue;
-      }
-    }
-
-    if (CpuFeature->AfterAll) {
-      //
-      // Check all features dispatched after this entry
-      //
-      CheckEntry = GetNextNode (FeatureList, CurrentEntry);
-      while (!IsNull (FeatureList, CheckEntry)) {
-        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
-        if (!CheckFeature->AfterAll) {
-          //
-          // If this feature has no AfterAll flag and is dispatched after CpuFeature,
-          // insert currentEntry after Checked feature
-          //
-          TempEntry = GetNextNode (FeatureList, CurrentEntry);
-          RemoveEntryList (CurrentEntry);
-          InsertHeadList (CheckEntry, CurrentEntry);
-          CurrentEntry = TempEntry;
-          Swapped = TRUE;
-          break;
-        }
-        CheckEntry = CheckEntry->ForwardLink;
-      }
-      if (Swapped) {
-        continue;
-      }
-    }
-
-    if (CpuFeature->BeforeFeatureBitMask != NULL) {
-      //
-      // Check all features dispatched before this entry
-      //
-      CheckEntry = GetFirstNode (FeatureList);
-      while (CheckEntry != CurrentEntry) {
-        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
-        if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {
-          //
-          // If there is dependency, swap them
-          //
-          RemoveEntryList (CurrentEntry);
-          InsertTailList (CheckEntry, CurrentEntry);
-          Swapped = TRUE;
-          break;
-        }
-        CheckEntry = CheckEntry->ForwardLink;
-      }
-      if (Swapped) {
-        continue;
-      }
-    }
-
-    if (CpuFeature->AfterFeatureBitMask != NULL) {
-      //
-      // Check all features dispatched after this entry
-      //
-      CheckEntry = GetNextNode (FeatureList, CurrentEntry);
-      while (!IsNull (FeatureList, CheckEntry)) {
-        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
-        if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {
-          //
-          // If there is dependency, swap them
-          //
-          TempEntry = GetNextNode (FeatureList, CurrentEntry);
-          RemoveEntryList (CurrentEntry);
-          InsertHeadList (CheckEntry, CurrentEntry);
-          CurrentEntry = TempEntry;
-          Swapped = TRUE;
-          break;
-        }
-        CheckEntry = CheckEntry->ForwardLink;
-      }
-      if (Swapped) {
-        continue;
-      }
-    }
-    //
-    // No swap happened, check the next feature
-    //
-    CurrentEntry = CurrentEntry->ForwardLink;
-  }
-}
-
-/**
-  Worker function to register CPU Feature.
-
-  @param[in]  CpuFeature            Pointer to CPU feature entry
-
-  @retval  RETURN_SUCCESS           The CPU feature was successfully registered.
-  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources to register
-                                    the CPU feature.
-  @retval  RETURN_UNSUPPORTED       Registration of the CPU feature is not
-                                    supported due to a circular dependency between
-                                    BEFORE and AFTER features.
-**/
-RETURN_STATUS
-RegisterCpuFeatureWorker (
-  IN CPU_FEATURES_ENTRY      *CpuFeature
-  )
-{
-  EFI_STATUS                 Status;
-  CPU_FEATURES_DATA          *CpuFeaturesData;
-  CPU_FEATURES_ENTRY         *CpuFeatureEntry;
-  LIST_ENTRY                 *Entry;
-  UINT32                     BitMaskSize;
-  BOOLEAN                    FeatureExist;
-
-  BitMaskSize     = PcdGetSize (PcdCpuFeaturesSupport);
-  CpuFeaturesData = GetCpuFeaturesData ();
-  if (CpuFeaturesData->FeaturesCount == 0) {
-    InitializeListHead (&CpuFeaturesData->FeatureList);
-    InitializeSpinLock (&CpuFeaturesData->MsrLock);
-    InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);
-    CpuFeaturesData->BitMaskSize = BitMaskSize;
-  }
-  ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);
-
-  FeatureExist = FALSE;
-  CpuFeatureEntry = NULL;
-  Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
-  while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
-    CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
-    if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {
-      //
-      // If this feature already registered
-      //
-      FeatureExist = TRUE;
-      break;
-    }
-    Entry = Entry->ForwardLink;
-  }
-
-  if (!FeatureExist) {
-    DEBUG ((DEBUG_INFO, "[NEW] "));
-    DumpCpuFeature (CpuFeature);
-    InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
-    CpuFeaturesData->FeaturesCount++;
-  } else {
-    DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
-    DumpCpuFeature (CpuFeature);
-    ASSERT (CpuFeatureEntry != NULL);
-    //
-    // Overwrite original parameters of CPU feature
-    //
-    if (CpuFeature->GetConfigDataFunc != NULL) {
-      CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
-    }
-    if (CpuFeature->SupportFunc != NULL) {
-      CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
-    }
-    if (CpuFeature->InitializeFunc != NULL) {
-      CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
-    }
-    if (CpuFeature->FeatureName != NULL) {
-      if (CpuFeatureEntry->FeatureName == NULL) {
-        CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
-        ASSERT (CpuFeatureEntry->FeatureName != NULL);
-      }
-      Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
-      ASSERT_EFI_ERROR (Status);
-      FreePool (CpuFeature->FeatureName);
-    }
-    if (CpuFeature->BeforeFeatureBitMask != NULL) {
-      if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
-        FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
-      }
-      CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
-    }
-    if (CpuFeature->AfterFeatureBitMask != NULL) {
-      if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
-        FreePool (CpuFeatureEntry->AfterFeatureBitMask);
-      }
-      CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
-    }
-    CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
-    CpuFeatureEntry->AfterAll  = CpuFeature->AfterAll;
-
-    FreePool (CpuFeature->FeatureMask);
-    FreePool (CpuFeature);
-  }
-  //
-  // Verify CPU features dependency can change CPU feature order
-  //
-  CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
-  return RETURN_SUCCESS;
-}
-
-/**
-  Sets CPU feature bit mask in CPU feature bit mask buffer.
-
-  @param[in]  FeaturesBitMask       Pointer to CPU feature bit mask buffer
-  @param[in]  Feature               The bit number of the CPU feature
-  @param[in]  BitMaskSize           CPU feature bit mask buffer size
-**/
-VOID
-SetCpuFeaturesBitMask (
-  IN UINT8               **FeaturesBitMask,
-  IN UINT32              Feature,
-  IN UINTN               BitMaskSize
-  )
-{
-  UINT8                  *CpuFeaturesBitMask;
-
-  ASSERT (FeaturesBitMask != NULL);
-  CpuFeaturesBitMask = *FeaturesBitMask;
-  if (CpuFeaturesBitMask == NULL) {
-    CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
-    ASSERT (CpuFeaturesBitMask != NULL);
-    *FeaturesBitMask = CpuFeaturesBitMask;
-  }
-
-  CpuFeaturesBitMask  += (Feature / 8);
-  *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
-}
-
-/**
-  Registers a CPU Feature.
-
-  @param[in]  FeatureName        A Null-terminated Ascii string indicates CPU feature
-                                 name.
-  @param[in]  GetConfigDataFunc  CPU feature get configuration data function.  This
-                                 is an optional parameter that may be NULL.  If NULL,
-                                 then the most recently registered function for the
-                                 CPU feature is used.  If no functions are registered
-                                 for a CPU feature, then the CPU configuration data
-                                 for the registered feature is NULL.
-  @param[in]  SupportFunc        CPU feature support function.  This is an optional
-                                 parameter that may be NULL.  If NULL, then the most
-                                 recently registered function for the CPU feature is
-                                 used. If no functions are registered for a CPU
-                                 feature, then the CPU feature is assumed to be
-                                 supported by all CPUs.
-  @param[in]  InitializeFunc     CPU feature initialize function.  This is an optional
-                                 parameter that may be NULL.  If NULL, then the most
-                                 recently registered function for the CPU feature is
-                                 used. If no functions are registered for a CPU
-                                 feature, then the CPU feature initialization is
-                                 skipped.
-  @param[in]  ...                Variable argument list of UINT32 CPU feature value.
-                                 Values with no modifiers are the features provided
-                                 by the registered functions.
-                                 Values with CPU_FEATURE_BEFORE modifier are features
-                                 that must be initialized after the features provided
-                                 by the registered functions are used.
-                                 Values with CPU_FEATURE_AFTER modifier are features
-                                 that must be initialized before the features provided
-                                 by the registered functions are used.
-                                 The last argument in this variable argument list must
-                                 always be CPU_FEATURE_END.
-
-  @retval  RETURN_SUCCESS           The CPU feature was successfully registered.
-  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources to register
-                                    the CPU feature.
-  @retval  RETURN_UNSUPPORTED       Registration of the CPU feature is not
-                                    supported due to a circular dependency between
-                                    BEFORE and AFTER features.
-
-  @note This service could be called by BSP only.
-**/
-RETURN_STATUS
-EFIAPI
-RegisterCpuFeature (
-  IN CHAR8                             *FeatureName,       OPTIONAL
-  IN CPU_FEATURE_GET_CONFIG_DATA       GetConfigDataFunc,  OPTIONAL
-  IN CPU_FEATURE_SUPPORT               SupportFunc,        OPTIONAL
-  IN CPU_FEATURE_INITIALIZE            InitializeFunc,     OPTIONAL
-  ...
-  )
-{
-  EFI_STATUS                 Status;
-  VA_LIST                    Marker;
-  UINT32                     Feature;
-  UINTN                      BitMaskSize;
-  CPU_FEATURES_ENTRY         *CpuFeature;
-  UINT8                      *FeatureMask;
-  UINT8                      *BeforeFeatureBitMask;
-  UINT8                      *AfterFeatureBitMask;
-  BOOLEAN                    BeforeAll;
-  BOOLEAN                    AfterAll;
-
-  FeatureMask          = NULL;
-  BeforeFeatureBitMask = NULL;
-  AfterFeatureBitMask  = NULL;
-  BeforeAll            = FALSE;
-  AfterAll             = FALSE;
-
-  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
-
-  VA_START (Marker, InitializeFunc);
-  Feature = VA_ARG (Marker, UINT32);
-  while (Feature != CPU_FEATURE_END) {
-    ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))
-                    != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));
-    ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))
-                    != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));
-    if (Feature < CPU_FEATURE_BEFORE) {
-      BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;
-      AfterAll  = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;
-      Feature  &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
-      ASSERT (FeatureMask == NULL);
-      SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);
-    } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {
-      SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);
-    } else if ((Feature & CPU_FEATURE_AFTER) != 0) {
-      SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);
-    }
-    Feature = VA_ARG (Marker, UINT32);
-  }
-  VA_END (Marker);
-
-  CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));
-  ASSERT (CpuFeature != NULL);
-  CpuFeature->Signature            = CPU_FEATURE_ENTRY_SIGNATURE;
-  CpuFeature->FeatureMask          = FeatureMask;
-  CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;
-  CpuFeature->AfterFeatureBitMask  = AfterFeatureBitMask;
-  CpuFeature->BeforeAll            = BeforeAll;
-  CpuFeature->AfterAll             = AfterAll;
-  CpuFeature->GetConfigDataFunc    = GetConfigDataFunc;
-  CpuFeature->SupportFunc          = SupportFunc;
-  CpuFeature->InitializeFunc       = InitializeFunc;
-  if (FeatureName != NULL) {
-    CpuFeature->FeatureName          = AllocatePool (CPU_FEATURE_NAME_SIZE);
-    ASSERT (CpuFeature->FeatureName != NULL);
-    Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);
-    ASSERT_EFI_ERROR (Status);
-  }
-
-  Status = RegisterCpuFeatureWorker (CpuFeature);
-  ASSERT_EFI_ERROR (Status);
-
-  return RETURN_SUCCESS;
-}
-
-/**
-  Add an entry in specified register table.
-
-  This function adds an entry in specified register table, with given register type,
-  register index, bit section and value.
-
-  @param[in]  PreSmmFlag       If TRUE, entry will be added into PreSmm register table
-                               If FALSE, entry will be added into register table
-  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry
-  @param[in]  RegisterType     Type of the register to program
-  @param[in]  Index            Index of the register to program
-  @param[in]  ValidBitStart    Start of the bit section
-  @param[in]  ValidBitLength   Length of the bit section
-  @param[in]  Value            Value to write
-**/
-VOID
-CpuRegisterTableWriteWorker (
-  IN BOOLEAN                 PreSmmFlag,
-  IN UINTN                   ProcessorNumber,
-  IN REGISTER_TYPE           RegisterType,
-  IN UINT64                  Index,
-  IN UINT8                   ValidBitStart,
-  IN UINT8                   ValidBitLength,
-  IN UINT64                  Value
-  )
-{
-  EFI_STATUS               Status;
-  CPU_FEATURES_DATA        *CpuFeaturesData;
-  ACPI_CPU_DATA            *AcpiCpuData;
-  CPU_REGISTER_TABLE       *RegisterTable;
-  CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
-
-  CpuFeaturesData = GetCpuFeaturesData ();
-  if (CpuFeaturesData->RegisterTable == NULL) {
-    AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
-    if (AcpiCpuData == NULL) {
-      AcpiCpuData = AllocateAcpiCpuData ();
-      ASSERT (AcpiCpuData != NULL);
-      //
-      // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
-      //
-      Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
-      ASSERT_EFI_ERROR (Status);
-    }
-    ASSERT (AcpiCpuData->RegisterTable != 0);
-    CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;
-    CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;
-  }
-
-  if (PreSmmFlag) {
-    RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
-  } else {
-    RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
-  }
-
-  if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
-    EnlargeRegisterTable (RegisterTable);
-  }
-
-  //
-  // Append entry in the register table.
-  //
-  RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
-  RegisterTableEntry[RegisterTable->TableLength].RegisterType   = RegisterType;
-  RegisterTableEntry[RegisterTable->TableLength].Index          = (UINT32) Index;
-  RegisterTableEntry[RegisterTable->TableLength].HighIndex      = (UINT32) RShiftU64 (Index, 32);
-  RegisterTableEntry[RegisterTable->TableLength].ValidBitStart  = ValidBitStart;
-  RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
-  RegisterTableEntry[RegisterTable->TableLength].Value          = Value;
-
-  RegisterTable->TableLength++;
-}
-
-/**
-  Adds an entry in specified register table.
-
-  This function adds an entry in specified register table, with given register type,
-  register index, bit section and value.
-
-  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry
-  @param[in]  RegisterType     Type of the register to program
-  @param[in]  Index            Index of the register to program
-  @param[in]  ValueMask        Mask of bits in register to write
-  @param[in]  Value            Value to write
-
-  @note This service could be called by BSP only.
-**/
-VOID
-EFIAPI
-CpuRegisterTableWrite (
-  IN UINTN               ProcessorNumber,
-  IN REGISTER_TYPE       RegisterType,
-  IN UINT64              Index,
-  IN UINT64              ValueMask,
-  IN UINT64              Value
-  )
-{
-  UINT8                   Start;
-  UINT8                   End;
-  UINT8                   Length;
-
-  Start  = (UINT8)LowBitSet64  (ValueMask);
-  End    = (UINT8)HighBitSet64 (ValueMask);
-  Length = End - Start + 1;
-  CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
-}
-
-/**
-  Adds an entry in specified Pre-SMM register table.
-
-  This function adds an entry in specified register table, with given register type,
-  register index, bit section and value.
-
-  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
-  @param[in]  RegisterType     Type of the register to program
-  @param[in]  Index            Index of the register to program
-  @param[in]  ValueMask        Mask of bits in register to write
-  @param[in]  Value            Value to write
-
-  @note This service could be called by BSP only.
-**/
-VOID
-EFIAPI
-PreSmmCpuRegisterTableWrite (
-  IN UINTN               ProcessorNumber,
-  IN REGISTER_TYPE       RegisterType,
-  IN UINT64              Index,
-  IN UINT64              ValueMask,
-  IN UINT64              Value
-  )
-{
-  UINT8  Start;
-  UINT8  End;
-  UINT8  Length;
-
-  Start  = (UINT8)LowBitSet64  (ValueMask);
-  End    = (UINT8)HighBitSet64 (ValueMask);
-  Length = End - Start + 1;
-  CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
-}
-
-/**
-  Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
-
-  @param[in]  CpuBitMask      CPU feature bit mask buffer
-  @param[in]  CpuBitMaskSize  The size of CPU feature bit mask buffer
-  @param[in]  Feature         The bit number of the CPU feature
-
-  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSupport.
-  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSupport.
-
-**/
-BOOLEAN
-IsCpuFeatureSetInCpuPcd (
-  IN UINT8               *CpuBitMask,
-  IN UINTN               CpuBitMaskSize,
-  IN UINT32              Feature
-  )
-{
-  if ((Feature >> 3) >= CpuBitMaskSize) {
-    return FALSE;
-  }
-  return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
-}
-
-/**
-  Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
-  If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
-  associated with that feature should be optimized away if compiler
-  optimizations are enabled.
-
-  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
-                       PcdCpuFeaturesSupport
-
-  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSupport.
-  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSupport.
-
-  @note This service could be called by BSP only.
-**/
-BOOLEAN
-EFIAPI
-IsCpuFeatureSupported (
-  IN UINT32              Feature
-  )
-{
-  return IsCpuFeatureSetInCpuPcd (
-           (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
-           PcdGetSize (PcdCpuFeaturesSupport),
-           Feature
-           );
-}
-
-/**
-  Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
-
-  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
-                       PcdCpuFeaturesSetting
-
-  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSetting.
-  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSetting.
-
-  @note This service could be called by BSP only.
-**/
-BOOLEAN
-EFIAPI
-IsCpuFeatureInSetting (
-  IN UINT32              Feature
-  )
-{
-  return IsCpuFeatureSetInCpuPcd (
-           (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
-           PcdGetSize (PcdCpuFeaturesSetting),
-           Feature
-           );
-}
-
-/**
-  Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
-
-  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
-                       PcdCpuFeaturesCapability
-
-  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesCapability.
-  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesCapability.
-
-  @note This service could be called by BSP only.
-**/
-BOOLEAN
-EFIAPI
-IsCpuFeatureCapability (
-  IN UINT32              Feature
-  )
-{
-  return IsCpuFeatureSetInCpuPcd (
-           (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
-           PcdGetSize (PcdCpuFeaturesCapability),
-           Feature
-           );
-
-}
-
-/**
-  Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
-
-  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
-                       PcdCpuFeaturesUserConfiguration
-
-  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesUserConfiguration.
-  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
-
-  @note This service could be called by BSP only.
-**/
-BOOLEAN
-EFIAPI
-IsCpuFeatureUserConfiguration (
-  IN UINT32              Feature
-  )
-{
-  return IsCpuFeatureSetInCpuPcd (
-           (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
-           PcdGetSize (PcdCpuFeaturesUserConfiguration),
-           Feature
-           );
-
-}
-
-/**
-  Switches to assigned BSP after CPU features initialization.
-
-  @param[in]  ProcessorNumber  The index of the CPU executing this function.
-
-  @note This service could be called by BSP only.
-**/
-VOID
-EFIAPI
-SwitchBspAfterFeaturesInitialize (
-  IN UINTN               ProcessorNumber
-  )
-{
-  CPU_FEATURES_DATA      *CpuFeaturesData;
-
-  CpuFeaturesData = GetCpuFeaturesData ();
-  CpuFeaturesData->BspNumber = ProcessorNumber;
-}
-
+/** @file\r
+  CPU Register Table Library functions.\r
+\r
+  Copyright (c) 2017, 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 "RegisterCpuFeatures.h"\r
+\r
+/**\r
+  Checks if two CPU feature bit masks are equal.\r
+\r
+  @param[in]  FirstFeatureMask  The first input CPU feature bit mask\r
+  @param[in]  SecondFeatureMask The second input CPU feature bit mask\r
+\r
+  @retval TRUE  Two CPU feature bit masks are equal.\r
+  @retval FALSE Two CPU feature bit masks are not equal.\r
+**/\r
+BOOLEAN\r
+IsCpuFeatureMatch (\r
+  IN UINT8               *FirstFeatureMask,\r
+  IN UINT8               *SecondFeatureMask\r
+  )\r
+{\r
+  UINTN                 BitMaskSize;\r
+\r
+  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
+  if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.\r
+\r
+  @param[in]  FeatureMask  A pointer to the CPU feature bit mask.\r
+**/\r
+VOID\r
+DumpCpuFeatureMask (\r
+  IN UINT8               *FeatureMask\r
+  )\r
+{\r
+  UINTN                  Index;\r
+  UINT8                  *Data8;\r
+  UINTN                  BitMaskSize;\r
+\r
+  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
+  Data8       = (UINT8 *) FeatureMask;\r
+  for (Index = 0; Index < BitMaskSize; Index++) {\r
+    DEBUG ((DEBUG_INFO, " %02x ", *Data8++));\r
+  }\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/**\r
+  Dump CPU feature name or CPU feature bit mask.\r
+\r
+  @param[in]  CpuFeature   Pointer to CPU_FEATURES_ENTRY\r
+**/\r
+VOID\r
+DumpCpuFeature (\r
+  IN CPU_FEATURES_ENTRY  *CpuFeature\r
+  )\r
+{\r
+\r
+  if (CpuFeature->FeatureName != NULL) {\r
+    DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName));\r
+  } else {\r
+    DEBUG ((DEBUG_INFO, "FeatureMask = "));\r
+    DumpCpuFeatureMask (CpuFeature->FeatureMask);\r
+  }\r
+}\r
+\r
+/**\r
+  Determines if the feature bit mask is in dependent CPU feature bit mask buffer.\r
+\r
+  @param[in]  FeatureMask        Pointer to CPU feature bit mask\r
+  @param[in]  DependentBitMask   Pointer to dependent CPU feature bit mask buffer\r
+\r
+  @retval TRUE  The feature bit mask is in dependent CPU feature bit mask buffer.\r
+  @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.\r
+**/\r
+BOOLEAN\r
+IsBitMaskMatchCheck (\r
+  IN UINT8        *FeatureMask,\r
+  IN UINT8        *DependentBitMask\r
+  )\r
+{\r
+  UINTN      Index;\r
+  UINTN      BitMaskSize;\r
+  UINT8      *Data1;\r
+  UINT8      *Data2;\r
+\r
+  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
+\r
+  Data1 = FeatureMask;\r
+  Data2 = DependentBitMask;\r
+  for (Index = 0; Index < BitMaskSize; Index++) {\r
+    if (((*(Data1++)) & (*(Data2++))) != 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Checks and adjusts CPU features order per dependency relationship.\r
+\r
+  @param[in]  FeatureList        Pointer to CPU feature list\r
+**/\r
+VOID\r
+CheckCpuFeaturesDependency (\r
+  IN LIST_ENTRY              *FeatureList\r
+  )\r
+{\r
+  LIST_ENTRY                 *CurrentEntry;\r
+  CPU_FEATURES_ENTRY         *CpuFeature;\r
+  LIST_ENTRY                 *CheckEntry;\r
+  CPU_FEATURES_ENTRY         *CheckFeature;\r
+  BOOLEAN                    Swapped;\r
+  LIST_ENTRY                 *TempEntry;\r
+\r
+  CurrentEntry = GetFirstNode (FeatureList);\r
+  while (!IsNull (FeatureList, CurrentEntry)) {\r
+    Swapped = FALSE;\r
+    CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
+    if (CpuFeature->BeforeAll) {\r
+      //\r
+      // Check all features dispatched before this entry\r
+      //\r
+      CheckEntry = GetFirstNode (FeatureList);\r
+      while (CheckEntry != CurrentEntry) {\r
+        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+        if (!CheckFeature->BeforeAll) {\r
+          //\r
+          // If this feature has no BeforeAll flag and is dispatched before CpuFeature,\r
+          // insert currentEntry before Checked feature\r
+          //\r
+          RemoveEntryList (CurrentEntry);\r
+          InsertTailList (CheckEntry, CurrentEntry);\r
+          Swapped = TRUE;\r
+          break;\r
+        }\r
+        CheckEntry = CheckEntry->ForwardLink;\r
+      }\r
+      if (Swapped) {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    if (CpuFeature->AfterAll) {\r
+      //\r
+      // Check all features dispatched after this entry\r
+      //\r
+      CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
+      while (!IsNull (FeatureList, CheckEntry)) {\r
+        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+        if (!CheckFeature->AfterAll) {\r
+          //\r
+          // If this feature has no AfterAll flag and is dispatched after CpuFeature,\r
+          // insert currentEntry after Checked feature\r
+          //\r
+          TempEntry = GetNextNode (FeatureList, CurrentEntry);\r
+          RemoveEntryList (CurrentEntry);\r
+          InsertHeadList (CheckEntry, CurrentEntry);\r
+          CurrentEntry = TempEntry;\r
+          Swapped = TRUE;\r
+          break;\r
+        }\r
+        CheckEntry = CheckEntry->ForwardLink;\r
+      }\r
+      if (Swapped) {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
+      //\r
+      // Check all features dispatched before this entry\r
+      //\r
+      CheckEntry = GetFirstNode (FeatureList);\r
+      while (CheckEntry != CurrentEntry) {\r
+        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+        if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {\r
+          //\r
+          // If there is dependency, swap them\r
+          //\r
+          RemoveEntryList (CurrentEntry);\r
+          InsertTailList (CheckEntry, CurrentEntry);\r
+          Swapped = TRUE;\r
+          break;\r
+        }\r
+        CheckEntry = CheckEntry->ForwardLink;\r
+      }\r
+      if (Swapped) {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    if (CpuFeature->AfterFeatureBitMask != NULL) {\r
+      //\r
+      // Check all features dispatched after this entry\r
+      //\r
+      CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
+      while (!IsNull (FeatureList, CheckEntry)) {\r
+        CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+        if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {\r
+          //\r
+          // If there is dependency, swap them\r
+          //\r
+          TempEntry = GetNextNode (FeatureList, CurrentEntry);\r
+          RemoveEntryList (CurrentEntry);\r
+          InsertHeadList (CheckEntry, CurrentEntry);\r
+          CurrentEntry = TempEntry;\r
+          Swapped = TRUE;\r
+          break;\r
+        }\r
+        CheckEntry = CheckEntry->ForwardLink;\r
+      }\r
+      if (Swapped) {\r
+        continue;\r
+      }\r
+    }\r
+    //\r
+    // No swap happened, check the next feature\r
+    //\r
+    CurrentEntry = CurrentEntry->ForwardLink;\r
+  }\r
+}\r
+\r
+/**\r
+  Worker function to register CPU Feature.\r
+\r
+  @param[in]  CpuFeature            Pointer to CPU feature entry\r
+\r
+  @retval  RETURN_SUCCESS           The CPU feature was successfully registered.\r
+  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources to register\r
+                                    the CPU feature.\r
+  @retval  RETURN_UNSUPPORTED       Registration of the CPU feature is not\r
+                                    supported due to a circular dependency between\r
+                                    BEFORE and AFTER features.\r
+**/\r
+RETURN_STATUS\r
+RegisterCpuFeatureWorker (\r
+  IN CPU_FEATURES_ENTRY      *CpuFeature\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  CPU_FEATURES_DATA          *CpuFeaturesData;\r
+  CPU_FEATURES_ENTRY         *CpuFeatureEntry;\r
+  LIST_ENTRY                 *Entry;\r
+  UINTN                      BitMaskSize;\r
+  BOOLEAN                    FeatureExist;\r
+\r
+  BitMaskSize     = PcdGetSize (PcdCpuFeaturesSupport);\r
+  CpuFeaturesData = GetCpuFeaturesData ();\r
+  if (CpuFeaturesData->FeaturesCount == 0) {\r
+    InitializeListHead (&CpuFeaturesData->FeatureList);\r
+    InitializeSpinLock (&CpuFeaturesData->MsrLock);\r
+    InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
+    CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;\r
+  }\r
+  ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);\r
+\r
+  FeatureExist = FALSE;\r
+  CpuFeatureEntry = NULL;\r
+  Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
+  while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
+    CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
+    if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {\r
+      //\r
+      // If this feature already registered\r
+      //\r
+      FeatureExist = TRUE;\r
+      break;\r
+    }\r
+    Entry = Entry->ForwardLink;\r
+  }\r
+\r
+  if (!FeatureExist) {\r
+    DEBUG ((DEBUG_INFO, "[NEW] "));\r
+    DumpCpuFeature (CpuFeature);\r
+    InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);\r
+    CpuFeaturesData->FeaturesCount++;\r
+  } else {\r
+    DEBUG ((DEBUG_INFO, "[OVERRIDE] "));\r
+    DumpCpuFeature (CpuFeature);\r
+    ASSERT (CpuFeatureEntry != NULL);\r
+    //\r
+    // Overwrite original parameters of CPU feature\r
+    //\r
+    if (CpuFeature->GetConfigDataFunc != NULL) {\r
+      CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;\r
+    }\r
+    if (CpuFeature->SupportFunc != NULL) {\r
+      CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;\r
+    }\r
+    if (CpuFeature->InitializeFunc != NULL) {\r
+      CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;\r
+    }\r
+    if (CpuFeature->FeatureName != NULL) {\r
+      if (CpuFeatureEntry->FeatureName == NULL) {\r
+        CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
+        ASSERT (CpuFeatureEntry->FeatureName != NULL);\r
+      }\r
+      Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);\r
+      ASSERT_EFI_ERROR (Status);\r
+      FreePool (CpuFeature->FeatureName);\r
+    }\r
+    if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
+      if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {\r
+        FreePool (CpuFeatureEntry->BeforeFeatureBitMask);\r
+      }\r
+      CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;\r
+    }\r
+    if (CpuFeature->AfterFeatureBitMask != NULL) {\r
+      if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {\r
+        FreePool (CpuFeatureEntry->AfterFeatureBitMask);\r
+      }\r
+      CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;\r
+    }\r
+    CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;\r
+    CpuFeatureEntry->AfterAll  = CpuFeature->AfterAll;\r
+\r
+    FreePool (CpuFeature->FeatureMask);\r
+    FreePool (CpuFeature);\r
+  }\r
+  //\r
+  // Verify CPU features dependency can change CPU feature order\r
+  //\r
+  CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Sets CPU feature bit mask in CPU feature bit mask buffer.\r
+\r
+  @param[in]  FeaturesBitMask       Pointer to CPU feature bit mask buffer\r
+  @param[in]  Feature               The bit number of the CPU feature\r
+  @param[in]  BitMaskSize           CPU feature bit mask buffer size\r
+**/\r
+VOID\r
+SetCpuFeaturesBitMask (\r
+  IN UINT8               **FeaturesBitMask,\r
+  IN UINT32              Feature,\r
+  IN UINTN               BitMaskSize\r
+  )\r
+{\r
+  UINT8                  *CpuFeaturesBitMask;\r
+\r
+  ASSERT (FeaturesBitMask != NULL);\r
+  CpuFeaturesBitMask = *FeaturesBitMask;\r
+  if (CpuFeaturesBitMask == NULL) {\r
+    CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);\r
+    ASSERT (CpuFeaturesBitMask != NULL);\r
+    *FeaturesBitMask = CpuFeaturesBitMask;\r
+  }\r
+\r
+  CpuFeaturesBitMask  += (Feature / 8);\r
+  *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));\r
+}\r
+\r
+/**\r
+  Registers a CPU Feature.\r
+\r
+  @param[in]  FeatureName        A Null-terminated Ascii string indicates CPU feature\r
+                                 name.\r
+  @param[in]  GetConfigDataFunc  CPU feature get configuration data function.  This\r
+                                 is an optional parameter that may be NULL.  If NULL,\r
+                                 then the most recently registered function for the\r
+                                 CPU feature is used.  If no functions are registered\r
+                                 for a CPU feature, then the CPU configuration data\r
+                                 for the registered feature is NULL.\r
+  @param[in]  SupportFunc        CPU feature support function.  This is an optional\r
+                                 parameter that may be NULL.  If NULL, then the most\r
+                                 recently registered function for the CPU feature is\r
+                                 used. If no functions are registered for a CPU\r
+                                 feature, then the CPU feature is assumed to be\r
+                                 supported by all CPUs.\r
+  @param[in]  InitializeFunc     CPU feature initialize function.  This is an optional\r
+                                 parameter that may be NULL.  If NULL, then the most\r
+                                 recently registered function for the CPU feature is\r
+                                 used. If no functions are registered for a CPU\r
+                                 feature, then the CPU feature initialization is\r
+                                 skipped.\r
+  @param[in]  ...                Variable argument list of UINT32 CPU feature value.\r
+                                 Values with no modifiers are the features provided\r
+                                 by the registered functions.\r
+                                 Values with CPU_FEATURE_BEFORE modifier are features\r
+                                 that must be initialized after the features provided\r
+                                 by the registered functions are used.\r
+                                 Values with CPU_FEATURE_AFTER modifier are features\r
+                                 that must be initialized before the features provided\r
+                                 by the registered functions are used.\r
+                                 The last argument in this variable argument list must\r
+                                 always be CPU_FEATURE_END.\r
+\r
+  @retval  RETURN_SUCCESS           The CPU feature was successfully registered.\r
+  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources to register\r
+                                    the CPU feature.\r
+  @retval  RETURN_UNSUPPORTED       Registration of the CPU feature is not\r
+                                    supported due to a circular dependency between\r
+                                    BEFORE and AFTER features.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+RegisterCpuFeature (\r
+  IN CHAR8                             *FeatureName,       OPTIONAL\r
+  IN CPU_FEATURE_GET_CONFIG_DATA       GetConfigDataFunc,  OPTIONAL\r
+  IN CPU_FEATURE_SUPPORT               SupportFunc,        OPTIONAL\r
+  IN CPU_FEATURE_INITIALIZE            InitializeFunc,     OPTIONAL\r
+  ...\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  VA_LIST                    Marker;\r
+  UINT32                     Feature;\r
+  UINTN                      BitMaskSize;\r
+  CPU_FEATURES_ENTRY         *CpuFeature;\r
+  UINT8                      *FeatureMask;\r
+  UINT8                      *BeforeFeatureBitMask;\r
+  UINT8                      *AfterFeatureBitMask;\r
+  BOOLEAN                    BeforeAll;\r
+  BOOLEAN                    AfterAll;\r
+\r
+  FeatureMask          = NULL;\r
+  BeforeFeatureBitMask = NULL;\r
+  AfterFeatureBitMask  = NULL;\r
+  BeforeAll            = FALSE;\r
+  AfterAll             = FALSE;\r
+\r
+  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
+\r
+  VA_START (Marker, InitializeFunc);\r
+  Feature = VA_ARG (Marker, UINT32);\r
+  while (Feature != CPU_FEATURE_END) {\r
+    ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))\r
+                    != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));\r
+    ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))\r
+                    != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));\r
+    if (Feature < CPU_FEATURE_BEFORE) {\r
+      BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;\r
+      AfterAll  = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;\r
+      Feature  &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);\r
+      ASSERT (FeatureMask == NULL);\r
+      SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);\r
+    } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {\r
+      SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);\r
+    } else if ((Feature & CPU_FEATURE_AFTER) != 0) {\r
+      SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);\r
+    }\r
+    Feature = VA_ARG (Marker, UINT32);\r
+  }\r
+  VA_END (Marker);\r
+\r
+  CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));\r
+  ASSERT (CpuFeature != NULL);\r
+  CpuFeature->Signature            = CPU_FEATURE_ENTRY_SIGNATURE;\r
+  CpuFeature->FeatureMask          = FeatureMask;\r
+  CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r
+  CpuFeature->AfterFeatureBitMask  = AfterFeatureBitMask;\r
+  CpuFeature->BeforeAll            = BeforeAll;\r
+  CpuFeature->AfterAll             = AfterAll;\r
+  CpuFeature->GetConfigDataFunc    = GetConfigDataFunc;\r
+  CpuFeature->SupportFunc          = SupportFunc;\r
+  CpuFeature->InitializeFunc       = InitializeFunc;\r
+  if (FeatureName != NULL) {\r
+    CpuFeature->FeatureName          = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
+    ASSERT (CpuFeature->FeatureName != NULL);\r
+    Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  Status = RegisterCpuFeatureWorker (CpuFeature);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Add an entry in specified register table.\r
+\r
+  This function adds an entry in specified register table, with given register type,\r
+  register index, bit section and value.\r
+\r
+  @param[in]  PreSmmFlag       If TRUE, entry will be added into PreSmm register table\r
+                               If FALSE, entry will be added into register table\r
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry\r
+  @param[in]  RegisterType     Type of the register to program\r
+  @param[in]  Index            Index of the register to program\r
+  @param[in]  ValidBitStart    Start of the bit section\r
+  @param[in]  ValidBitLength   Length of the bit section\r
+  @param[in]  Value            Value to write\r
+**/\r
+VOID\r
+CpuRegisterTableWriteWorker (\r
+  IN BOOLEAN                 PreSmmFlag,\r
+  IN UINTN                   ProcessorNumber,\r
+  IN REGISTER_TYPE           RegisterType,\r
+  IN UINT64                  Index,\r
+  IN UINT8                   ValidBitStart,\r
+  IN UINT8                   ValidBitLength,\r
+  IN UINT64                  Value\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  CPU_FEATURES_DATA        *CpuFeaturesData;\r
+  ACPI_CPU_DATA            *AcpiCpuData;\r
+  CPU_REGISTER_TABLE       *RegisterTable;\r
+  CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
+\r
+  CpuFeaturesData = GetCpuFeaturesData ();\r
+  if (CpuFeaturesData->RegisterTable == NULL) {\r
+    AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
+    if (AcpiCpuData == NULL) {\r
+      AcpiCpuData = AllocateAcpiCpuData ();\r
+      ASSERT (AcpiCpuData != NULL);\r
+      //\r
+      // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
+      //\r
+      Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    ASSERT (AcpiCpuData->RegisterTable != 0);\r
+    CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;\r
+    CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;\r
+  }\r
+\r
+  if (PreSmmFlag) {\r
+    RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];\r
+  } else {\r
+    RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
+  }\r
+\r
+  if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {\r
+    EnlargeRegisterTable (RegisterTable);\r
+  }\r
+\r
+  //\r
+  // Append entry in the register table.\r
+  //\r
+  RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
+  RegisterTableEntry[RegisterTable->TableLength].RegisterType   = RegisterType;\r
+  RegisterTableEntry[RegisterTable->TableLength].Index          = (UINT32) Index;\r
+  RegisterTableEntry[RegisterTable->TableLength].HighIndex      = (UINT32) RShiftU64 (Index, 32);\r
+  RegisterTableEntry[RegisterTable->TableLength].ValidBitStart  = ValidBitStart;\r
+  RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;\r
+  RegisterTableEntry[RegisterTable->TableLength].Value          = Value;\r
+\r
+  RegisterTable->TableLength++;\r
+}\r
+\r
+/**\r
+  Adds an entry in specified register table.\r
+\r
+  This function adds an entry in specified register table, with given register type,\r
+  register index, bit section and value.\r
+\r
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry\r
+  @param[in]  RegisterType     Type of the register to program\r
+  @param[in]  Index            Index of the register to program\r
+  @param[in]  ValueMask        Mask of bits in register to write\r
+  @param[in]  Value            Value to write\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+VOID\r
+EFIAPI\r
+CpuRegisterTableWrite (\r
+  IN UINTN               ProcessorNumber,\r
+  IN REGISTER_TYPE       RegisterType,\r
+  IN UINT64              Index,\r
+  IN UINT64              ValueMask,\r
+  IN UINT64              Value\r
+  )\r
+{\r
+  UINT8                   Start;\r
+  UINT8                   End;\r
+  UINT8                   Length;\r
+\r
+  Start  = (UINT8)LowBitSet64  (ValueMask);\r
+  End    = (UINT8)HighBitSet64 (ValueMask);\r
+  Length = End - Start + 1;\r
+  CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
+}\r
+\r
+/**\r
+  Adds an entry in specified Pre-SMM register table.\r
+\r
+  This function adds an entry in specified register table, with given register type,\r
+  register index, bit section and value.\r
+\r
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.\r
+  @param[in]  RegisterType     Type of the register to program\r
+  @param[in]  Index            Index of the register to program\r
+  @param[in]  ValueMask        Mask of bits in register to write\r
+  @param[in]  Value            Value to write\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+VOID\r
+EFIAPI\r
+PreSmmCpuRegisterTableWrite (\r
+  IN UINTN               ProcessorNumber,\r
+  IN REGISTER_TYPE       RegisterType,\r
+  IN UINT64              Index,\r
+  IN UINT64              ValueMask,\r
+  IN UINT64              Value\r
+  )\r
+{\r
+  UINT8  Start;\r
+  UINT8  End;\r
+  UINT8  Length;\r
+\r
+  Start  = (UINT8)LowBitSet64  (ValueMask);\r
+  End    = (UINT8)HighBitSet64 (ValueMask);\r
+  Length = End - Start + 1;\r
+  CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
+}\r
+\r
+/**\r
+  Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.\r
+\r
+  @param[in]  CpuBitMask      CPU feature bit mask buffer\r
+  @param[in]  CpuBitMaskSize  The size of CPU feature bit mask buffer\r
+  @param[in]  Feature         The bit number of the CPU feature\r
+\r
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSupport.\r
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSupport.\r
+\r
+**/\r
+BOOLEAN\r
+IsCpuFeatureSetInCpuPcd (\r
+  IN UINT8               *CpuBitMask,\r
+  IN UINTN               CpuBitMaskSize,\r
+  IN UINT32              Feature\r
+  )\r
+{\r
+  if ((Feature >> 3) >= CpuBitMaskSize) {\r
+    return FALSE;\r
+  }\r
+  return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);\r
+}\r
+\r
+/**\r
+  Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.\r
+  If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data\r
+  associated with that feature should be optimized away if compiler\r
+  optimizations are enabled.\r
+\r
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD\r
+                       PcdCpuFeaturesSupport\r
+\r
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSupport.\r
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSupport.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsCpuFeatureSupported (\r
+  IN UINT32              Feature\r
+  )\r
+{\r
+  return IsCpuFeatureSetInCpuPcd (\r
+           (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),\r
+           PcdGetSize (PcdCpuFeaturesSupport),\r
+           Feature\r
+           );\r
+}\r
+\r
+/**\r
+  Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.\r
+\r
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD\r
+                       PcdCpuFeaturesSetting\r
+\r
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSetting.\r
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSetting.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsCpuFeatureInSetting (\r
+  IN UINT32              Feature\r
+  )\r
+{\r
+  return IsCpuFeatureSetInCpuPcd (\r
+           (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),\r
+           PcdGetSize (PcdCpuFeaturesSetting),\r
+           Feature\r
+           );\r
+}\r
+\r
+/**\r
+  Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.\r
+\r
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD\r
+                       PcdCpuFeaturesCapability\r
+\r
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesCapability.\r
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesCapability.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsCpuFeatureCapability (\r
+  IN UINT32              Feature\r
+  )\r
+{\r
+  return IsCpuFeatureSetInCpuPcd (\r
+           (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),\r
+           PcdGetSize (PcdCpuFeaturesCapability),\r
+           Feature\r
+           );\r
+\r
+}\r
+\r
+/**\r
+  Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.\r
+\r
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD\r
+                       PcdCpuFeaturesUserConfiguration\r
+\r
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesUserConfiguration.\r
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesUserConfiguration.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsCpuFeatureUserConfiguration (\r
+  IN UINT32              Feature\r
+  )\r
+{\r
+  return IsCpuFeatureSetInCpuPcd (\r
+           (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),\r
+           PcdGetSize (PcdCpuFeaturesUserConfiguration),\r
+           Feature\r
+           );\r
+\r
+}\r
+\r
+/**\r
+  Switches to assigned BSP after CPU features initialization.\r
+\r
+  @param[in]  ProcessorNumber  The index of the CPU executing this function.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+VOID\r
+EFIAPI\r
+SwitchBspAfterFeaturesInitialize (\r
+  IN UINTN               ProcessorNumber\r
+  )\r
+{\r
+  CPU_FEATURES_DATA      *CpuFeaturesData;\r
+\r
+  CpuFeaturesData = GetCpuFeaturesData ();\r
+  CpuFeaturesData->BspNumber = ProcessorNumber;\r
+}\r
+\r