]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Universal/PCD/Pei/Service.c
Make EDK Module Package pass Intel IPF compiler with /Ox switch.
[mirror_edk2.git] / EdkModulePkg / Universal / PCD / Pei / Service.c
index 38293252bc52b4be65e30c5ba28bb041fb6acf88..e705c283cb8be05db457c158abd2cd2edd823400 100644 (file)
@@ -14,799 +14,715 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 Module Name: Service.c\r
 \r
 **/\r
-#include "../Common/PcdCommon.h"\r
 #include "Service.h"\r
 \r
-\r
-\r
-\r
 /**\r
-  This function expand the StateByte\r
+  The function registers the CallBackOnSet fucntion\r
+  according to TokenNumber and EFI_GUID space.\r
 \r
-  @param[out]   StateByte The output StateByte information.\r
-  @param[in]    Byte The StateByte.\r
+  @param  TokenNumber       The token number.\r
+  @param  Guid              The GUID space.\r
+  @param  CallBackFunction  The Callback function to be registered.\r
+  @param  Register          To register or unregister the callback function.\r
 \r
-  @retval       VOID\r
+  @retval EFI_SUCCESS If the Callback function is registered.\r
+  @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
+  @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free\r
+                                slot left in the CallbackFnTable.\r
 --*/\r
-VOID\r
-PcdImageExpandStateByte (\r
-  OUT PCD_STATEBYTE *StateByte,\r
-  IN  UINT8          Byte\r
+EFI_STATUS\r
+PeiRegisterCallBackWorker (\r
+  IN  UINTN                       ExTokenNumber,\r
+  IN  CONST EFI_GUID              *Guid, OPTIONAL\r
+  IN  PCD_PPI_CALLBACK            CallBackFunction,\r
+  IN  BOOLEAN                     Register\r
 )\r
 {\r
-  switch (Byte & PCD_STATEBYTE_DATUMTYPE) {\r
-    case PCD_BYTE8:\r
-      StateByte->DataType = PcdByte8;\r
-      break;\r
-    case PCD_BYTE16:\r
-      StateByte->DataType = PcdByte16;\r
-      break;\r
-    case PCD_BYTE32:\r
-      StateByte->DataType = PcdByte32;\r
-      break;\r
-    case PCD_BYTE64:\r
-      StateByte->DataType = PcdByte64;\r
-      break;\r
-    case PCD_POINTER:\r
-      StateByte->DataType = PcdPointer;\r
-      break;\r
-    case PCD_BOOLEAN:\r
-      StateByte->DataType = PcdBoolean;\r
-      break;\r
-    default:\r
-      ASSERT (FALSE);\r
-  }\r
-\r
-  StateByte->ExtendedGuidPresent = (BOOLEAN) ((Byte & PCD_STATEBYTE_EXTENDEDGUIDPRESENT) != 0);\r
-  StateByte->HiiEnable           = (BOOLEAN) ((Byte & PCD_STATEBYTE_HIIENABLE)           != 0);\r
-  StateByte->SkuDataArrayEnable  = (BOOLEAN) ((Byte & PCD_STATEBYTE_SKUDATAARRAYENABLE)  != 0);\r
-  StateByte->SkuEnable           = (BOOLEAN) ((Byte & PCD_STATEBYTE_SKUENABLE)           != 0);\r
-  StateByte->VpdEnable           = (BOOLEAN) ((Byte & PCD_STATEBYTE_VPDENABLE)           != 0);\r
+  EFI_HOB_GUID_TYPE       *GuidHob;\r
+  PCD_PPI_CALLBACK        *CallbackTable;\r
+  PCD_PPI_CALLBACK        Compare;\r
+  PCD_PPI_CALLBACK        Assign;\r
+  UINT32                  LocalTokenNumber;\r
+  UINTN                   TokenNumber;\r
+  UINTN                   Idx;\r
 \r
-}\r
+  if (Guid == NULL) {\r
+    TokenNumber = ExTokenNumber;\r
 \r
+    //\r
+    // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+    // We have to decrement TokenNumber by 1 to make it usable\r
+    // as the array index.\r
+    //\r
+    TokenNumber--;\r
+    ASSERT (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1);\r
+  } else {\r
+    TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
 \r
+    //\r
+    // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+    // We have to decrement TokenNumber by 1 to make it usable\r
+    // as the array index.\r
+    //\r
+    TokenNumber--;\r
+    // EBC compiler is very choosy. It may report warning about comparison\r
+    // between UINTN and 0 . So we add 1 in each size of the \r
+    // comparison.\r
+    ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
+  }\r
 \r
-/**\r
-  This function locates the <PCD_IMAGE> on the flash and \r
-  return a pointer to the Section Data on flash.\r
 \r
-  @param[in]  VOID\r
+  LocalTokenNumber = GetPcdDatabase()->Init.LocalTokenNumberTable[TokenNumber];\r
 \r
-  @retval     VOID\r
---*/\r
-UINT8 *\r
-LocatePcdImage (\r
-  VOID\r
-)\r
-{\r
-  EFI_STATUS                 Status;\r
-  EFI_FIRMWARE_VOLUME_HEADER *FvHdr;\r
-  EFI_FFS_FILE_HEADER        *FfsHdr;\r
-  VOID                       *SectionData;\r
+  //\r
+  // We don't support SET for HII and VPD type PCD entry in PEI phase.\r
+  // So we will assert if any register callback for such PCD entry.\r
+  //\r
+  ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);\r
+  ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);\r
 \r
-  Status = PeiCoreFfsFindNextVolume (0, &FvHdr);\r
-  ASSERT_EFI_ERROR (Status);\r
+  GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
+  ASSERT (GuidHob != NULL);\r
+  \r
+  CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
+  CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
 \r
