]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/PCD/Dxe/Service.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Service.c
index 53780dca9fac2db9d2713fff74a3495e26071064..ea7edc3cbb1c620860b333577129dde4e980f470 100644 (file)
 /** @file\r
     Help functions used by PCD DXE driver.\r
 \r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Service.h"\r
+#include <Library/DxeServicesLib.h>\r
+\r
+PCD_DATABASE   mPcdDatabase;\r
 \r
-PCD_DATABASE  *mPcdDatabase;\r
+UINT32         mPcdTotalTokenCount;\r
+UINT32         mPeiLocalTokenCount;\r
+UINT32         mDxeLocalTokenCount;\r
+UINT32         mPeiNexTokenCount;\r
+UINT32         mDxeNexTokenCount;\r
+UINT32         mPeiExMapppingTableSize;\r
+UINT32         mDxeExMapppingTableSize;\r
+UINT32         mPeiGuidTableSize;\r
+UINT32         mDxeGuidTableSize;\r
+\r
+BOOLEAN        mPeiExMapTableEmpty;\r
+BOOLEAN        mDxeExMapTableEmpty;\r
+BOOLEAN        mPeiDatabaseEmpty;\r
 \r
 LIST_ENTRY    *mCallbackFnTable;\r
+EFI_GUID     **TmpTokenSpaceBuffer;\r
+UINTN          TmpTokenSpaceBufferCount;\r
+\r
+UINTN                 mPeiPcdDbSize    = 0;\r
+PEI_PCD_DATABASE      *mPeiPcdDbBinary = NULL;\r
+UINTN                 mDxePcdDbSize    = 0;\r
+DXE_PCD_DATABASE      *mDxePcdDbBinary = NULL;\r
+\r
+/**\r
+  Get Local Token Number by Token Number.\r
+\r
+  @param[in]    IsPeiDb     If TRUE, the pcd entry is initialized in PEI phase,\r
+                            If FALSE, the pcd entry is initialized in DXE phase.\r
+  @param[in]    TokenNumber The PCD token number.\r
+\r
+  @return       Local Token Number.\r
+**/\r
+UINT32\r
+GetLocalTokenNumber (\r
+  IN BOOLEAN            IsPeiDb,\r
+  IN UINTN              TokenNumber\r
+  )\r
+{\r
+  UINT32                *LocalTokenNumberTable;\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
+  LocalTokenNumberTable  = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) :\r
+                                     (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
+  TokenNumber            = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount;\r
+\r
+  return LocalTokenNumberTable[TokenNumber];\r
+}\r
+\r
+/**\r
+  Get PCD type by Local Token Number.\r
+\r
+  @param[in]    LocalTokenNumber The PCD local token number.\r
+\r
+  @return       PCD type.\r
+**/\r
+EFI_PCD_TYPE\r
+GetPcdType (\r
+  IN UINT32             LocalTokenNumber\r
+  )\r
+{\r
+  switch (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) {\r
+    case PCD_DATUM_TYPE_POINTER:\r
+      return EFI_PCD_TYPE_PTR;\r
+    case PCD_DATUM_TYPE_UINT8:\r
+      if ((LocalTokenNumber & PCD_DATUM_TYPE_UINT8_BOOLEAN) == PCD_DATUM_TYPE_UINT8_BOOLEAN) {\r
+        return EFI_PCD_TYPE_BOOL;\r
+      } else {\r
+        return EFI_PCD_TYPE_8;\r
+      }\r
+    case PCD_DATUM_TYPE_UINT16:\r
+      return EFI_PCD_TYPE_16;\r
+    case PCD_DATUM_TYPE_UINT32:\r
+      return EFI_PCD_TYPE_32;\r
+    case PCD_DATUM_TYPE_UINT64:\r
+      return EFI_PCD_TYPE_64;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_PCD_TYPE_8;\r
+  }\r
+}\r
+\r
+/**\r
+  Get PCD name.\r
+\r
+  @param[in]    OnlyTokenSpaceName  If TRUE, only need to get the TokenSpaceCName.\r
+                                    If FALSE, need to get the full PCD name.\r
+  @param[in]    IsPeiDb             If TRUE, the pcd entry is initialized in PEI phase,\r
+                                    If FALSE, the pcd entry is initialized in DXE phase.\r
+  @param[in]    TokenNumber         The PCD token number.\r
+\r
+  @return       The TokenSpaceCName or full PCD name.\r
+**/\r
+CHAR8 *\r
+GetPcdName (\r
+  IN BOOLEAN            OnlyTokenSpaceName,\r
+  IN BOOLEAN            IsPeiDb,\r
+  IN UINTN              TokenNumber\r
+  )\r
+{\r
+  PCD_DATABASE_INIT *Database;\r
+  UINT8             *StringTable;\r
+  UINTN             NameSize;\r
+  PCD_NAME_INDEX    *PcdNameIndex;\r
+  CHAR8             *TokenSpaceName;\r
+  CHAR8             *PcdName;\r
+  CHAR8             *Name;\r
+\r
+  //\r
+  // Return NULL when PCD name table is absent.\r
+  //\r
+  if (IsPeiDb) {\r
+    if (mPcdDatabase.PeiDb->PcdNameTableOffset == 0) {\r
+      return NULL;\r
+    }\r
+  } else {\r
+    if (mPcdDatabase.DxeDb->PcdNameTableOffset == 0) {\r
+      return NULL;\r
+    }\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
+  Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
+  TokenNumber = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount;\r
+\r
+  StringTable = (UINT8 *) Database + Database->StringTableOffset;\r
+\r
+  //\r
+  // Get the PCD name index.\r
+  //\r
+  PcdNameIndex = (PCD_NAME_INDEX *)((UINT8 *) Database + Database->PcdNameTableOffset) + TokenNumber;\r
+  TokenSpaceName = (CHAR8 *)&StringTable[PcdNameIndex->TokenSpaceCNameIndex];\r
+  PcdName = (CHAR8 *)&StringTable[PcdNameIndex->PcdCNameIndex];\r
+\r
+  if (OnlyTokenSpaceName) {\r
+    //\r
+    // Only need to get the TokenSpaceCName.\r
+    //\r
+    Name = AllocateCopyPool (AsciiStrSize (TokenSpaceName), TokenSpaceName);\r
+  } else {\r
+    //\r
+    // Need to get the full PCD name.\r
+    //\r
+    NameSize = AsciiStrSize (TokenSpaceName) + AsciiStrSize (PcdName);\r
+    Name = AllocateZeroPool (NameSize);\r
+    ASSERT (Name != NULL);\r
+    //\r
+    // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.\r
+    //\r
+    AsciiStrCatS (Name, NameSize, TokenSpaceName);\r
+    Name[AsciiStrSize (TokenSpaceName) - sizeof (CHAR8)] = '.';\r
+    AsciiStrCatS (Name, NameSize, PcdName);\r
+  }\r
+\r
+  return Name;\r
+}\r
+\r
+/**\r
+  Retrieve additional information associated with a PCD token.\r
+\r
+  This includes information such as the type of value the TokenNumber is associated with as well as possible\r
+  human readable name that is associated with the token.\r
+\r
+  @param[in]    IsPeiDb     If TRUE, the pcd entry is initialized in PEI phase,\r
+                            If FALSE, the pcd entry is initialized in DXE phase.\r
+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]    TokenNumber The PCD token number.\r
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.\r
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
+\r
+  @retval  EFI_SUCCESS      The PCD information was returned successfully\r
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.\r
+**/\r
+EFI_STATUS\r
+ExGetPcdInfo (\r
+  IN        BOOLEAN             IsPeiDb,\r
+  IN CONST  EFI_GUID            *Guid,\r
+  IN        UINTN               TokenNumber,\r
+  OUT       EFI_PCD_INFO        *PcdInfo\r
+  )\r
+{\r
+  PCD_DATABASE_INIT     *Database;\r
+  UINTN                 GuidTableIdx;\r
+  EFI_GUID              *MatchGuid;\r
+  EFI_GUID              *GuidTable;\r
+  DYNAMICEX_MAPPING     *ExMapTable;\r
+  UINTN                 Index;\r
+  UINT32                LocalTokenNumber;\r
+\r
+  Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
+\r
+  GuidTable = (EFI_GUID *)((UINT8 *)Database + Database->GuidTableOffset);\r
+  MatchGuid = ScanGuid (GuidTable, Database->GuidTableCount * sizeof(EFI_GUID), Guid);\r
+\r
+  if (MatchGuid == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  GuidTableIdx = MatchGuid - GuidTable;\r
+\r
+  ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)Database + Database->ExMapTableOffset);\r
+\r
+  //\r
+  // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.\r
+  //\r
+  for (Index = 0; Index < Database->ExTokenCount; Index++) {\r
+    if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
+      if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
+        //\r
+        // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
+        // PcdSize to 0 and PcdName to the null-terminated ASCII string\r
+        // associated with the token's namespace Guid.\r
+        //\r
+        PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
+        PcdInfo->PcdSize = 0;\r
+        //\r
+        // Here use one representative in the token space to get the TokenSpaceCName.\r
+        //\r
+        PcdInfo->PcdName = GetPcdName (TRUE, IsPeiDb, ExMapTable[Index].TokenNumber);\r
+        return EFI_SUCCESS;\r
+      } else if (ExMapTable[Index].ExTokenNumber == TokenNumber) {\r
+        PcdInfo->PcdSize = DxePcdGetSize (ExMapTable[Index].TokenNumber);\r
+        LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, ExMapTable[Index].TokenNumber);\r
+        PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
+        PcdInfo->PcdName = GetPcdName (FALSE, IsPeiDb, ExMapTable[Index].TokenNumber);\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Retrieve additional information associated with a PCD token.\r
+\r
+  This includes information such as the type of value the TokenNumber is associated with as well as possible\r
+  human readable name that is associated with the token.\r
+\r
+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]    TokenNumber The PCD token number.\r
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.\r
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
+\r
+  @retval  EFI_SUCCESS      The PCD information was returned successfully.\r
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.\r
+**/\r
+EFI_STATUS\r
+DxeGetPcdInfo (\r
+  IN CONST  EFI_GUID        *Guid,\r
+  IN        UINTN           TokenNumber,\r
+  OUT       EFI_PCD_INFO    *PcdInfo\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  BOOLEAN               PeiExMapTableEmpty;\r
+  BOOLEAN               DxeExMapTableEmpty;\r
+  UINT32                LocalTokenNumber;\r
+  BOOLEAN               IsPeiDb;\r
+\r
+  ASSERT (PcdInfo != NULL);\r
+\r
+  Status = EFI_NOT_FOUND;\r
+  PeiExMapTableEmpty = mPeiExMapTableEmpty;\r
+  DxeExMapTableEmpty = mDxeExMapTableEmpty;\r
+\r
+  if (Guid == NULL) {\r
+    if (((TokenNumber + 1 > mPeiNexTokenCount + 1) && (TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||\r
+        ((TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1)))) {\r
+      return EFI_NOT_FOUND;\r
+    } else if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
+      //\r
+      // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
+      // PcdSize to 0 and PcdName to NULL for default Token Space.\r
+      //\r
+      PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
+      PcdInfo->PcdSize = 0;\r
+      PcdInfo->PcdName = NULL;\r
+    } else {\r
+      PcdInfo->PcdSize = DxePcdGetSize (TokenNumber);\r
+      IsPeiDb = FALSE;\r
+      if ((TokenNumber + 1 <= mPeiNexTokenCount + 1)) {\r
+        IsPeiDb = TRUE;\r
+      }\r
+      LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber);\r
+      PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
+      PcdInfo->PcdName = GetPcdName (FALSE, IsPeiDb, TokenNumber);\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (PeiExMapTableEmpty && DxeExMapTableEmpty) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (!PeiExMapTableEmpty) {\r
+    Status = ExGetPcdInfo (\r
+               TRUE,\r
+               Guid,\r
+               TokenNumber,\r
+               PcdInfo\r
+               );\r
+  }\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    return Status;\r
+  }\r
+\r
+  if (!DxeExMapTableEmpty) {\r
+    Status = ExGetPcdInfo (\r
+               FALSE,\r
+               Guid,\r
+               TokenNumber,\r
+               PcdInfo\r
+               );\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Get the PCD entry pointer in PCD database.\r
-  \r
+\r
   This routine will visit PCD database to find the PCD entry according to given\r
-  token number. The given token number is autogened by build tools and it will be \r
-  translated to local token number. Local token number contains PCD's type and \r
+  token number. The given token number is autogened by build tools and it will be\r
+  translated to local token number. Local token number contains PCD's type and\r
   offset of PCD entry in PCD database.\r
 \r
   @param TokenNumber     Token's number, it is autogened by build tools\r
@@ -38,7 +364,6 @@ GetWorker (
   IN UINTN             GetSize\r
   )\r
 {\r
-  UINT32              *LocalTokenNumberTable;\r
   EFI_GUID            *GuidTable;\r
   UINT8               *StringTable;\r
   EFI_GUID            *Guid;\r
@@ -49,13 +374,12 @@ GetWorker (
   VPD_HEAD            *VpdHead;\r
   UINT8               *PcdDb;\r
   VOID                *RetPtr;\r
-  UINTN               MaxSize;\r
   UINTN               TmpTokenNumber;\r
   UINTN               DataSize;\r
   EFI_STATUS          Status;\r
   UINT32              LocalTokenNumber;\r
   UINT32              Offset;\r
-  STRING_HEAD         StringTableIdx;      \r
+  STRING_HEAD         StringTableIdx;\r
   BOOLEAN             IsPeiDb;\r
 \r
   //\r
@@ -64,6 +388,8 @@ GetWorker (
   EfiAcquireLock (&mPcdDatabaseLock);\r
 \r
   RetPtr = NULL;\r
+\r
+  ASSERT (TokenNumber > 0);\r
   //\r
   // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
   // We have to decrement TokenNumber by 1 to make it usable\r
@@ -72,115 +398,90 @@ GetWorker (
   TokenNumber--;\r
 \r
   TmpTokenNumber = TokenNumber;\r
-  \r
+\r
   //\r
-  // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.\r
-  // It could be zero. EBC compiler is very choosy. It may\r
-  // report warning. So we add 1 in each size of the \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
   //\r
-  ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
+  ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\r
 \r
   ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));\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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
-  IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
-\r
-  LocalTokenNumberTable  = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
-                                     mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
+  IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
 \r
-  TokenNumber            = IsPeiDb ? TokenNumber :\r
-                                     TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
+  LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);\r
 \r
-  LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
-  \r
-  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
-    if (GetSize == 0) {\r
-      GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
-    } else {\r
-      MaxSize = GetSize;\r
-    }\r
-    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
-  }\r
+  PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);\r
 \r
-  PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
-                                    \r
   if (IsPeiDb) {\r
-    StringTable = (UINT8 *) (&mPcdDatabase->PeiDb.Init.StringTable[0]);\r
+    StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);\r
   } else {\r
-    StringTable = (UINT8 *) (&mPcdDatabase->DxeDb.Init.StringTable[0]);\r
+    StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);\r
   }\r