-  do {\r
-    FfsHdr = NULL;\r
-    Status = PeiCoreFfsFindNextFile (EFI_FV_FILETYPE_FREEFORM, FvHdr, &FfsHdr);\r
-    if (Status == EFI_SUCCESS) {\r
-      if (CompareGuid (&gPcdImageFileGuid, &FfsHdr->Name)) {\r
+  Compare = Register? NULL: CallBackFunction;\r
+  Assign  = Register? CallBackFunction: NULL;\r
 \r
-        Status = PeiCoreFfsFindSectionData (EFI_SECTION_RAW, FfsHdr, &SectionData);\r
-        ASSERT_EFI_ERROR (Status);\r
 \r
-        return (UINT8 *)SectionData;\r
-      }\r
+  for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
+    if (CallbackTable[Idx] == Compare) {\r
+      CallbackTable[Idx] = Assign;\r
+      return EFI_SUCCESS;\r
     }\r
-  } while (Status == EFI_SUCCESS);\r
+  }\r
 \r
-  ASSERT (FALSE);\r
+  return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;\r
 \r
-  return NULL;\r
 }\r
 \r
-/**\r
-  The function retrieves the PCD data value according to\r
-  TokenNumber and Guid space given.\r
 \r
-  @param[in]  TokenNumber The token number.\r
-  @param[in]  Guid The Guid space.\r
-  @param[in]  Type The storage type.\r
-  @param[out] Data The output data.\r
 \r
 \r
-  @retval EFI_SUCESS    If data value is found according to SKU_ID.\r
-  @retval EFI_NOT_FOUND If not such a value is found.\r
+/**\r
+  The function builds the PCD database.\r
+\r
+  @param VOID\r
 \r
+  @retval VOID\r
 --*/\r
 VOID\r
-PeiGetPcdEntryWorker (\r
-  IN UINTN TokenNumber,\r
-  IN CONST EFI_GUID       *Guid,  OPTIONAL\r
-  IN PCD_DATA_TYPE        Type,\r
-  OUT VOID                *Data\r
+BuildPcdDatabase (\r
+  VOID\r
   )\r
 {\r
-  PCD_DATABASE *Database;\r
-  EFI_HOB_GUID_TYPE *GuidHob;\r
-\r
-  ASSERT (Data != NULL);\r
-\r
-  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
-  ASSERT (GuidHob != NULL);\r
+  PEI_PCD_DATABASE  *Database;\r
+  VOID              *CallbackFnTable;\r
+  UINTN             SizeOfCallbackFnTable;\r
+  \r
+  Database = BuildGuidHob (&gPcdDataBaseHobGuid, sizeof (PEI_PCD_DATABASE));\r
 \r
-  Database = GET_GUID_HOB_DATA (GuidHob);\r
+  ZeroMem (Database, sizeof (PEI_PCD_DATABASE));\r
 \r
-  GetPcdEntryWorker ( &Database->Info,\r
-                      TokenNumber,\r
-                      Guid,\r
-                      Type,\r
-                      Data\r
-                      );\r
+  //\r
+  // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE\r
+  //\r
+  \r
+  CopyMem (&Database->Init, &gPEIPcdDbInit, sizeof (gPEIPcdDbInit));\r
 \r
+  SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
 \r
+  CallbackFnTable = BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid, SizeOfCallbackFnTable);\r
+  \r
+  ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
+  \r
   return;\r
 }\r
 \r
 \r
-/**\r
-  The function set the PCD data value according to\r
-  TokenNumber and Guid space given.\r
-\r
-  @param[in] Database     The PCD Database Instance.\r
-  @param[in] TokenNumber  The token number.\r
-  @param[in] Guid         The Guid space.\r
-  @param[in] Type         The storage type.\r
-  @param[in] Data         The output data.\r
 \r
+/**\r
+  The function is provided by PCD PEIM and PCD DXE driver to\r
+  do the work of reading a HII variable from variable service.\r
 \r
-  @retval EFI_SUCESS      If data value is found according to SKU_ID.\r
-  @retval EFI_NOT_FOUND   If not such a value is found.\r
+  @param VariableGuid     The Variable GUID.\r
+  @param VariableName     The Variable Name.\r
+  @param VariableData    The output data.\r
+  @param VariableSize    The size of the variable.\r
 \r
+  @retval EFI_SUCCESS         Operation successful.\r
+  @retval EFI_NOT_FOUND         Variablel not found.\r
 --*/\r
+STATIC\r
 EFI_STATUS\r
-SetPcdEntryWorker (\r
-  IN CONST PCD_DATABASE     *Database,\r
-  IN UINTN                  TokenNumber,\r
-  IN CONST EFI_GUID         *Guid,  OPTIONAL\r
-  IN PCD_DATA_TYPE          Type,\r
-  IN VOID                   *Data\r
+GetHiiVariable (\r
+  IN  CONST EFI_GUID      *VariableGuid,\r
+  IN  UINT16              *VariableName,\r
+  OUT VOID                **VariableData,\r
+  OUT UINTN               *VariableSize\r
   )\r
 {\r
-  PCD_INDEX               *PcdIndex;\r
-  EFI_STATUS              Status;\r
-  PCD_PPI_CALLBACK        *CallbackTable;\r
-  UINTN                   Idx;\r
+  UINTN      Size;\r
+  EFI_STATUS Status;\r
+  VOID       *Buffer;\r
+  EFI_PEI_READ_ONLY_VARIABLE_PPI *VariablePpi;\r
 \r
-  ASSERT (Data != NULL);\r
+  Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-  //\r
-  // Find the PCD entry in list in memory first\r
-  //\r
-  PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, &Idx);\r
+  Size = 0;\r
+  Status = VariablePpi->PeiGetVariable (\r
+                          GetPeiServicesTablePointer (),\r
+                          VariableName,\r
+                          (EFI_GUID *) VariableGuid,\r
+                          NULL,\r
+                          &Size,\r
+                          NULL\r
+                            );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
 \r
-  ASSERT (PcdIndex != NULL);\r
 \r
-  ASSERT (PcdIndex->StateByte.DataType == Type);\r
+    Status = PeiServicesAllocatePool (Size, &Buffer);\r
+    ASSERT_EFI_ERROR (Status);\r
 \r
-  //\r
-  // Invoke the callback function.\r
-  //\r
-  CallbackTable = (PCD_PPI_CALLBACK *)\r
-                              GetAbsoluteAddress (Idx * Database->Info.MaxCallbackNum * sizeof(PCD_PPI_CALLBACK),\r
-                              Database->Info.CallbackTableOffset,\r
-                              &Database->Info\r
+    Status = VariablePpi->PeiGetVariable (\r
+                              GetPeiServicesTablePointer (),\r
+                              (UINT16 *) VariableName,\r
+                              (EFI_GUID *) VariableGuid,\r
+                              NULL,\r
+                              &Size,\r
+                              Buffer\r
                               );\r
-  \r
-  for (Idx = 0; Idx < Database->Info.MaxCallbackNum; Idx++) {\r
-    if (CallbackTable[Idx] != NULL) {\r
-      CallbackTable[Idx] (Guid,\r
-                          PcdIndex->TokenNumber,\r
-                          Data,\r
-                          PcdIndex->DatumSize\r
-                          );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    *VariableSize = Size;\r
+    *VariableData = Buffer;\r
+\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+}\r
+\r
+STATIC\r
+UINT32\r
+GetSkuEnabledTokenNumber (\r
+  UINT32 LocalTokenNumber,\r
+  UINTN  Size\r
+  ) \r
+{\r
+  PEI_PCD_DATABASE      *PeiPcdDb;\r
+  SKU_HEAD              *SkuHead;\r
+  SKU_ID                *SkuIdTable;\r
+  INTN                  i;\r
+  UINT8                 *Value;\r
+\r
+  PeiPcdDb = GetPcdDatabase ();\r
+\r
+  ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
+\r
+  SkuHead     = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
+  Value       = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));\r
+  SkuIdTable  = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));\r
+        \r
+  for (i = 0; i < SkuIdTable[0]; i++) {\r
+    if (PeiPcdDb->Init.SystemSkuId == SkuIdTable[i + 1]) {\r
+      break;\r
     }\r
   }\r
 \r
-  Status = SetPcdData (PcdIndex, &Database->Info, Data);\r
+  switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
+    case PCD_TYPE_VPD:\r
+      Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);\r
+      return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);\r
 \r
-  return Status;\r
-}\r
+    case PCD_TYPE_HII:\r
+      Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);\r
+      return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);\r
+      \r
+    case PCD_TYPE_STRING:\r
+      Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);\r
+      return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);\r
 \r
+    case PCD_TYPE_DATA:\r
+      Value += Size * i;\r
+      return (UINT32) (Value - (UINT8 *) PeiPcdDb);\r
 \r
+    default:\r
+      ASSERT (FALSE);\r
+  }\r
 \r
-/**\r
-  (reviewed) The function set the PCD data value according to\r
-  TokenNumber and Guid space given.\r
+  ASSERT (FALSE);\r
 \r
-  @param[in] TokenNumber  The token number.\r
-  @param[in] Guid         The Guid space.\r
-  @param[in] Type         The storage type.\r
-  @param[in] Data         The output data.\r
+  return 0;\r
+  \r
+}\r
 \r
 \r
-  @retval EFI_SUCESS    If data value is found according to SKU_ID.\r
-  @retval EFI_NOT_FOUND If not such a value is found.\r
 \r
---*/\r
-EFI_STATUS\r
-PeiSetPcdEntryWorker (\r
-  IN UINTN TokenNumber,\r
-  IN CONST EFI_GUID       *Guid,  OPTIONAL\r
-  IN PCD_DATA_TYPE        Type,\r
-  IN VOID                 *Data\r
+STATIC\r
+VOID\r
+InvokeCallbackOnSet (\r
+  UINTN             ExTokenNumber,\r
+  CONST EFI_GUID    *Guid, OPTIONAL\r
+  UINTN             TokenNumber,\r
+  VOID              *Data,\r
+  UINTN             Size\r
   )\r
 {\r
-  PCD_DATABASE *Database;\r
-  EFI_HOB_GUID_TYPE *GuidHob;\r
+  EFI_HOB_GUID_TYPE   *GuidHob;\r
+  PCD_PPI_CALLBACK    *CallbackTable;\r
+  UINTN               Idx;\r
 \r
-  ASSERT (Data != NULL);\r
+  //\r
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+  // We have to decrement TokenNumber by 1 to make it usable\r
+  // as the array index.\r
+  //\r
+  TokenNumber--;\r
+  \r
+  if (Guid == NULL) {\r
+    // EBC compiler is very choosy. It may report warning about comparison\r
+    // between UINTN and 0 . So we add 1 in each size of the \r
+    // comparison.\r
+    ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
+  }\r
 \r
-  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
+  GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
   ASSERT (GuidHob != NULL);\r
   \r
-  Database = GET_GUID_HOB_DATA (GuidHob);\r
+  CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
 \r
-  SetPcdEntryWorker (Database,\r
-                     TokenNumber,\r
-                     Guid,\r
-                     Type,\r
-                     Data\r
-                     );\r
+  CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
 \r
-  return EFI_SUCCESS;\r
+  for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
+    if (CallbackTable[Idx] != NULL) {\r
+      CallbackTable[Idx] (Guid,\r
+                          (Guid == NULL)? TokenNumber: ExTokenNumber,\r
+                          Data,\r
+                          Size\r
+                          );\r
+    }\r
+  }\r
+  \r
 }\r
 \r
 \r
 \r
-UINTN\r
-PeiGetPcdEntrySizeWorker (\r
-  IN UINTN                TokenNumber,\r
-  IN CONST EFI_GUID       *Guid  OPTIONAL\r
+EFI_STATUS\r
+SetValueWorker (\r
+  IN          UINTN              TokenNumber,\r
+  IN          VOID               *Data,\r
+  IN          UINTN              Size\r
   )\r
 {\r
-  PCD_DATABASE      *Database;\r
-  EFI_HOB_GUID_TYPE *GuidHob;\r
-\r
-  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
-  ASSERT (GuidHob != NULL);\r
+  return SetWorker (TokenNumber, Data, &Size, FALSE);\r
+}\r
 \r
-  Database = GET_GUID_HOB_DATA (GuidHob);\r
 \r
-  return GetPcdEntrySizeWorker (&Database->Info,\r
-                                TokenNumber,\r
-                                Guid\r
-                                );\r
 \r
-}\r
+EFI_STATUS\r
+SetWorker (\r
+  IN          UINTN               TokenNumber,\r
+  IN OUT      VOID                *Data,\r
+  IN OUT      UINTN               *Size,\r
+  IN          BOOLEAN             PtrType\r
+  )\r
+{\r
+  UINT32              LocalTokenNumber;\r
+  PEI_PCD_DATABASE    *PeiPcdDb;\r
+  UINT16              StringTableIdx;\r
+  UINTN               Offset;\r
+  VOID                *InternalData;\r
+  UINTN               MaxSize;\r
+\r
+  if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  //\r
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+  // We have to decrement TokenNumber by 1 to make it usable\r
+  // as the array index.\r
+  //\r
+  TokenNumber--;\r
 \r
+  // EBC compiler is very choosy. It may report warning about comparison\r
+  // between UINTN and 0 . So we add 1 in each size of the \r
+  // comparison.\r
+  ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
+    \r
+  PeiPcdDb = GetPcdDatabase ();\r
 \r
+  LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];\r
 \r