-                                      \r
-  \r
+\r
+\r
   Offset     = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
-  \r
+\r
   switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
     case PCD_TYPE_VPD:\r
       VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);\r
-      RetPtr = (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);\r
+      ASSERT (mVpdBaseAddress != 0);\r
+      RetPtr = (VOID *) (mVpdBaseAddress + VpdHead->Offset);\r
+\r
       break;\r
-      \r
+\r
     case PCD_TYPE_HII|PCD_TYPE_STRING:\r
     case PCD_TYPE_HII:\r
       if (IsPeiDb) {\r
-        GuidTable = (EFI_GUID *) (&mPcdDatabase->PeiDb.Init.GuidTable[0]);\r
+        GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
       } else {\r
-        GuidTable = (EFI_GUID *) (&mPcdDatabase->DxeDb.Init.GuidTable[0]);\r
+        GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
       }\r
-                              \r
+\r
       VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
       Guid = GuidTable + VariableHead->GuidTableIndex;\r
       Name = (UINT16*)(StringTable + VariableHead->StringIndex);\r
-      \r
+\r
       if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
-           //\r
-               // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of \r
-               // string array in string table.\r
-               //\r
-        StringTableIdx = *(STRING_HEAD*)((UINT8 *) PcdDb + VariableHead->DefaultValueOffset);   \r
-        VaraiableDefaultBuffer = (VOID *) (StringTable + StringTableIdx);     \r
-        Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
-        if (Status == EFI_SUCCESS) {\r
-          if (GetSize == 0) {\r
-            //\r
-            // It is a pointer type. So get the MaxSize reserved for\r
-            // this PCD entry.\r
-            //\r
-            GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
-          }\r
-          CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
-          FreePool (Data);\r
-        }\r
-        RetPtr = (VOID *) VaraiableDefaultBuffer;                \r
+        //\r
+        // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of\r
+        // string array in string table.\r
+        //\r
+        StringTableIdx = *(STRING_HEAD*)((UINT8 *) PcdDb + VariableHead->DefaultValueOffset);\r
+        VaraiableDefaultBuffer = (UINT8 *) (StringTable + StringTableIdx);\r
       } else {\r
         VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;\r
-  \r
-        Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
-        if (Status == EFI_SUCCESS) {\r
+      }\r
+      Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
+      if (Status == EFI_SUCCESS) {\r
+        if (DataSize >= (VariableHead->Offset + GetSize)) {\r
           if (GetSize == 0) {\r
             //\r
             // It is a pointer type. So get the MaxSize reserved for\r
             // this PCD entry.\r
             //\r
             GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
+            if (GetSize > (DataSize - VariableHead->Offset)) {\r
+              //\r
+              // Use actual valid size.\r
+              //\r
+              GetSize = DataSize - VariableHead->Offset;\r
+            }\r
           }\r
+          //\r
+          // If the operation is successful, we copy the data\r
+          // to the default value buffer in the PCD Database.\r
+          // So that we can free the Data allocated in GetHiiVariable.\r
+          //\r
           CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
-          FreePool (Data);\r
         }\r
-        //\r
-        // If the operation is successful, we copy the data\r
-        // to the default value buffer in the PCD Database.\r
-        // So that we can free the Data allocated in GetHiiVariable.\r
-        //\r
-        //\r
-        // If the operation is not successful, \r
-        // Return 1) either the default value specified by Platform Integrator \r
-        //        2) Or the value Set by a PCD set operation.\r
-        //\r
-        RetPtr = (VOID *) VaraiableDefaultBuffer;\r
+        FreePool (Data);\r
       }\r
+      RetPtr = (VOID *) VaraiableDefaultBuffer;\r
       break;\r
 \r
     case PCD_TYPE_STRING:\r
@@ -195,13 +496,13 @@ GetWorker (
     default:\r
       ASSERT (FALSE);\r
       break;\r
-      \r
+\r
   }\r
 \r
   EfiReleaseLock (&mPcdDatabaseLock);\r
-  \r
+\r
   return RetPtr;\r
-  \r
+\r
 }\r
 \r
 /**\r
@@ -209,9 +510,9 @@ GetWorker (
 \r
   This routine will register a callback function to a PCD entry by given token number\r
   and token space guid.\r
-  \r
+\r
   @param TokenNumber        PCD token's number, it is autogened by build tools.\r
-  @param Guid               PCD token space's guid, \r
+  @param Guid               PCD token space's guid,\r
                             if not NULL, this PCD is dynamicEx type PCD.\r
   @param CallBackFunction   Callback function pointer\r
 \r
@@ -259,7 +560,7 @@ DxeRegisterCallBackWorker (
 \r
   FnTableEntry->CallbackFn = CallBackFunction;\r
   InsertTailList (ListHead, &FnTableEntry->Node);\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -311,7 +612,7 @@ DxeUnRegisterCallBackWorker (
       //\r
       RemoveEntryList (ListNode);\r
       FreePool (FnTableEntry);\r
-      \r
+\r
       return EFI_SUCCESS;\r
     }\r
     ListNode = GetNextNode (ListHead, ListNode);\r
@@ -322,16 +623,16 @@ DxeUnRegisterCallBackWorker (
 \r
 /**\r
   Get next token number in given token space.\r
-  \r
+\r
   This routine is used for dynamicEx type PCD. It will firstly scan token space\r
-  table to get token space according to given token space guid. Then scan given \r
-  token number in found token space, if found, then return next token number in \r
+  table to get token space according to given token space guid. Then scan given\r
+  token number in found token space, if found, then return next token number in\r
   this token space.\r
 \r
-  @param Guid            Token space guid. Next token number will be scaned in \r
+  @param Guid            Token space guid. Next token number will be scaned in\r
                          this token space.\r
-  @param TokenNumber     Token number. \r
-                         If PCD_INVALID_TOKEN_NUMBER, return first token number in \r
+  @param TokenNumber     Token number.\r
+                         If PCD_INVALID_TOKEN_NUMBER, return first token number in\r
                          token space table.\r
                          If not PCD_INVALID_TOKEN_NUMBER, return next token number\r
                          in token space table.\r
@@ -359,10 +660,11 @@ ExGetNextTokeNumber (
   UINTN            Index;\r
   UINTN            GuidTableIdx;\r
   BOOLEAN          Found;\r
+  UINTN            ExMapTableCount;\r
 \r
   //\r
-  // Scan token space guid \r
-  // \r
+  // Scan token space guid\r
+  //\r
   MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);\r
   if (MatchGuid == NULL) {\r
     return EFI_NOT_FOUND;\r
@@ -373,7 +675,8 @@ ExGetNextTokeNumber (
   //\r
   Found = FALSE;\r
   GuidTableIdx = MatchGuid - GuidTable;\r
-  for (Index = 0; Index < SizeOfExMapTable; Index++) {\r
+  ExMapTableCount = SizeOfExMapTable / sizeof(ExMapTable[0]);\r
+  for (Index = 0; Index < ExMapTableCount; Index++) {\r
     if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
       Found = TRUE;\r
       break;\r
@@ -390,40 +693,147 @@ ExGetNextTokeNumber (
       return EFI_SUCCESS;\r
     }\r
 \r
-    for ( ; Index < SizeOfExMapTable; Index++) {\r
-      if (ExMapTable[Index].ExTokenNumber == *TokenNumber) {\r
-        Index ++;\r
-        if (Index == SizeOfExMapTable) {\r
-          //\r
-          // Exceed the length of ExMap Table\r
-          //\r
-          *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
-          return EFI_SUCCESS;\r
-        } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
-          //\r
-          // Found the next match\r
-          //\r
-          *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
-          return EFI_SUCCESS;\r
-        } else {\r
-          //\r
-          // Guid has been changed. It is the next Token Space Guid.\r
-          // We should flag no more TokenNumber.\r
-          //\r
-          *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
-          return EFI_SUCCESS;\r
-        }\r
+    for ( ; Index < ExMapTableCount; Index++) {\r
+      if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    while (Index < ExMapTableCount) {\r
+      Index++;\r
+      if (Index == ExMapTableCount) {\r
+        //\r
+        // Exceed the length of ExMap Table\r
+        //\r
+        *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
+        return EFI_NOT_FOUND;\r
+      } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
+        //\r
+        // Found the next match\r
+        //\r
+        *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
+        return EFI_SUCCESS;\r
       }\r
     }\r
   }\r
-  \r
+\r
   return EFI_NOT_FOUND;\r
 }\r
 \r
+/**\r
+  Find the PCD database.\r
+\r
+  @retval The base address of external PCD database binary.\r
+  @retval NULL         Return NULL if not find.\r
+**/\r
+DXE_PCD_DATABASE *\r
+LocateExPcdBinary (\r
+  VOID\r
+)\r
+{\r
+  EFI_STATUS            Status;\r
+\r
+  //\r
+  // Search the External Pcd database from one section of current FFS,\r
+  // and read it to memory\r
+  //\r
+  Status = GetSectionFromFfs (\r
+             EFI_SECTION_RAW,\r
+             0,\r
+             (VOID **) &mDxePcdDbBinary,\r
+             &mDxePcdDbSize\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Check the first bytes (Header Signature Guid) and build version.\r
+  //\r
+  if (!CompareGuid ((VOID *)mDxePcdDbBinary, &gPcdDataBaseSignatureGuid) ||\r
+      (mDxePcdDbBinary->BuildVersion != PCD_SERVICE_DXE_VERSION)) {\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return mDxePcdDbBinary;\r
+}\r
+\r
+/**\r
+  Update PCD database base on current SkuId\r
+\r
+  @param   SkuId     Current SkuId\r
+  @param   IsPeiDb   Whether to update PEI PCD database.\r
+\r
+  @retval EFI_SUCCESS    Update PCD database successfully.\r
+  @retval EFI_NOT_FOUND  Not found PCD database for current SkuId.\r
+**/\r
+EFI_STATUS\r
+UpdatePcdDatabase (\r
+  IN SKU_ID        SkuId,\r
+  IN BOOLEAN       IsPeiDb\r
+  )\r
+{\r
+  UINTN                       Index;\r
+  PCD_DATABASE_SKU_DELTA      *SkuDelta;\r
+  PCD_DATA_DELTA              *SkuDeltaData;\r
+\r
+  if (IsPeiDb && mPeiPcdDbBinary != NULL) {\r
+    //\r
+    // Find the delta data for PEI DB\r
+    //\r
+    Index    = (mPcdDatabase.PeiDb->Length + 7) & (~7);\r
+    SkuDelta = NULL;\r
+    while (Index < mPeiPcdDbSize) {\r
+      SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) mPeiPcdDbBinary + Index);\r
+      if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) {\r
+        break;\r
+      }\r
+      Index = (Index + SkuDelta->Length + 7) & (~7);\r
+    }\r
+\r
+    //\r
+    // Patch the delta data into current PCD database\r
+    //\r
+    if (Index < mPeiPcdDbSize && SkuDelta != NULL) {\r
+      SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1);\r
+      while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) {\r
+        *((UINT8 *) mPcdDatabase.PeiDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value;\r
+        SkuDeltaData ++;\r
+      }\r
+    } else {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Find the delta data for DXE DB\r
+  //\r
+  Index    = (mPcdDatabase.DxeDb->Length + 7) & (~7);\r
+  SkuDelta = NULL;\r
+  while (Index < mDxePcdDbSize) {\r
+    SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) mDxePcdDbBinary + Index);\r
+    if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) {\r
+      break;\r
+    }\r
+    Index = (Index + SkuDelta->Length + 7) & (~7);\r
+  }\r
+\r
+  //\r
+  // Patch the delta data into current PCD database\r
+  //\r
+  if (Index < mDxePcdDbSize && SkuDelta != NULL) {\r
+    SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1);\r
+    while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) {\r
+      *((UINT8 *) mPcdDatabase.DxeDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value;\r
+      SkuDeltaData ++;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
 \r
 /**\r
   Initialize the PCD database in DXE phase.\r
-  \r
+\r
   PCD database in DXE phase also contains PCD database in PEI phase which is copied\r
   from GUID Hob.\r
 \r
@@ -436,46 +846,92 @@ BuildPcdDxeDataBase (
   PEI_PCD_DATABASE    *PeiDatabase;\r
   EFI_HOB_GUID_TYPE   *GuidHob;\r
   UINTN               Index;\r
+  UINT32              PcdDxeDbLen;\r
+  VOID                *PcdDxeDb;\r
+  EFI_STATUS          Status;\r
 \r
-  mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));\r
-  ASSERT (mPcdDatabase != NULL);\r
+  //\r
+  // Assign PCD Entries with default value to PCD DATABASE\r
+  //\r
+  mPcdDatabase.DxeDb = LocateExPcdBinary ();\r
+  ASSERT(mPcdDatabase.DxeDb != NULL);\r
+  PcdDxeDbLen = mPcdDatabase.DxeDb->Length + mPcdDatabase.DxeDb->UninitDataBaseSize;\r
+  PcdDxeDb = AllocateZeroPool (PcdDxeDbLen);\r
+  ASSERT (PcdDxeDb != NULL);\r
+  CopyMem (PcdDxeDb, mPcdDatabase.DxeDb, mPcdDatabase.DxeDb->Length);\r
+  mPcdDatabase.DxeDb = PcdDxeDb;\r
 \r
   GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
   if (GuidHob != NULL) {\r
 \r
     //\r
-    // We will copy over the PEI phase's PCD Database.\r
-    // \r
     // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
     // should not be included at all. So the GuidHob could\r
     // be NULL. If it is NULL, we just copy over the DXE Default\r
     // Value to PCD Database.\r
     //\r
-    \r
     PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
+\r
+    //\r
+    // Get next one that stores full PEI data\r
+    //\r
+    GuidHob = GetNextGuidHob (&gPcdDataBaseHobGuid, GET_NEXT_HOB (GuidHob));\r
+    if (GuidHob != NULL) {\r
+      mPeiPcdDbBinary = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
+      mPeiPcdDbSize   = (UINTN) GET_GUID_HOB_DATA_SIZE (GuidHob);\r
+    }\r
+\r
+    //\r
+    // Assign PCD Entries refereneced in PEI phase to PCD DATABASE\r
     //\r
-    // Copy PCD Entries refereneced in PEI phase to PCD DATABASE\r
+    mPcdDatabase.PeiDb = PeiDatabase;\r
     //\r
-    CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));\r
+    // Inherit the SystemSkuId from PEI phase.\r
+    //\r
+    if (mPcdDatabase.PeiDb->SystemSkuId != 0) {\r
+      Status = UpdatePcdDatabase (mPcdDatabase.PeiDb->SystemSkuId, FALSE);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    mPcdDatabase.DxeDb->SystemSkuId = mPcdDatabase.PeiDb->SystemSkuId;\r
+  } else {\r
+    mPcdDatabase.PeiDb = AllocateZeroPool (sizeof (PEI_PCD_DATABASE));\r
+    ASSERT(mPcdDatabase.PeiDb != NULL);\r
   }\r
 \r
   //\r
-  // Copy PCD Entries with default value to PCD DATABASE\r
+  // Initialized the external PCD database local variables\r
   //\r
-  CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));\r
+  mPeiLocalTokenCount     = mPcdDatabase.PeiDb->LocalTokenCount;\r
+  mDxeLocalTokenCount     = mPcdDatabase.DxeDb->LocalTokenCount;\r
+\r
+  mPeiExMapppingTableSize = mPcdDatabase.PeiDb->ExTokenCount * sizeof (DYNAMICEX_MAPPING);\r
+  mDxeExMapppingTableSize = mPcdDatabase.DxeDb->ExTokenCount * sizeof (DYNAMICEX_MAPPING);\r
+  mPeiGuidTableSize       = mPcdDatabase.PeiDb->GuidTableCount * sizeof(GUID);\r
+  mDxeGuidTableSize       = mPcdDatabase.DxeDb->GuidTableCount * sizeof (GUID);\r
 \r
+  mPcdTotalTokenCount     = mPeiLocalTokenCount + mDxeLocalTokenCount;\r
+  mPeiNexTokenCount       = mPeiLocalTokenCount - mPcdDatabase.PeiDb->ExTokenCount;\r
+  mDxeNexTokenCount       = mDxeLocalTokenCount - mPcdDatabase.DxeDb->ExTokenCount;\r
+\r
+  mPeiExMapTableEmpty     = (mPcdDatabase.PeiDb->ExTokenCount == 0) ? TRUE : FALSE;\r
+  mDxeExMapTableEmpty     = (mPcdDatabase.DxeDb->ExTokenCount == 0) ? TRUE : FALSE;\r
+  mPeiDatabaseEmpty       = (mPeiLocalTokenCount == 0) ? TRUE : FALSE;\r
+\r
+  TmpTokenSpaceBufferCount = mPcdDatabase.PeiDb->ExTokenCount + mPcdDatabase.DxeDb->ExTokenCount;\r
+  TmpTokenSpaceBuffer     = (EFI_GUID **)AllocateZeroPool(TmpTokenSpaceBufferCount * sizeof (EFI_GUID *));\r
 \r
   //\r
   // Initialized the Callback Function Table\r
   //\r
-\r
-  mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));\r
+  mCallbackFnTable = AllocateZeroPool (mPcdTotalTokenCount * sizeof (LIST_ENTRY));\r
   ASSERT(mCallbackFnTable != NULL);\r
-  \r
+\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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
-  for (Index = 0; Index + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Index++) {\r
+  //\r
+  for (Index = 0; Index + 1 < mPcdTotalTokenCount + 1; Index++) {\r
     InitializeListHead (&mCallbackFnTable[Index]);\r
   }\r
 }\r
@@ -485,7 +941,7 @@ BuildPcdDxeDataBase (
 \r
   @param VariableGuid    Variable's guid\r
   @param VariableName    Variable's unicode name string\r
-  @param VariableData    Variable's data pointer, \r
+  @param VariableData    Variable's data pointer,\r
   @param VariableSize    Variable's size.\r
 \r
   @return the status of gRT->GetVariable\r
@@ -504,7 +960,7 @@ GetHiiVariable (
 \r
   Size = 0;\r
   Buffer = NULL;\r
-  \r
+\r
   //\r
   // Firstly get the real size of HII variable\r
   //\r
@@ -515,7 +971,7 @@ GetHiiVariable (
     &Size,\r
     Buffer\r
     );\r
-  \r
+\r
   //\r
   // Allocate buffer to hold whole variable data according to variable size.\r
   //\r
@@ -535,87 +991,19 @@ GetHiiVariable (
     ASSERT (Status == EFI_SUCCESS);\r
     *VariableData = Buffer;\r
     *VariableSize = Size;\r
+  } else {\r
+    //\r
+    // Use Default Data only when variable is not found.\r
+    // For other error status, correct data can't be got, and trig ASSERT().\r
+    //\r
+    ASSERT (Status == EFI_NOT_FOUND);\r
   }\r
 \r
   return Status;\r
 }\r
 \r
 /**\r
-  Find the local token number according to system SKU ID.\r
-\r
-  @param LocalTokenNumber PCD token number\r
-  @param Size             The size of PCD entry.\r
-  @param IsPeiDb          If TRUE, the PCD entry is initialized in PEI phase.\r
-                          If False, the PCD entry is initialized in DXE phase.\r
-\r
-  @return Token number according to system SKU ID.\r
-\r
-**/\r
-UINT32\r
-GetSkuEnabledTokenNumber (\r
-  UINT32    LocalTokenNumber,\r
-  UINTN     Size,\r
-  BOOLEAN   IsPeiDb\r
-  ) \r
-{\r
-  SKU_HEAD              *SkuHead;\r
-  SKU_ID                *SkuIdTable;\r
-  INTN                  Index;\r
-  UINT8                 *Value;\r
-  SKU_ID                *PhaseSkuIdTable;\r
-  UINT8                 *PcdDb;\r
-\r
-  ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
-\r
-  PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
-\r
-  SkuHead     = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
-  Value       = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
-\r
-  PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
-                              mPcdDatabase->DxeDb.Init.SkuIdTable;\r
-                              \r
-  SkuIdTable  = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
-        \r
-  //\r
-  // Find the current system's SKU ID entry in SKU ID table.\r
-  //\r
-  for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
-    if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[Index + 1]) {\r
-      break;\r
-    }\r
-  }\r
-  ASSERT (Index < SkuIdTable[0]);\r
-\r
-  switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
-    case PCD_TYPE_VPD:\r
-      Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);\r
-      return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);\r
-\r
-    case PCD_TYPE_HII:\r
-      Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);\r
-      return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);\r
-\r
-    case PCD_TYPE_STRING:\r
-      Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);\r
-      return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);\r
-      \r
-    case PCD_TYPE_DATA:\r
-      Value += Size * Index;\r
-      return (UINT32) (Value - PcdDb);\r
-\r
-    default:\r
-      ASSERT (FALSE);\r
-  }\r
-\r
-  ASSERT (FALSE);\r
-\r
-  return 0;\r
-  \r
-}\r
-\r
-/**\r
-  Invoke the callback function when dynamic PCD entry was set, if this PCD entry \r
+  Invoke the callback function when dynamic PCD entry was set, if this PCD entry\r
   has registered callback function.\r
 \r
   @param ExTokenNumber   DynamicEx PCD's token number, if this PCD entry is dyanmicEx\r
@@ -651,14 +1039,14 @@ InvokeCallbackOnSet (
   while (ListNode != ListHead) {\r
     FnTableEntry = CR_FNENTRY_FROM_LISTNODE (ListNode, CALLBACK_FN_ENTRY, Node);\r
 \r
-    FnTableEntry->CallbackFn(Guid, \r
+    FnTableEntry->CallbackFn(Guid,\r
                     (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
                     Data,\r
                     Size);\r
-    \r
+\r
     ListNode = GetNextNode (ListHead, ListNode);\r
   }\r
-  \r
+\r
   return;\r
 }\r
 \r
@@ -695,10 +1083,10 @@ SetValueWorker (
 \r
   @retval EFI_INVALID_PARAMETER  If this PCD type is VPD, VPD PCD can not be set.\r
   @retval EFI_INVALID_PARAMETER  If Size can not be set to size table.\r
-  @retval EFI_INVALID_PARAMETER  If Size of non-Ptr type PCD does not match the size information in PCD database.  \r
+  @retval EFI_INVALID_PARAMETER  If Size of non-Ptr type PCD does not match the size information in PCD database.\r
   @retval EFI_NOT_FOUND          If value type of PCD entry is intergrate, but not in\r
                                  range of UINT8, UINT16, UINT32, UINT64\r
-  @retval EFI_NOT_FOUND          Can not find the PCD type according to token number.                                \r
+  @retval EFI_NOT_FOUND          Can not find the PCD type according to token number.\r
 **/\r
 EFI_STATUS\r
 SetWorker (\r
@@ -708,7 +1096,6 @@ SetWorker (
   IN          BOOLEAN                 PtrType\r
   )\r
 {\r
-  UINT32              *LocalTokenNumberTable;\r
   BOOLEAN             IsPeiDb;\r
   UINT32              LocalTokenNumber;\r
   EFI_GUID            *GuidTable;\r
@@ -716,6 +1103,7 @@ SetWorker (
   EFI_GUID            *Guid;\r
   UINT16              *Name;\r
   UINTN               VariableOffset;\r
+  UINT32              Attributes;\r
   VOID                *InternalData;\r
   VARIABLE_HEAD       *VariableHead;\r
   UINTN               Offset;\r
@@ -732,13 +1120,13 @@ SetWorker (
   TokenNumber--;\r
 \r
   TmpTokenNumber = TokenNumber;\r
-  \r
+\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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
   //\r
-  ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
+  ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\r
 \r
   if (PtrType) {\r
     //\r
@@ -757,11 +1145,11 @@ SetWorker (
 \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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
   //\r
-  if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||\r
-      (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {\r
+  if ((TokenNumber + 1 < mPeiNexTokenCount + 1) ||\r
+      (TokenNumber + 1 >= mPeiLocalTokenCount + 1 && TokenNumber + 1 < (mPeiLocalTokenCount + mDxeNexTokenCount + 1))) {\r
     InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
   }\r
 \r
@@ -772,39 +1160,24 @@ SetWorker (
 \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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
   //\r
-  IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
-\r
-  LocalTokenNumberTable  = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
-                                     mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
+  IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
 \r
-  TokenNumber = IsPeiDb ? TokenNumber\r
-                        : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
-\r
-  LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
-  \r
-  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
-    if (PtrType) {\r
-      GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
-    } else {\r
-      MaxSize = *Size;\r
-    }\r
-    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
-  }\r
+  LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);\r
 \r
   Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
 \r
-  PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
+  PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);\r
 \r
   if (IsPeiDb) {\r
-    StringTable = (UINT8 *) (&mPcdDatabase->PeiDb.Init.StringTable[0]);\r
+    StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);\r
   } else {\r
-    StringTable = (UINT8 *) (&mPcdDatabase->DxeDb.Init.StringTable[0]);\r
+    StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);\r
   }\r
 \r
-  \r
+\r
   InternalData = PcdDb + Offset;\r
 \r
   switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
@@ -812,7 +1185,7 @@ SetWorker (
       ASSERT (FALSE);\r
       Status = EFI_INVALID_PARAMETER;\r
       break;\r
-    \r
+\r
     case PCD_TYPE_STRING:\r
       if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
         CopyMem (StringTable + *((STRING_HEAD *)InternalData), Data, *Size);\r
@@ -830,34 +1203,22 @@ SetWorker (
           break;\r
         }\r
       }\r
-      \r
+\r
       if (IsPeiDb) {\r
-        GuidTable = (EFI_GUID *) (&mPcdDatabase->PeiDb.Init.GuidTable[0]);\r
+        GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
       } else {\r
-        GuidTable = (EFI_GUID *) (&mPcdDatabase->DxeDb.Init.GuidTable[0]);\r
+        GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
       }\r
-                              \r
+\r
       VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
-      \r
+\r
       Guid = GuidTable + VariableHead->GuidTableIndex;\r
       Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
       VariableOffset = VariableHead->Offset;\r
-      Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
-      \r
-      if (EFI_NOT_FOUND == Status) {\r
-        if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING))  {\r
-          CopyMem (\r
-            StringTable + *(STRING_HEAD *)(PcdDb + VariableHead->DefaultValueOffset),\r
-            Data,\r
-            *Size\r
-            );\r
-        } else {\r
-          CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
-        } \r
-        Status = EFI_SUCCESS;\r
-      }\r
+      Attributes = VariableHead->Attributes;\r
+      Status = SetHiiVariable (Guid, Name, Attributes, Data, *Size, VariableOffset);\r
       break;\r
-      \r
+\r
     case PCD_TYPE_DATA:\r
       if (PtrType) {\r
         if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
@@ -901,7 +1262,7 @@ SetWorker (
     }\r
 \r
   EfiReleaseLock (&mPcdDatabaseLock);\r
-  \r
+\r
   return Status;\r
 }\r
 \r
@@ -920,7 +1281,7 @@ ExGetWorker (
   IN CONST EFI_GUID         *Guid,\r
   IN UINTN                  ExTokenNumber,\r
   IN UINTN                  GetSize\r
-  ) \r
+  )\r
 {\r
   return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
 }\r
@@ -948,13 +1309,13 @@ ExSetValueWorker (
 }\r
 \r
 /**\r
-  Set value for a dynamic PCD entry.\r
-  \r
-  This routine find the local token number according to dynamic-ex PCD's token \r
+  Set value for a dynamic-ex PCD entry.\r
+\r
+  This routine find the local token number according to dynamic-ex PCD's token\r
   space guid and token number firstly, and invoke callback function if this PCD\r
   entry registered callback function. Finally, invoken general SetWorker to set\r
   PCD value.\r
-  \r
+\r
   @param ExTokenNumber   Dynamic-ex PCD token number.\r
   @param Guid            Token space guid for dynamic-ex PCD.\r
   @param Data            PCD value want to be set\r
@@ -975,7 +1336,7 @@ ExSetWorker (
   )\r
 {\r
   UINTN                   TokenNumber;\r
-  \r
+\r
   TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
 \r
   InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
@@ -984,14 +1345,93 @@ ExSetWorker (
 \r
 }\r
 \r
+/**\r
+  Get variable size and data from HII-type PCDs.\r
+\r
+  @param[in]  VariableGuid   Guid of variable which stored value of a HII-type PCD.\r
+  @param[in]  VariableName   Unicode name of variable which stored value of a HII-type PCD.\r
+  @param[out] VariableSize   Pointer to variable size got from HII-type PCDs.\r
+  @param[out] VariableData   Pointer to variable data got from HII-type PCDs.\r
+\r
+**/\r
+VOID\r
+GetVariableSizeAndDataFromHiiPcd (\r
+  IN EFI_GUID               *VariableGuid,\r
+  IN UINT16                 *VariableName,\r
+  OUT UINTN                 *VariableSize,\r
+  OUT VOID                  *VariableData OPTIONAL\r
+  )\r
+{\r
+  BOOLEAN                   IsPeiDb;\r
+  PCD_DATABASE_INIT         *Database;\r
+  UINTN                     TokenNumber;\r
+  UINT32                    LocalTokenNumber;\r
+  UINTN                     Offset;\r
+  EFI_GUID                  *GuidTable;\r
+  UINT8                     *StringTable;\r
+  VARIABLE_HEAD             *VariableHead;\r
+  EFI_GUID                  *Guid;\r
+  UINT16                    *Name;\r
+  UINTN                     PcdDataSize;\r
+  UINTN                     Size;\r
+  UINT8                     *VaraiableDefaultBuffer;\r
+  STRING_HEAD               StringTableIdx;\r
+\r
+  *VariableSize = 0;\r
+\r
+  //\r
+  // Go through PCD database to find out DynamicHii PCDs.\r
+  //\r
+  for (TokenNumber = 1; TokenNumber <= mPcdTotalTokenCount; TokenNumber++) {\r
+    IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
+    Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
+    LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber);\r
+    if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {\r
+      //\r
+      // Get the Variable Guid and Name pointer.\r
+      //\r
+      Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
+      VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);\r
+      StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);\r
+      GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);\r
+      Guid = GuidTable + VariableHead->GuidTableIndex;\r
+      Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
+      if (CompareGuid (VariableGuid, Guid) && (StrCmp (VariableName, Name) == 0)) {\r
+        //\r
+        // It is the matched DynamicHii PCD.\r
+        //\r
+        PcdDataSize = DxePcdGetSize (TokenNumber);\r
+        Size = VariableHead->Offset + PcdDataSize;\r
+        if (Size > *VariableSize) {\r
+          *VariableSize = Size;\r
+        }\r
+        if (VariableData != NULL) {\r
+          if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
+            //\r
+            // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of\r
+            // string array in string table.\r
+            //\r
+            StringTableIdx = *(STRING_HEAD *) ((UINT8 *) Database + VariableHead->DefaultValueOffset);\r
+            VaraiableDefaultBuffer = (UINT8 *) (StringTable + StringTableIdx);\r
+          } else {\r
+            VaraiableDefaultBuffer = (UINT8 *) Database + VariableHead->DefaultValueOffset;\r
+          }\r
+          CopyMem ((UINT8 *) VariableData + VariableHead->Offset, VaraiableDefaultBuffer, PcdDataSize);\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Set value for HII-type PCD.\r
 \r
-  A HII-type PCD's value is stored in a variable. Setting/Getting the value of \r
+  A HII-type PCD's value is stored in a variable. Setting/Getting the value of\r
   HII-type PCD is to visit this variable.\r
-  \r
+\r
   @param VariableGuid    Guid of variable which stored value of a HII-type PCD.\r
   @param VariableName    Unicode name of variable which stored value of a HII-type PCD.\r
+  @param SetAttributes   Attributes bitmask to set for the variable.\r
   @param Data            Value want to be set.\r
   @param DataSize        Size of value\r
   @param Offset          Value offset of HII-type PCD in variable.\r
@@ -1003,6 +1443,7 @@ EFI_STATUS
 SetHiiVariable (\r
   IN  EFI_GUID     *VariableGuid,\r
   IN  UINT16       *VariableName,\r
+  IN  UINT32       SetAttributes,\r
   IN  CONST VOID   *Data,\r
   IN  UINTN        DataSize,\r
   IN  UINTN        Offset\r
@@ -1027,12 +1468,12 @@ SetHiiVariable (
     &Size,\r
     NULL\r
     );\r
-  \r
+\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     //\r
     // Patch new PCD's value to offset in given HII variable.\r
     //\r
-    if  (Size >= (DataSize + Offset)) {\r
+    if (Size >= (DataSize + Offset)) {\r
       SetSize = Size;\r
     } else {\r
       SetSize = DataSize + Offset;\r
@@ -1047,15 +1488,19 @@ SetHiiVariable (
       &Size,\r
       Buffer\r
       );\r
-    \r
+\r
     ASSERT_EFI_ERROR (Status);\r
 \r
     CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
 \r
+    if (SetAttributes == 0) {\r
+      SetAttributes = Attribute;\r
+    }\r
+\r
     Status = gRT->SetVariable (\r
               VariableName,\r
               VariableGuid,\r
-              Attribute,\r
+              SetAttributes,\r
               SetSize,\r
               Buffer\r
               );\r
@@ -1066,47 +1511,56 @@ SetHiiVariable (
     //\r
     // If variable does not exist, a new variable need to be created.\r
     //\r
-    \r
-    Size = Offset + DataSize;\r
-    \r
+\r
+    //\r
+    // Get size, allocate buffer and get data.\r
+    //\r
+    GetVariableSizeAndDataFromHiiPcd (VariableGuid, VariableName, &Size, NULL);\r
     Buffer = AllocateZeroPool (Size);\r
     ASSERT (Buffer != NULL);\r
-    \r
+    GetVariableSizeAndDataFromHiiPcd (VariableGuid, VariableName, &Size, Buffer);\r
+\r
+    //\r
+    // Update buffer.\r
+    //\r
     CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
-    \r
+\r
+    if (SetAttributes == 0) {\r
+      SetAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
+    }\r
+\r
     Status = gRT->SetVariable (\r
               VariableName,\r
               VariableGuid,\r
-              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+              SetAttributes,\r
               Size,\r
               Buffer\r
               );\r
 \r
     FreePool (Buffer);\r
-    return Status;    \r
+    return Status;\r
   }\r
-  \r
+\r
   //\r
-  // If we drop to here, the value is failed to be written in to variable area\r
-  // So, we will save the data in the PCD Database's volatile area.\r
+  // If we drop to here, the value is failed to be written in to variable area.\r
   //\r
   return Status;\r
 }\r
 \r
 /**\r
-  Get local token number according to dynamic-ex PCD's {token space guid:token number}\r
+  Get Token Number according to dynamic-ex PCD's {token space guid:token number}\r
 \r
   A dynamic-ex type PCD, developer must provide pair of token space guid: token number\r
   in DEC file. PCD database maintain a mapping table that translate pair of {token\r
-  space guid: token number} to local token number.\r
-  \r
+  space guid: token number} to Token Number.\r
+\r
   @param Guid            Token space guid for dynamic-ex PCD entry.\r
   @param ExTokenNumber   Dynamic-ex PCD token number.\r
 \r
-  @return local token number for dynamic-ex PCD.\r
+  @return Token Number for dynamic-ex PCD.\r
 \r
 **/\r
-UINTN           \r
+UINTN\r
 GetExPcdTokenNumber (\r
   IN CONST EFI_GUID             *Guid,\r
   IN UINT32                     ExTokenNumber\r
@@ -1118,29 +1572,29 @@ GetExPcdTokenNumber (
   EFI_GUID            *MatchGuid;\r
   UINTN               MatchGuidIdx;\r
 \r
-  if (!PEI_DATABASE_EMPTY) {\r
-    ExMap       = mPcdDatabase->PeiDb.Init.ExMapTable;\r
-    GuidTable   = mPcdDatabase->PeiDb.Init.GuidTable;\r
-    \r
-    MatchGuid   = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
-    \r
+  if (!mPeiDatabaseEmpty) {\r
+    ExMap       = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset);\r
+    GuidTable   = (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);\r
+\r
+    MatchGuid   = ScanGuid (GuidTable, mPeiGuidTableSize, Guid);\r
+\r
     if (MatchGuid != NULL) {\r
 \r
       MatchGuidIdx = MatchGuid - GuidTable;\r
-      \r
-      for (Index = 0; Index < PEI_EXMAPPING_TABLE_SIZE; Index++) {\r
+\r
+      for (Index = 0; Index < mPcdDatabase.PeiDb->ExTokenCount; Index++) {\r
         if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
             (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
-            return ExMap[Index].LocalTokenNumber;\r
+            return ExMap[Index].TokenNumber;\r
         }\r
       }\r
     }\r
   }\r
-  \r
-  ExMap       = mPcdDatabase->DxeDb.Init.ExMapTable;\r
-  GuidTable   = mPcdDatabase->DxeDb.Init.GuidTable;\r
 \r
-  MatchGuid   = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
+  ExMap       = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset);\r
+  GuidTable   = (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);\r
+\r
+  MatchGuid   = ScanGuid (GuidTable, mDxeGuidTableSize, 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
@@ -1148,11 +1602,11 @@ GetExPcdTokenNumber (
   ASSERT (MatchGuid != NULL);\r
 \r
   MatchGuidIdx = MatchGuid - GuidTable;\r
-  \r
-  for (Index = 0; Index < DXE_EXMAPPING_TABLE_SIZE; Index++) {\r
+\r
+  for (Index = 0; Index < mPcdDatabase.DxeDb->ExTokenCount; Index++) {\r
     if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&\r
          (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {\r
-        return ExMap[Index].LocalTokenNumber;\r
+        return ExMap[Index].TokenNumber;\r
     }\r
   }\r
 \r
@@ -1161,44 +1615,9 @@ GetExPcdTokenNumber (
   return 0;\r
 }\r
 \r
-/**\r
-  Get SKU ID table from PCD database.\r
-\r
-  @param LocalTokenNumberTableIdx Index of local token number in token number table.\r
-  @param IsPeiPcd                 If TRUE, \r
-\r
-  @return Pointer to SKU ID array table\r
-\r
-**/\r
-SKU_ID *\r
-GetSkuIdArray (\r
-  IN    UINTN             LocalTokenNumberTableIdx,\r
-  IN    BOOLEAN           IsPeiPcd\r
-  )\r
-{\r
-  SKU_HEAD  *SkuHead;\r
-  UINTN     LocalTokenNumber;\r
-  UINT8     *Database;\r
-\r
-  if (IsPeiPcd) {\r
-    LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
-    Database         = (UINT8 *) &mPcdDatabase->PeiDb;\r
-  } else {\r
-    LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];\r
-    Database         = (UINT8 *) &mPcdDatabase->DxeDb;\r
-  }\r
-\r
-  ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
-\r
-  SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
-\r
-  return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
-  \r
-}\r
-\r
 /**\r
   Wrapper function of getting index of PCD entry in size table.\r
-  \r
+\r
   @param LocalTokenNumberTableIdx Index of this PCD in local token number table.\r
   @param IsPeiDb                  If TRUE, the pcd entry is initialized in PEI phase,\r
                                   If FALSE, the pcd entry is initialized in DXE phase.\r
@@ -1215,12 +1634,11 @@ GetSizeTableIndex (
   UINTN  LocalTokenNumber;\r
   UINTN  Index;\r
   UINTN  SizeTableIdx;\r
-  SKU_ID *SkuIdTable;\r
-  \r
+\r
   if (IsPeiDb) {\r
-    LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
+    LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
   } else {\r
-    LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
+    LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
   }\r
 \r
   SizeTableIdx = 0;\r
@@ -1230,39 +1648,30 @@ GetSizeTableIndex (
 \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
+      // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type\r
       // PCD entry.\r
       //\r
       if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
           //\r
-          // We have only one entry for VPD enabled PCD entry:\r
+          // We have only two entry for VPD enabled PCD entry:\r
           // 1) MAX Size.\r
-          // We consider current size is equal to MAX size.\r
+          // 2) Current Size\r
+          // Current size is equal to MAX size.\r
           //\r
-          SizeTableIdx++;\r
+          SizeTableIdx += 2;\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 (Index, IsPeiDb);\r
-          SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
-        }\r
       }\r
     }\r
 \r
   }\r
 \r
-  return SizeTableIdx;  \r
+  return SizeTableIdx;\r
 }\r
 \r
 /**\r
@@ -1282,67 +1691,51 @@ GetPtrTypeSize (
 {\r
   INTN        SizeTableIdx;\r
   UINTN       LocalTokenNumber;\r
-  SKU_ID      *SkuIdTable;\r
   SIZE_INFO   *SizeTable;\r
-  UINTN       Index;\r
   BOOLEAN     IsPeiDb;\r
   UINT32      *LocalTokenNumberTable;\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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
-  IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
+  IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);\r
 \r
 \r
   if (IsPeiDb) {\r
-    LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
-    SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
+    LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
+    SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);\r
   } else {\r
-    LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
-    LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
-    SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
+    LocalTokenNumberTableIdx -= mPeiLocalTokenCount;\r
+    LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
+    SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);\r
   }\r
 \r
   LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
 \r
   ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
-  \r
+\r
   SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
 \r
   *MaxSize = SizeTable[SizeTableIdx];\r
   //\r
-  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
+  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type\r
   // PCD entry.\r
   //\r
   if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
       //\r
-      // We have only one entry for VPD enabled PCD entry:\r
+      // We have only two entry for VPD enabled PCD entry:\r
       // 1) MAX Size.\r
+      // 2) Current Size\r
       // We consider current size is equal to MAX size.\r
       //\r
       return *MaxSize;\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
       return SizeTable[SizeTableIdx + 1];\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 (LocalTokenNumberTableIdx, IsPeiDb);\r
-      for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
-        if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
-          return SizeTable[SizeTableIdx + 1 + Index];\r
-        }\r
-      }\r
-      return SizeTable[SizeTableIdx + 1];\r
-    }\r
   }\r
 }\r
 \r
@@ -1364,38 +1757,36 @@ SetPtrTypeSize (
 {\r
   INTN        SizeTableIdx;\r
   UINTN       LocalTokenNumber;\r
-  SKU_ID      *SkuIdTable;\r
   SIZE_INFO   *SizeTable;\r
-  UINTN       Index;\r
   UINTN       MaxSize;\r
   BOOLEAN     IsPeiDb;\r
   UINT32      *LocalTokenNumberTable;\r
 \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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
   //\r
-  IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
+  IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);\r
 \r
   if (IsPeiDb) {\r
-    LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
-    SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
+    LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);\r
+    SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);\r
   } else {\r
-    LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
-    LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
-    SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
+    LocalTokenNumberTableIdx -= mPeiLocalTokenCount;\r
+    LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
+    SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);\r
   }\r
 \r
   LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
 \r
   ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
-  \r
+\r
   SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
 \r
   MaxSize = SizeTable[SizeTableIdx];\r
   //\r
-  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
+  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type\r
   // PCD entry.\r
   //\r
   if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {\r
@@ -1409,31 +1800,102 @@ SetPtrTypeSize (
       (*CurrentSize == MAX_ADDRESS)) {\r
        *CurrentSize = MaxSize;\r
        return FALSE;\r
-    } \r
-    \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
-      SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
-      return TRUE;\r
+    }\r
+\r
+    //\r
+    // We have only two entry for Non-Sku enabled PCD entry:\r
+    // 1) MAX SIZE\r
+    // 2) Current Size\r
+    //\r
+    SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+/**\r
+  VariableLock DynamicHiiPcd.\r
+\r
+  @param[in] IsPeiDb        If TRUE, the pcd entry is initialized in PEI phase,\r
+                            If FALSE, the pcd entry is initialized in DXE phase.\r
+  @param[in] VariableLock   Pointer to VariableLockProtocol.\r
+\r
+**/\r
+VOID\r
+VariableLockDynamicHiiPcd (\r
+  IN BOOLEAN                        IsPeiDb,\r
+  IN EDKII_VARIABLE_LOCK_PROTOCOL   *VariableLock\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  PCD_DATABASE_INIT         *Database;\r
+  UINT32                    LocalTokenCount;\r
+  UINTN                     TokenNumber;\r
+  UINT32                    LocalTokenNumber;\r
+  UINTN                     Offset;\r
+  EFI_GUID                  *GuidTable;\r
+  UINT8                     *StringTable;\r
+  VARIABLE_HEAD             *VariableHead;\r
+  EFI_GUID                  *Guid;\r
+  UINT16                    *Name;\r
+\r
+  Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
+  LocalTokenCount = IsPeiDb ? mPeiLocalTokenCount: mDxeLocalTokenCount;\r
+\r
+  //\r
+  // Go through PCD database to find out DynamicHii PCDs.\r
+  //\r
+  for (TokenNumber = 1; TokenNumber <= LocalTokenCount; TokenNumber++) {\r
+    if (IsPeiDb) {\r
+      LocalTokenNumber = GetLocalTokenNumber (TRUE, TokenNumber);\r
     } else {\r
+      LocalTokenNumber = GetLocalTokenNumber (FALSE, TokenNumber + mPeiLocalTokenCount);\r
+    }\r
+    if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {\r
+      Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
+      VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);\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
+      // Why not to set property by VarCheckProtocol with Attributes and Property directly here?\r
+      // It is because that set property by VarCheckProtocol will indicate the variable to\r
+      // be a system variable, but the unknown max size of the variable is dangerous to\r
+      // the system variable region.\r
       //\r
-      SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
-      for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
-        if (SkuIdTable[1 + Index] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
-          SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;\r
-          return TRUE;\r
-        }\r
+      if ((VariableHead->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0) {\r
+        //\r
+        // DynamicHii PCD with RO property set in *.dsc.\r
+        //\r
+        StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);\r
+        GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);\r
+        Guid = GuidTable + VariableHead->GuidTableIndex;\r
+        Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
+        Status = VariableLock->RequestToLock (VariableLock, Name, Guid);\r
+        ASSERT_EFI_ERROR (Status);\r
       }\r
-      SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
-      return TRUE;\r
     }\r
   }\r
 }\r
+\r
+/**\r
+  VariableLockProtocol callback\r
+  to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.\r
+\r
+  @param[in] Event      Event whose notification function is being invoked.\r
+  @param[in] Context    Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VariableLockCallBack (\r
+  IN EFI_EVENT          Event,\r
+  IN VOID               *Context\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;\r
+\r
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+  if (!EFI_ERROR (Status)) {\r
+    VariableLockDynamicHiiPcd (TRUE, VariableLock);\r
+    VariableLockDynamicHiiPcd (FALSE, VariableLock);\r
+  }\r
+}\r
+\r