-/**\r
-  The function registers the CallBackOnSet fucntion\r
-  according to TokenNumber and EFI_GUID space.\r
+  if (!PtrType) {\r
+    ASSERT (PeiPcdGetSize(TokenNumber + 1) == *Size);\r
+  }\r
 \r
-  @param[in]  TokenNumber       The token number.\r
-  @param[in]  Guid              The GUID space.\r
-  @param[in]  CallBackFunction  The Callback function to be registered.\r
+  //\r
+  // We only invoke the callback function for Dynamic Type PCD Entry.\r
+  // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX\r
+  // type PCD entry in ExSetWorker.\r
+  //\r
+  if (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) {\r
+    InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
+  }\r
 \r
-  @retval EFI_SUCCESS If the Callback function is registered.\r
-  @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
---*/\r
-EFI_STATUS\r
-PeiRegisterCallBackWorker (\r
-  IN  UINTN                       TokenNumber,\r
-  IN  CONST EFI_GUID              *Guid, OPTIONAL\r
-  IN  PCD_PPI_CALLBACK            CallBackFunction,\r
-  IN  BOOLEAN                     Register\r
-)\r
-{\r
-  PCD_DATABASE        *Database;\r
-  EFI_HOB_GUID_TYPE   *GuidHob;\r
-  PCD_INDEX           *PcdIndex;\r
-  UINTN               Idx;\r
-  PCD_PPI_CALLBACK    *CallbackTable;\r
-  PCD_PPI_CALLBACK    Compare;\r
-  PCD_PPI_CALLBACK    Assign;\r
+  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
+    if (PtrType) {\r
+      MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
+    } else {\r
+      MaxSize = *Size;\r
+    }\r
+    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
+  }\r
 \r
-  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
-  ASSERT (GuidHob != NULL);\r
+  Offset          = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
+  InternalData    = (VOID *) ((UINT8 *) PeiPcdDb + Offset);\r
   \r
-  Database = GET_GUID_HOB_DATA (GuidHob);\r
+  switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
+    case PCD_TYPE_VPD:\r
+    case PCD_TYPE_HII:\r
+    {\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
 \r
-  PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL);\r
+    case PCD_TYPE_STRING:\r
+      if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
+        StringTableIdx = *((UINT16 *)InternalData);\r
+        CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, *Size);\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
 \r
-  ASSERT (PcdIndex != NULL);\r
+    case PCD_TYPE_DATA:\r
+    {\r
+      if (PtrType) {\r
+        if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
+          CopyMem (InternalData, Data, *Size);\r
+          return EFI_SUCCESS;\r
+        } else {\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+      }\r
 \r
-  if (PcdIndex->StateByte.VpdEnable) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+      switch (*Size) {\r
+        case sizeof(UINT8):\r
+          *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
+          return EFI_SUCCESS;\r
 \r
-  Idx = ((UINTN) PcdIndex - Database->Info.CallbackTableOffset) / sizeof(PCD_INDEX);\r
+        case sizeof(UINT16):\r
+          *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
+          return EFI_SUCCESS;\r
 \r
-  CallbackTable = (PCD_PPI_CALLBACK *) GetAbsoluteAddress (\r
-                                              sizeof (PCD_PPI_CALLBACK) * Idx * Database->Info.MaxCallbackNum,\r
-                                              Database->Info.CallbackTableOffset,\r
-                                              &Database->Info\r
-                                              );\r
+        case sizeof(UINT32):\r
+          *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
+          return EFI_SUCCESS;\r
 \r
-  Compare = Register? NULL: CallBackFunction;\r
-  Assign  = Register? CallBackFunction: NULL;\r
+        case sizeof(UINT64):\r
+          *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
+          return EFI_SUCCESS;\r
 \r
-  for (Idx = 0; Idx < Database->Info.MaxCallbackNum; Idx++) {\r
-    if (CallbackTable[Idx] == Compare) {\r
-      CallbackTable[Idx] = Assign;\r
-      return EFI_SUCCESS;\r
+        default:\r
+          ASSERT (FALSE);\r
+          return EFI_NOT_FOUND;\r
+      }\r
     }\r
+      \r
   }\r
 \r
-  return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;\r
+  ASSERT (FALSE);\r
+  return EFI_NOT_FOUND;\r
 \r
 }\r
 \r
 \r
 \r
 EFI_STATUS\r
-PeiGetNextTokenWorker (\r
-  IN OUT UINTN                *TokenNumber,\r
-  IN CONST EFI_GUID           *Guid     OPTIONAL\r
+ExSetValueWorker (\r
+  IN          UINTN                ExTokenNumber,\r
+  IN          CONST EFI_GUID       *Guid,\r
+  IN          VOID                 *Data,\r
+  IN          UINTN                Size\r
   )\r
 {\r
-  PCD_DATABASE        *Database;\r
-  EFI_HOB_GUID_TYPE   *GuidHob;\r
-\r
-  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
-  ASSERT (GuidHob != NULL);\r
-  \r
-  Database = GET_GUID_HOB_DATA (GuidHob);\r
-\r
-  return GetNextTokenWorker (&Database->Info,\r
-                             TokenNumber,\r
-                             Guid\r
-                             );\r
-\r
+  return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);\r
 }\r
 \r
 \r
 \r
-VOID\r
-GetPcdImageInfo (\r
-  IN CONST UINT8          *PcdImageOnFlash,\r
-  OUT PCD_IMAGE_RECORD    *ImageInfo\r
-)\r
+EFI_STATUS\r
+ExSetWorker (\r
+  IN            UINTN                ExTokenNumber,\r
+  IN            CONST EFI_GUID       *Guid,\r
+  IN            VOID                 *Data,\r
+  IN OUT        UINTN                *Size,\r
+  IN            BOOLEAN              PtrType\r
+  )\r
 {\r
-  PCD_FFS_ENCODING *PcdFfsHdr;\r
+  UINTN                     TokenNumber;\r
 \r
-  PcdFfsHdr = (PCD_FFS_ENCODING *) PcdImageOnFlash;\r
+  if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
 \r
-  ZeroMem (ImageInfo, sizeof (*ImageInfo));\r
+  TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
 \r
-  ImageInfo->ImageStart = PcdImageOnFlash;\r
+  InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);\r
+\r
+  return SetWorker (TokenNumber, Data, Size, PtrType);\r
 \r
-  CopyMem (&ImageInfo->EntryCount,              PcdFfsHdr->EntryCount,         3);\r
-  \r
-  CopyMem (&ImageInfo->GlobalDatumLength,       PcdFfsHdr->GlobalDatumLength,  1);\r
-  ASSERT  (ImageInfo->GlobalDatumLength <= 3);\r
-  \r
-  CopyMem (&ImageInfo->GlobalOffsetLength,      PcdFfsHdr->GlobalOffsetLength, 1);\r
-  ASSERT  (ImageInfo->GlobalOffsetLength <= 3);\r
-  \r
-  CopyMem (&ImageInfo->GlobalTokenLength,       PcdFfsHdr->GlobalTokenLength,  1);\r
-  ASSERT  (ImageInfo->GlobalTokenLength <= 4);\r
-\r
-  CopyMem (&ImageInfo->GlobalGuidTabIdxLength,  PcdFfsHdr->GuidLength,         1);\r
-  ASSERT  (ImageInfo->GlobalGuidTabIdxLength <= 2);\r
-\r
-  CopyMem (&ImageInfo->GlobalStrTabIdxLength,   PcdFfsHdr->GlobalStrTabIdxLength, 1);\r
-  ASSERT  (ImageInfo->GlobalStrTabIdxLength <= 2);\r
-\r
-  CopyMem (&ImageInfo->ImageLength,             PcdFfsHdr->ImageLength,        3);\r
-  CopyMem (&ImageInfo->IndexLength,             PcdFfsHdr->PcdIndexLength,     3);\r
-  CopyMem (&ImageInfo->WholeDataDefaultLength,  PcdFfsHdr->WholeDataBufferLength, 3);\r
-  CopyMem (&ImageInfo->DataDefaultLength,       PcdFfsHdr->DataBufferLength, 3);\r
-  CopyMem (&ImageInfo->GuidTableLength,         PcdFfsHdr->GuidTableLength,  3);\r
-\r
-  ImageInfo->StringTableLength = ImageInfo->ImageLength\r
-                                  - sizeof (PCD_FFS_ENCODING)\r
-                                  - ImageInfo->DataDefaultLength\r
-                                  - ImageInfo->IndexLength\r
-                                  - ImageInfo->GuidTableLength;\r
-\r
-  ImageInfo->DataDefaultStart = PcdImageOnFlash + sizeof (PCD_FFS_ENCODING);\r
-  ImageInfo->IndexStart       = ImageInfo->DataDefaultStart + ImageInfo->DataDefaultLength;\r
-  ImageInfo->GuidTableStart   = (CONST EFI_GUID *)(ImageInfo->IndexStart + ImageInfo->IndexLength);\r
-  ImageInfo->StringTableStart = (CONST UINT16 *) ((UINT8 *) ImageInfo->GuidTableStart + ImageInfo->GuidTableLength);\r
-  \r
-  return;\r
 }\r
 \r
 \r
 \r
-/**\r
-  The function builds the PCD database based on the\r
-  PCD_IMAGE on the flash.\r
-\r
-  The layout of the PCD_DATABASE is as follows:\r
-\r
-  ---------------------------\r
-  |  PCD_DATABASE_HEADER    |\r
-  ---------------------------\r
-  |  GUID_TABLE             |  Aligned on GUID    (128 bits)\r
-  ---------------------------\r
-  |  PCD_CALL_BACK_TABLE    |  Aligned on Pointer (32 bits or 64 bits)\r
-  ---------------------------\r
-  |  PCD_INDEX_TABLE        |  Aligned on PCD_INDEX (see PCD_INDEX's declaration)\r
-  ---------------------------\r
-  |  IMAGE_STRING_TABLE     |  Aligned on 16 Bits\r
-  ---------------------------\r
-  |  IMAGE_PCD_INDEX        |  Unaligned\r
-  ---------------------------\r
-  |  Data Defaults          |  Unaligned\r
-  ---------------------------\r
-  |  Data Buffer            |\r
-  |  for entries without    |\r
-  |  defaults               |\r
-  ---------------------------\r
-\r
-  @param[in] PcdImageOnFlash  The PCD image on flash.\r
 \r
-  @retval VOID\r
---*/\r
-UINTN\r
-GetPcdDatabaseLen (\r
-  IN CONST UINT8          *PcdImageOnFlash,\r
-  OUT PCD_DATABASE_HEADER *Info,\r
-  OUT PCD_IMAGE_RECORD    *ImageInfo\r
+VOID *\r
+ExGetWorker (\r
+  IN CONST  EFI_GUID  *Guid,\r
+  IN UINTN            ExTokenNumber,\r
+  IN UINTN            GetSize\r
   )\r
 {\r
-  UINTN DatabaseLen;\r
-  UINTN DatabaseHeaderLength;\r
-  UINTN PcdIndexLength;\r
-  UINTN CallbackBufferLength;\r
-\r
-\r
-  GetPcdImageInfo (PcdImageOnFlash, ImageInfo);\r
-\r
-  Info->MaxCallbackNum = FixedPcdGet32(PcdMaxPcdCallBackNumber) ;\r
-\r
-  DatabaseHeaderLength = sizeof (PCD_DATABASE) - sizeof(UINT8);\r
-\r
-  PcdIndexLength       = sizeof (PCD_INDEX) * ImageInfo->EntryCount;\r
-  CallbackBufferLength = sizeof (PCD_PPI_CALLBACK) * Info->MaxCallbackNum * ImageInfo->EntryCount;\r
-\r
-  Info->EntryCount          = ImageInfo->EntryCount;\r
-  Info->GuidTableOffset     = DatabaseHeaderLength;\r
-  Info->CallbackTableOffset = Info->GuidTableOffset + ImageInfo->GuidTableLength;\r
-  Info->PcdIndexOffset      = Info->PcdIndexOffset + PcdIndexLength;\r
-  Info->ImageIndexOffset    = Info->CallbackTableOffset + CallbackBufferLength;\r
-  Info->DataBufferOffset    = Info->ImageIndexOffset + ImageInfo->DataDefaultLength;\r
-\r
-  Info->HiiGuidOffsetLength = ImageInfo->GlobalGuidTabIdxLength;\r
-  Info->HiiVariableOffsetLength = ImageInfo->GlobalStrTabIdxLength;\r
-  Info->ExtendedOffsetLength    = ImageInfo->GlobalOffsetLength;\r
-\r
-  Info->SkuId = 0;\r
-\r
-  DatabaseLen = DatabaseHeaderLength\r
-              + ImageInfo->GuidTableLength\r
-              + PcdIndexLength\r
-              + CallbackBufferLength\r
-              + ImageInfo->IndexLength\r
-              + ImageInfo->WholeDataDefaultLength;\r
-\r
-  Info->DatabaseLen = DatabaseLen;\r
-\r
-  return DatabaseLen;\r
+  if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {\r
+    ASSERT (FALSE);\r
+    return 0;\r
+  }\r
+  \r
+  return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);\r
 }\r
 \r
 \r
-/**\r
-  The function constructs a single PCD_INDEX according a index in\r
-  <PCD_IMAGE>.\r
 \r
-  @param[in] ImageIndex  The starting address of a PCD index defined in PCD spec 0.51.\r
-  @param[in] Index       The output PCD_INDEX. \r
-  @param[in] ImageInfo   The attributes of the PCD_IMAGE as this binary stream is highly\r
-                          optimized for size.\r
 \r
-  @retval UINTN The length of the current PCD index.\r
-**/\r
-UINTN\r
-BuildPcdIndex (\r
-  IN CONST UINT8            *ImageIndex,\r
-  OUT PCD_INDEX             *Index,\r
-  IN CONST PCD_IMAGE_RECORD *ImageInfo\r
-)\r
+VOID *\r
+GetWorker (\r
+  UINTN               TokenNumber,\r
+  UINTN               GetSize\r
+  )\r
 {\r
-  UINTN       SkuCount;\r
-  CONST UINT8 *ImageIndexBackUp;\r
+  UINT32              Offset;\r
+  EFI_GUID            *Guid;\r
+  UINT16              *Name;\r
+  VARIABLE_HEAD       *VariableHead;\r
+  EFI_STATUS          Status;\r
+  UINTN               DataSize;\r
+  VOID                *Data;\r
+  UINT16              *StringTable;\r
+  UINT16              StringTableIdx;\r
+  PEI_PCD_DATABASE    *PeiPcdDb;\r
+  UINT32              LocalTokenNumber;\r
+  UINTN               MaxSize;\r
 \r
-  ImageIndexBackUp = ImageIndex;\r
-  \r
   //\r
-  // Token Number\r
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+  // We have to decrement TokenNumber by 1 to make it usable\r
+  // as the array index.\r
   //\r
-  CopyMem (&Index->TokenNumber,\r
-            ImageIndex,\r
-            ImageInfo->GlobalTokenLength\r
-            );\r
+  TokenNumber--;\r
 \r
-  ImageIndex += ImageInfo->GlobalTokenLength;\r
-  \r
-  //\r
-  // State Byte\r
-  //\r
-  PcdImageExpandStateByte (&Index->StateByte,\r
-                           *ImageIndex\r
-                           );\r
+  // EBC compiler is very choosy. It may report warning about comparison\r
+  // between UINTN and 0 . So we add 1 in each size of the \r
+  // comparison.\r
+  ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
 \r
-  ImageIndex += 1;\r
-  \r
-  //\r
-  // Dataum Size\r
-  //\r
-  CopyMem (&Index->DatumSize,\r
-          ImageIndex,\r
-          ImageInfo->GlobalDatumLength\r
-          );\r
+  ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));\r
 \r
-  ImageIndex += ImageInfo->GlobalDatumLength;\r
+  PeiPcdDb        = GetPcdDatabase ();\r
 \r
-  //\r
-  // SKU_DATA\r
-  //\r
-  if (Index->StateByte.SkuEnable) {\r
-    Index->SkuCount     = *ImageIndex;\r
-    SkuCount            = *ImageIndex;\r
-    ImageIndex++;\r
-    Index->SkuIdArray   = (UINT32) ImageIndex - (UINT32) ImageInfo->IndexStart;\r
-    ImageIndex         += Index->SkuCount;\r
-  } else {\r
-    //\r
-    // There is always a default SKU_ID of zero even \r
-    // if SKU is not enabled for this PCD entry.\r
-    // \r
-    //\r
-    SkuCount = 1;\r
-  }\r
+  LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];\r
 \r
-  //\r
-  // Extended Offset\r
-  //\r
-  CopyMem (&Index->ExtendedDataOffset,\r
-           ImageIndex,\r
-           ImageInfo->GlobalOffsetLength\r
-           );\r
+  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
+    if (GetSize == 0) {\r
+      MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
+    } else {\r
+      MaxSize = GetSize;\r
+    }\r
+    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
+  }\r
 \r
-  ImageIndex += ImageInfo->GlobalOffsetLength * SkuCount;\r
+  Offset      = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
+  StringTable = PeiPcdDb->Init.StringTable;\r
+  \r
+  switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
+    case PCD_TYPE_VPD:\r
+    {\r
+      VPD_HEAD *VpdHead;\r
+      VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
+      return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);\r
+    }\r
+      \r
+    case PCD_TYPE_HII:\r
+    {\r
+      VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
+      \r
+      Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);\r
+      Name = &StringTable[VariableHead->StringIndex];\r
+\r
+      Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
+\r
+      if (Status == EFI_SUCCESS) {\r
+        return (VOID *) ((UINT8 *) Data + VariableHead->Offset);\r
+      } else {\r
+        //\r
+        // Return the default value specified by Platform Integrator \r
+        //\r
+        return (VOID *) ((UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset);\r
+      }\r
+    }\r
 \r
-  //\r
-  // DynamicEX Guid Offset\r
-  //\r
-  if (Index->StateByte.ExtendedGuidPresent) {\r
-    CopyMem (&Index->DynamicExGuid,\r
-             ImageIndex,\r
-             ImageInfo->GlobalGuidTabIdxLength\r
-             );\r
+    case PCD_TYPE_DATA:\r
+      return (VOID *) ((UINT8 *)PeiPcdDb + Offset);\r
 \r
-    ImageIndex += ImageInfo->GlobalGuidTabIdxLength;\r
-  }\r
+    case PCD_TYPE_STRING:\r
+      StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);\r
+      return (VOID *) (&StringTable[StringTableIdx]);\r
 \r
-  //\r
-  // HII_DATA\r
-  //\r
-  if (Index->StateByte.HiiEnable) {\r
-    Index->HiiData = (UINT32) ImageIndex - (UINT32) ImageInfo->IndexStart;\r
-    ImageIndex += ((ImageInfo->GlobalStrTabIdxLength + ImageInfo->GlobalGuidTabIdxLength) * SkuCount);\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+      \r
   }\r
 \r
-  return (UINTN) (ImageIndex - ImageIndexBackUp);\r
+  ASSERT (FALSE);\r
+      \r
+  return NULL;\r
+  \r
 }\r
 \r
 \r
 \r
-\r
-/**\r
-  The function builds the PCD database based on the\r
-  PCD_IMAGE on the flash.\r
-\r
-  @param[in] Database  The database instance.\r
-  @param[in] ImageIndex The starting address of a PCD index defined in PCD spec 0.51.\r
-  @param[in] ImageInfo The attributes of the PCD_IMAGE as this binary stream is highly\r
-              optimized for size.\r
-\r
-  @retval VOID\r
-**/\r
-VOID\r
-BuildPcdDatabaseIndex (\r
-  PCD_DATABASE     *Database,\r
-  UINT8            *ImageIndex,\r
-  PCD_IMAGE_RECORD *ImageInfo\r
+UINTN           \r
+GetExPcdTokenNumber (\r
+  IN CONST EFI_GUID             *Guid,\r
+  IN UINTN                      ExTokenNumber\r
   )\r
 {\r
-  UINTN     Idx;\r
-  UINTN     Len;\r
-  PCD_INDEX *IndexTable;\r
-\r
-  IndexTable = (PCD_INDEX *) GetAbsoluteAddress (0, Database->Info.PcdIndexOffset, Database);\r
+  UINT32              i;\r
+  DYNAMICEX_MAPPING   *ExMap;\r
+  EFI_GUID            *GuidTable;\r
+  EFI_GUID            *MatchGuid;\r
+  UINTN               MatchGuidIdx;\r
+  PEI_PCD_DATABASE    *PeiPcdDb;\r
+\r
+  PeiPcdDb    = GetPcdDatabase();\r
+  \r
+  ExMap       = PeiPcdDb->Init.ExMapTable;\r
+  GuidTable   = PeiPcdDb->Init.GuidTable;\r
 \r
-  for (Idx = 0; Idx < Database->Info.EntryCount; Idx++) {\r
-    Len = BuildPcdIndex (ImageIndex, &IndexTable[Idx], ImageInfo);\r
-    ImageIndex += Len;\r
+  MatchGuid = ScanGuid (GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);\r
+  //\r
+  // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
+  // error in the BUILD system.\r
+  //\r
+  ASSERT (MatchGuid != NULL);\r
+  \r
+  MatchGuidIdx = MatchGuid - GuidTable;\r
+  \r
+  for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
+    if ((ExTokenNumber == ExMap[i].ExTokenNumber) && \r
+        (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
+      return ExMap[i].LocalTokenNumber;\r
+    }\r
   }\r
-\r
-  return;\r
+  \r
+  ASSERT (FALSE);\r
+  \r
+  return 0;\r
 }\r
 \r
 \r
-/**\r
-  The function builds the PCD database based on the\r
-  PCD_IMAGE on the flash.\r
-\r
-  @param[in] PcdImageOnFlash  The PCD image on flash.\r
 \r
-  @retval VOID\r
---*/\r
-VOID\r
-BuildPcdDatabase (\r
-  UINT8 *PcdImageOnFlash\r
+PEI_PCD_DATABASE *\r
+GetPcdDatabase (\r
+  VOID\r
   )\r
 {\r
-  PCD_DATABASE        *Database;\r
-  UINTN               Len;\r
-  PCD_IMAGE_RECORD    ImageInfo;\r
-  UINT8               *ImageIndex;\r
-  PCD_DATABASE_HEADER DatabaseHeader;\r
-\r
-  Len = GetPcdDatabaseLen(PcdImageOnFlash, &DatabaseHeader, &ImageInfo);\r
-\r
-  Database = BuildGuidHob (&gPcdDataBaseHobGuid, Len);\r
-  ASSERT (Database != NULL);\r
-\r
-  ZeroMem (Database, Len);\r
-\r
-  //\r
-  // Update Database header\r
-  //\r
-  CopyMem (&Database->Info, &DatabaseHeader, sizeof (DatabaseHeader));\r
+  EFI_HOB_GUID_TYPE *GuidHob;\r
 \r
-  //\r
-  // I need this to get the GuidTableOffset as we don't\r
-  // know if Database field of PCD_DATABASE starts from an aligned\r
-  // address. The compilor may add padding after PCD_DATABASE_HEADER field.\r
-  //\r
-  Database->Info.GuidTableOffset = ((UINTN) &Database->GuidTable) - (UINTN)Database;\r
+  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
+  ASSERT (GuidHob != NULL);\r
   \r
-  //\r
-  // Copy Guid Table from Flash\r
-  //\r
-  CopyMem ((UINT8 *) Database + Database->Info.GuidTableOffset,\r
-            ImageInfo.GuidTableStart,\r
-            ImageInfo.GuidTableLength\r
-            );\r
-\r
-  //\r
-  // Copy ImageIndex from Flash\r
-  //\r
-  CopyMem ((UINT8 *) Database + Database->Info.ImageIndexOffset,\r
-            ImageInfo.IndexStart,\r
-            ImageInfo.IndexLength\r
-            );\r
-\r
-  //\r
-  // Copy Default Value\r
-  //\r
-  CopyMem ((UINT8 *) Database + Database->Info.DataBufferOffset,\r
-           ImageInfo.DataDefaultStart,\r
-           ImageInfo.DataDefaultLength\r
-           );\r
-\r
-  //\r
-  // Copy String Table\r
-  //\r
-  CopyMem ((UINT8 *) Database + Database->Info.StringTableOffset,\r
-           ImageInfo.StringTableStart,\r
-           ImageInfo.StringTableLength\r
-           );\r
-\r
-  ImageIndex = GetAbsoluteAddress (0, Database->Info.ImageIndexOffset, Database);\r
-\r
-  BuildPcdDatabaseIndex (Database, ImageIndex, &ImageInfo);\r
-\r
-  return;\r
+  return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
 }\r
 \r
 \r
 \r
-/**\r
-  The function is provided by PCD PEIM and PCD DXE driver to\r
-  do the work of reading a HII variable from variable service.\r
-\r
-  @param[in] VariableGuid     The Variable GUID.\r
-  @param[in] VariableName     The Variable Name.\r
-  @param[out] VariableData    The output data.\r
-  @param[out] VariableSize    The size of the variable.\r
-\r
-  @retval EFI_SUCCESS         Operation successful.\r
-  @retval EFI_SUCCESS         Variablel not found.\r
---*/\r
-EFI_STATUS\r
-GetHiiVariable (\r
-  IN  EFI_GUID     *VariableGuid,\r
-  IN  UINT16       *VariableName,\r
-  OUT VOID         **VariableData,\r
-  OUT UINTN        *VariableSize\r
+SKU_ID *\r
+GetSkuIdArray (\r
+  IN    UINTN             LocalTokenNumberTableIdx,\r
+  IN    PEI_PCD_DATABASE  *Database\r
   )\r
 {\r
-  UINTN      Size;\r
-  EFI_STATUS Status;\r
-  VOID       *Buffer;\r
-  EFI_PEI_READ_ONLY_VARIABLE_PPI *VariablePpi;\r
-\r
-  Status = PeiCoreLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, &VariablePpi);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Size = 0;\r
-\r
-  Status = VariablePpi->PeiGetVariable (\r
-                          GetPeiServicesTablePointer (),\r
-                          VariableName,\r
-                          VariableGuid,\r
-                          NULL,\r
-                          &Size,\r
-                          NULL\r
-                            );\r
-  ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+  SKU_HEAD *SkuHead;\r
+  UINTN     LocalTokenNumber;\r
 \r
-  Status = PeiCoreAllocatePool (Size, &Buffer);\r
-  ASSERT_EFI_ERROR (Status);\r
+  LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
 \r
-  // declare a local for STP.\r
-  //\r
-  Status = VariablePpi->PeiGetVariable (\r
-                            GetPeiServicesTablePointer (),\r
-                            (UINT16 *) VariableName,\r
-                            VariableGuid,\r
-                            NULL,\r
-                            &Size,\r
-                            Buffer\r
-                            );\r
-  ASSERT_EFI_ERROR (Status);\r
+  ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
 \r
-  *VariableSize = Size;\r
-  *VariableData = Buffer;\r
+  SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
 \r
-  return EFI_SUCCESS;\r
+  return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);\r
+  \r
 }\r
 \r
 \r
 \r
-/**\r
-  The function is provided by PCD PEIM and PCD DXE driver to\r
-  do the work of reading a HII variable from variable service.\r
-\r
-  @param[in] VariableGuid     The Variable GUID.\r
-  @param[in] VariableName     The Variable Name.\r
-  @param[in] Data             The input data.\r
-  @param[out] VariableSize    The size of the variable.\r
-  @param[in] Offset           The offset of the variable data that a PCD entry will starts from.\r
-\r
-  @retval EFI_SUCCESS         Operation successful.\r
-  @retval EFI_SUCCESS         Variablel not found.\r
---*/\r
-EFI_STATUS\r
-SetHiiVariable (\r
-  IN  EFI_GUID     *VariableGuid,\r
-  IN  UINT16       *VariableName,\r
-  IN  CONST VOID   *Data,\r
-  IN  UINTN        VariableSize,\r
-  IN  UINTN        Offset\r
+UINTN\r
+GetSizeTableIndex (\r
+  IN    UINTN             LocalTokenNumberTableIdx,\r
+  IN    PEI_PCD_DATABASE  *Database\r
   )\r
 {\r
-  ASSERT (FALSE);\r
-  return EFI_INVALID_PARAMETER;\r
-}\r
+  UINTN       i;\r
+  UINTN        SizeTableIdx;\r
+  UINTN       LocalTokenNumber;\r
+  SKU_ID      *SkuIdTable;\r
+  \r
+  SizeTableIdx = 0;\r
+\r
+  for (i=0; i<LocalTokenNumberTableIdx; i++) {\r
+    LocalTokenNumber = Database->Init.LocalTokenNumberTable[i];\r
+\r
+    if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
+      //\r
+      // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
+      // PCD entry.\r
+      //\r
+      if (LocalTokenNumber & PCD_TYPE_VPD) {\r
+          //\r
+          // We have only one entry for VPD enabled PCD entry:\r
+          // 1) MAX Size.\r
+          // We consider current size is equal to MAX size.\r
+          //\r
+          SizeTableIdx++;\r
+      } else {\r
+        if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
+          //\r
+          // We have only two entry for Non-Sku enabled PCD entry:\r
+          // 1) MAX SIZE\r
+          // 2) Current Size\r
+          //\r
+          SizeTableIdx += 2;\r
+        } else {\r
+          //\r
+          // We have these entry for SKU enabled PCD entry\r
+          // 1) MAX SIZE\r
+          // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
+          //\r
+          SkuIdTable = GetSkuIdArray (i, Database);\r
+          SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
+        }\r
+      }\r
+    }\r
 \r
+  }\r
 \r
+  return SizeTableIdx;\r
+}\r