]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/PCD/Dxe/Pcd.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Pcd.c
index 861de0fa842680deb6394dafcbf40529d3fba704..855ba3cceb770e09186316b0c20a7ee8cefb4a6f 100644 (file)
@@ -1,30 +1,25 @@
 /** @file\r
-PCD DXE driver\r
+  PCD DXE driver manage all PCD entry initialized in PEI phase and DXE phase, and\r
+  produce the implementation of native PCD protocol and EFI_PCD_PROTOCOL defined in\r
+  PI 1.4a Vol3.\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-\r
-Module Name: Pcd.c\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-//\r
-// Include common header file for this module.\r
-//\r
-#include "CommonHeader.h"\r
-\r
 #include "Service.h"\r
 \r
-EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_CALLBACK);\r
+///\r
+/// PCD database lock.\r
+///\r
+EFI_LOCK  mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
 \r
-PCD_PROTOCOL mPcdInstance = {\r
+///\r
+/// PCD_PROTOCOL the EDKII native implementation which support dynamic\r
+/// type and dynamicEx type PCDs.\r
+///\r
+PCD_PROTOCOL  mPcdInstance = {\r
   DxePcdSetSku,\r
 \r
   DxePcdGet8,\r
@@ -63,20 +58,73 @@ PCD_PROTOCOL mPcdInstance = {
   DxePcdGetNextTokenSpace\r
 };\r
 \r
+///\r
+/// EFI_PCD_PROTOCOL is defined in PI 1.2 Vol 3 which only support dynamicEx type\r
+/// PCD.\r
+///\r
+EFI_PCD_PROTOCOL  mEfiPcdInstance = {\r
+  DxePcdSetSku,\r
+  DxePcdGet8Ex,\r
+  DxePcdGet16Ex,\r
+  DxePcdGet32Ex,\r
+  DxePcdGet64Ex,\r
+  DxePcdGetPtrEx,\r
+  DxePcdGetBoolEx,\r
+  DxePcdGetSizeEx,\r
+  DxePcdSet8Ex,\r
+  DxePcdSet16Ex,\r
+  DxePcdSet32Ex,\r
+  DxePcdSet64Ex,\r
+  DxePcdSetPtrEx,\r
+  DxePcdSetBoolEx,\r
+  (EFI_PCD_PROTOCOL_CALLBACK_ON_SET)DxeRegisterCallBackOnSet,\r
+  (EFI_PCD_PROTOCOL_CANCEL_CALLBACK)DxeUnRegisterCallBackOnSet,\r
+  DxePcdGetNextToken,\r
+  DxePcdGetNextTokenSpace\r
+};\r
+\r
+///\r
+/// Instance of GET_PCD_INFO_PROTOCOL protocol is EDKII native implementation.\r
+/// This protocol instance support dynamic and dynamicEx type PCDs.\r
+///\r
+GET_PCD_INFO_PROTOCOL  mGetPcdInfoInstance = {\r
+  DxeGetPcdInfoGetInfo,\r
+  DxeGetPcdInfoGetInfoEx,\r
+  DxeGetPcdInfoGetSku\r
+};\r
 \r
-//\r
-// Static global to reduce the code size\r
-//\r
-static EFI_HANDLE mNewHandle = NULL;\r
+///\r
+/// Instance of EFI_GET_PCD_INFO_PROTOCOL which is defined in PI 1.2.1 Vol 3.\r
+/// This PPI instance only support dyanmicEx type PCD.\r
+///\r
+EFI_GET_PCD_INFO_PROTOCOL  mEfiGetPcdInfoInstance = {\r
+  DxeGetPcdInfoGetInfoEx,\r
+  DxeGetPcdInfoGetSku\r
+};\r
+\r
+EFI_HANDLE  mPcdHandle      = NULL;\r
+UINTN       mVpdBaseAddress = 0;\r
+\r
+/**\r
+  Main entry for PCD DXE driver.\r
+\r
+  This routine initialize the PCD database and install PCD_PROTOCOL.\r
 \r
+  @param ImageHandle     Image handle for PCD DXE driver.\r
+  @param SystemTable     Pointer to SystemTable.\r
+\r
+  @return Status of gBS->InstallProtocolInterface()\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 PcdDxeInit (\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
+  EFI_STATUS  Status;\r
+  VOID        *Registration;\r
 \r
   //\r
   // Make sure the Pcd Protocol is not already installed in the system\r
@@ -86,110 +134,348 @@ PcdDxeInit (
 \r
   BuildPcdDxeDataBase ();\r
 \r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mNewHandle,\r
+  //\r
+  // Install PCD_PROTOCOL to handle dynamic type PCD\r
+  // Install EFI_PCD_PROTOCOL to handle dynamicEx type PCD\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mPcdHandle,\r
                   &gPcdProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &mPcdInstance\r
+                  &mPcdInstance,\r
+                  &gEfiPcdProtocolGuid,\r
+                  &mEfiPcdInstance,\r
+                  NULL\r
                   );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Install GET_PCD_INFO_PROTOCOL to handle dynamic type PCD\r
+  // Install EFI_GET_PCD_INFO_PROTOCOL to handle dynamicEx type PCD\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mPcdHandle,\r
+                  &gGetPcdInfoProtocolGuid,\r
+                  &mGetPcdInfoInstance,\r
+                  &gEfiGetPcdInfoProtocolGuid,\r
+                  &mEfiGetPcdInfoInstance,\r
+                  NULL\r
+                  );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  return EFI_SUCCESS;\r
+  //\r
+  // Register callback function upon VariableLockProtocol\r
+  // to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.\r
+  //\r
+  EfiCreateProtocolNotifyEvent (\r
+    &gEdkiiVariableLockProtocolGuid,\r
+    TPL_CALLBACK,\r
+    VariableLockCallBack,\r
+    NULL,\r
+    &Registration\r
+    );\r
 \r
+  //\r
+  // Cache VpdBaseAddress in entry point for the following usage.\r
+  //\r
+\r
+  //\r
+  // PcdVpdBaseAddress64 is DynamicEx PCD only. So, DxePcdGet64Ex() is used to get its value.\r
+  //\r
+  mVpdBaseAddress = (UINTN)DxePcdGet64Ex (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdVpdBaseAddress64));\r
+  if (mVpdBaseAddress == 0) {\r
+    //\r
+    // PcdVpdBaseAddress64 is not set, get value from PcdVpdBaseAddress.\r
+    //\r
+    mVpdBaseAddress = (UINTN)PcdGet32 (PcdVpdBaseAddress);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Retrieve additional information associated with a PCD token in the default token space.\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]    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
+EFIAPI\r
+DxeGetPcdInfoGetInfo (\r
+  IN        UINTN         TokenNumber,\r
+  OUT       EFI_PCD_INFO  *PcdInfo\r
+  )\r
+{\r
+  return DxeGetPcdInfo (NULL, TokenNumber, PcdInfo);\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
+EFIAPI\r
+DxeGetPcdInfoGetInfoEx (\r
+  IN CONST  EFI_GUID      *Guid,\r
+  IN        UINTN         TokenNumber,\r
+  OUT       EFI_PCD_INFO  *PcdInfo\r
+  )\r
+{\r
+  return DxeGetPcdInfo (Guid, TokenNumber, PcdInfo);\r
+}\r
+\r
+/**\r
+  Retrieve the currently set SKU Id.\r
+\r
+  @return   The currently set SKU Id. If the platform has not set at a SKU Id, then the\r
+            default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU\r
+            Id is returned.\r
+**/\r
+UINTN\r
+EFIAPI\r
+DxeGetPcdInfoGetSku (\r
+  VOID\r
+  )\r
+{\r
+  return (UINTN)mPcdDatabase.DxeDb->SystemSkuId;\r
+}\r
+\r
+/**\r
+  Sets the SKU value for subsequent calls to set or get PCD token values.\r
+\r
+  SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.\r
+  SetSku() is normally called only once by the system.\r
+\r
+  For each item (token), the database can hold a single value that applies to all SKUs,\r
+  or multiple values, where each value is associated with a specific SKU Id. Items with multiple,\r
+  SKU-specific values are called SKU enabled.\r
+\r
+  The SKU Id of zero is reserved as a default.\r
+  For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the\r
+  single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the\r
+  last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,\r
+  the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been\r
+  set for that Id, the results are unpredictable.\r
+\r
+  @param[in]  SkuId The SKU value that will be used when the PCD service will retrieve and\r
+              set values associated with a PCD token.\r
+\r
+**/\r
 VOID\r
 EFIAPI\r
 DxePcdSetSku (\r
-  IN  UINTN         SkuId\r
+  IN  UINTN  SkuId\r
   )\r
 {\r
-  mPcdDatabase->PeiDb.Init.SystemSkuId = (SKU_ID) SkuId;\r
-  \r
+  SKU_ID      *SkuIdTable;\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  DEBUG ((DEBUG_INFO, "PcdDxe - SkuId 0x%lx is to be set.\n", (SKU_ID)SkuId));\r
+\r
+  if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) {\r
+    //\r
+    // The input SKU Id is equal to current SKU Id, return directly.\r
+    //\r
+    DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is same to current system Sku.\n"));\r
+    return;\r
+  }\r
+\r
+  if (mPcdDatabase.DxeDb->SystemSkuId != (SKU_ID)0) {\r
+    DEBUG ((DEBUG_ERROR, "PcdDxe - The SKU Id could be changed only once."));\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "PcdDxe - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",\r
+      mPcdDatabase.DxeDb->SystemSkuId,\r
+      (SKU_ID)SkuId\r
+      ));\r
+    ASSERT (FALSE);\r
+    return;\r
+  }\r
+\r
+  SkuIdTable = (SKU_ID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SkuIdTableOffset);\r
+  for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
+    if (SkuId == SkuIdTable[Index + 1]) {\r
+      DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is found in SkuId table.\n"));\r
+      Status = UpdatePcdDatabase (SkuId, TRUE);\r
+      if (!EFI_ERROR (Status)) {\r
+        mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID)SkuId;\r
+        DEBUG ((DEBUG_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID)SkuId));\r
+        return;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Invalid input SkuId, the default SKU Id will be still used for the system.\r
+  //\r
+  DEBUG ((DEBUG_ERROR, "PcdDxe - Invalid input SkuId, the default SKU Id will be still used.\n"));\r
   return;\r
 }\r
 \r
+/**\r
+  Retrieves an 8-bit value for a given PCD token.\r
+\r
+  Retrieves the current byte-sized value for a PCD token number.\r
+  If the TokenNumber is invalid, the results are unpredictable.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
 \r
+  @return The UINT8 value.\r
+\r
+**/\r
 UINT8\r
 EFIAPI\r
 DxePcdGet8 (\r
-  IN UINTN                    TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
-  return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));\r
+  return *((UINT8 *)GetWorker (TokenNumber, sizeof (UINT8)));\r
 }\r
 \r
+/**\r
+  Retrieves an 16-bit value for a given PCD token.\r
+\r
+  Retrieves the current 16-bits value for a PCD token number.\r
+  If the TokenNumber is invalid, the results are unpredictable.\r
+\r
+  @param[in]  TokenNumber The PCD token number.\r
 \r
+  @return The UINT16 value.\r
 \r
+**/\r
 UINT16\r
 EFIAPI\r
 DxePcdGet16 (\r
-  IN UINTN                    TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
   return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));\r
 }\r
 \r
+/**\r
+  Retrieves an 32-bit value for a given PCD token.\r
+\r
+  Retrieves the current 32-bits value for a PCD token number.\r
+  If the TokenNumber is invalid, the results are unpredictable.\r
+\r
+  @param[in]  TokenNumber The PCD token number.\r
 \r
+  @return The UINT32 value.\r
 \r
+**/\r
 UINT32\r
 EFIAPI\r
 DxePcdGet32 (\r
-  IN UINTN                    TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
   return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));\r
 }\r
 \r
+/**\r
+  Retrieves an 64-bit value for a given PCD token.\r
+\r
+  Retrieves the current 64-bits value for a PCD token number.\r
+  If the TokenNumber is invalid, the results are unpredictable.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
 \r
+  @return The UINT64 value.\r
+\r
+**/\r
 UINT64\r
 EFIAPI\r
 DxePcdGet64 (\r
-  IN UINTN                     TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
-  return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64)));\r
+  return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));\r
 }\r
 \r
+/**\r
+  Retrieves a pointer to a value for a given PCD token.\r
 \r
+  Retrieves the current pointer to the buffer for a PCD token number.\r
+  Do not make any assumptions about the alignment of the pointer that\r
+  is returned by this function call.  If the TokenNumber is invalid,\r
+  the results are unpredictable.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+\r
+  @return The pointer to the buffer to be retrived.\r
+\r
+**/\r
 VOID *\r
 EFIAPI\r
 DxePcdGetPtr (\r
-  IN UINTN                     TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
   return GetWorker (TokenNumber, 0);\r
 }\r
 \r
+/**\r
+  Retrieves a Boolean value for a given PCD token.\r
 \r
+  Retrieves the current boolean value for a PCD token number.\r
+  Do not make any assumptions about the alignment of the pointer that\r
+  is returned by this function call.  If the TokenNumber is invalid,\r
+  the results are unpredictable.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+\r
+  @return The Boolean value.\r
+\r
+**/\r
 BOOLEAN\r
 EFIAPI\r
 DxePcdGetBool (\r
-  IN UINTN                     TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
-  return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));\r
+  return *((BOOLEAN *)GetWorker (TokenNumber, sizeof (BOOLEAN)));\r
 }\r
 \r
+/**\r
+  Retrieves the size of the value for a given PCD token.\r
+\r
+  Retrieves the current size of a particular PCD token.\r
+  If the TokenNumber is invalid, the results are unpredictable.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
 \r
+  @return The size of the value for the PCD token.\r
+\r
+**/\r
 UINTN\r
 EFIAPI\r
 DxePcdGetSize (\r
-  IN UINTN                     TokenNumber\r
+  IN UINTN  TokenNumber\r
   )\r
 {\r
-  UINTN   Size;\r
-  UINT32  *LocalTokenNumberTable;\r
-  BOOLEAN IsPeiDb;\r
-  UINTN   MaxSize;\r
-  UINTN   TmpTokenNumber;\r
+  UINTN    Size;\r
+  UINT32   *LocalTokenNumberTable;\r
+  BOOLEAN  IsPeiDb;\r
+  UINTN    MaxSize;\r
+  UINTN    TmpTokenNumber;\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
@@ -199,24 +485,24 @@ DxePcdGetSize (
 \r
   //\r
   // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber\r
-  // \r
+  //\r
   TmpTokenNumber = 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
+  // between UINTN and 0 . So we add 1 in each size of the\r
   // comparison.\r
-  ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
+  ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);\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);\r
-  \r
-  TokenNumber = IsPeiDb ? TokenNumber : \r
-                          (TokenNumber - PEI_LOCAL_TOKEN_NUMBER);\r
+  IsPeiDb = (BOOLEAN)(TokenNumber + 1 < mPeiLocalTokenCount + 1);\r
+\r
+  TokenNumber = IsPeiDb ? TokenNumber :\r
+                (TokenNumber - mPeiLocalTokenCount);\r
 \r
-  LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable \r
-                                  : mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
+  LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset)\r
+                                  : (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);\r
 \r
   Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;\r
 \r
@@ -228,260 +514,553 @@ DxePcdGetSize (
   } else {\r
     return Size;\r
   }\r
-\r
 }\r
 \r
+/**\r
+  Retrieves an 8-bit value for a given PCD token.\r
+\r
+  Retrieves the 8-bit value of a particular PCD token.\r
+  If the TokenNumber is invalid or the token space\r
+  specified by Guid does not exist, the results are\r
+  unpredictable.\r
 \r
+  @param[in]  Guid          The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
 \r
+  @return The size 8-bit value for the PCD token.\r
+\r
+**/\r
 UINT8\r
 EFIAPI\r
 DxePcdGet8Ex (\r
-  IN CONST EFI_GUID         *Guid,\r
-  IN UINTN                 ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof(UINT8)));\r
+  return *((UINT8 *)ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));\r
 }\r
 \r
+/**\r
+  Retrieves an 16-bit value for a given PCD token.\r
+\r
+  Retrieves the 16-bit value of a particular PCD token.\r
+  If the TokenNumber is invalid or the token space\r
+  specified by Guid does not exist, the results are\r
+  unpredictable.\r
+\r
+  @param[in]  Guid The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
 \r
+  @return The size 16-bit value for the PCD token.\r
 \r
+**/\r
 UINT16\r
 EFIAPI\r
 DxePcdGet16Ex (\r
-  IN CONST EFI_GUID        *Guid,\r
-  IN UINTN                ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT16)));\r
+  return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));\r
 }\r
 \r
+/**\r
+  Retrieves an 32-bit value for a given PCD token.\r
+\r
+  Retrieves the 32-bit value of a particular PCD token.\r
+  If the TokenNumber is invalid or the token space\r
+  specified by Guid does not exist, the results are\r
+  unpredictable.\r
 \r
+  @param[in]  Guid The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
 \r
+  @return The size 32-bit value for the PCD token.\r
+\r
+**/\r
 UINT32\r
 EFIAPI\r
 DxePcdGet32Ex (\r
-  IN CONST EFI_GUID        *Guid,\r
-  IN UINTN                 ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT32)));\r
+  return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));\r
 }\r
 \r
+/**\r
+  Retrieves an 64-bit value for a given PCD token.\r
 \r
+  Retrieves the 64-bit value of a particular PCD token.\r
+  If the TokenNumber is invalid or the token space\r
+  specified by Guid does not exist, the results are\r
+  unpredictable.\r
 \r
+  @param[in]  Guid The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+\r
+  @return The size 64-bit value for the PCD token.\r
+\r
+**/\r
 UINT64\r
 EFIAPI\r
 DxePcdGet64Ex (\r
-  IN CONST EFI_GUID        *Guid,\r
-  IN UINTN                 ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64)));\r
+  return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));\r
 }\r
 \r
+/**\r
+  Retrieves a pointer to a value for a given PCD token.\r
 \r
+  Retrieves the current pointer to the buffer for a PCD token number.\r
+  Do not make any assumptions about the alignment of the pointer that\r
+  is returned by this function call.  If the TokenNumber is invalid,\r
+  the results are unpredictable.\r
 \r
+  @param[in]  Guid The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+\r
+  @return The pointer to the buffer to be retrived.\r
+\r
+**/\r
 VOID *\r
 EFIAPI\r
 DxePcdGetPtrEx (\r
-  IN CONST EFI_GUID        *Guid,\r
-  IN UINTN                 ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return  ExGetWorker (Guid, ExTokenNumber, 0);\r
+  return ExGetWorker (Guid, ExTokenNumber, 0);\r
 }\r
 \r
+/**\r
+  Retrieves an Boolean value for a given PCD token.\r
+\r
+  Retrieves the Boolean value of a particular PCD token.\r
+  If the TokenNumber is invalid or the token space\r
+  specified by Guid does not exist, the results are\r
+  unpredictable.\r
 \r
+  @param[in]  Guid The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
 \r
+  @return The size Boolean value for the PCD token.\r
+\r
+**/\r
 BOOLEAN\r
 EFIAPI\r
 DxePcdGetBoolEx (\r
-  IN CONST EFI_GUID        *Guid,\r
-  IN UINTN                 ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof(BOOLEAN)));\r
+  return *((BOOLEAN *)ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));\r
 }\r
 \r
+/**\r
+  Retrieves the size of the value for a given PCD token.\r
+\r
+  Retrieves the current size of a particular PCD token.\r
+  If the TokenNumber is invalid, the results are unpredictable.\r
+\r
+  @param[in]  Guid The token space for the token number.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
 \r
+  @return The size of the value for the PCD token.\r
 \r
+**/\r
 UINTN\r
 EFIAPI\r
 DxePcdGetSizeEx (\r
-  IN CONST EFI_GUID        *Guid,\r
-  IN UINTN                 ExTokenNumber\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber\r
   )\r
 {\r
-  return DxePcdGetSize(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber));\r
+  return DxePcdGetSize (GetExPcdTokenNumber (Guid, (UINT32)ExTokenNumber));\r
 }\r
 \r
+/**\r
+  Sets an 8-bit value for a given PCD token.\r
+\r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
 \r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet8 (\r
-  IN UINTN              TokenNumber,\r
-  IN UINT8              Value\r
+  IN UINTN  TokenNumber,\r
+  IN UINT8  Value\r
   )\r
 {\r
   return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 16-bit value for a given PCD token.\r
 \r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
+\r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet16 (\r
-  IN UINTN              TokenNumber,\r
-  IN UINT16             Value\r
+  IN UINTN   TokenNumber,\r
+  IN UINT16  Value\r
   )\r
 {\r
   return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 32-bit value for a given PCD token.\r
 \r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
+\r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet32 (\r
-  IN UINTN              TokenNumber,\r
-  IN UINT32             Value\r
+  IN UINTN   TokenNumber,\r
+  IN UINT32  Value\r
   )\r
 {\r
   return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 64-bit value for a given PCD token.\r
+\r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
 \r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet64 (\r
-  IN UINTN              TokenNumber,\r
-  IN UINT64             Value\r
+  IN UINTN   TokenNumber,\r
+  IN UINT64  Value\r
   )\r
 {\r
   return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets a value of a specified size for a given PCD token.\r
+\r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
+\r
+  @param[in]  TokenNumber The PCD token number.\r
+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.\r
+                              On input, if the SizeOfValue is greater than the maximum size supported\r
+                              for this TokenNumber then the output value of SizeOfValue will reflect\r
+                              the maximum size supported for this TokenNumber.\r
+  @param[in]  Buffer The buffer to set for the PCD token.\r
 \r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
 \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSetPtr (\r
-  IN          UINTN              TokenNumber,\r
-  IN OUT      UINTN              *SizeOfBuffer,\r
-  IN          VOID               *Buffer\r
+  IN          UINTN  TokenNumber,\r
+  IN OUT      UINTN  *SizeOfBuffer,\r
+  IN          VOID   *Buffer\r
   )\r
 {\r
   return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);\r
 }\r
 \r
+/**\r
+  Sets an Boolean value for a given PCD token.\r
+\r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  TokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
 \r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSetBool (\r
-  IN UINTN              TokenNumber,\r
-  IN BOOLEAN            Value\r
+  IN UINTN    TokenNumber,\r
+  IN BOOLEAN  Value\r
   )\r
 {\r
   return SetValueWorker (TokenNumber, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 8-bit value for a given PCD token.\r
 \r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
+\r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet8Ex (\r
-  IN CONST EFI_GUID         *Guid,\r
-  IN UINTN                  ExTokenNumber,\r
-  IN UINT8                  Value\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber,\r
+  IN UINT8           Value\r
   )\r
 {\r
-  return  ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 16-bit value for a given PCD token.\r
 \r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
+\r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet16Ex (\r
-  IN CONST EFI_GUID    *Guid,\r
-  IN UINTN             ExTokenNumber,\r
-  IN UINT16            Value\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber,\r
+  IN UINT16          Value\r
   )\r
 {\r
-  return  ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
+  //\r
+  // PcdSetNvStoreDefaultId should be set in PEI phase to take effect.\r
+  //\r
+  ASSERT (\r
+    !(CompareGuid (Guid, &gEfiMdeModulePkgTokenSpaceGuid) &&\r
+      (ExTokenNumber == PcdToken (PcdSetNvStoreDefaultId)))\r
+    );\r
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 32-bit value for a given PCD token.\r
+\r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
+\r
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
 \r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
 \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet32Ex (\r
-  IN CONST EFI_GUID     *Guid,\r
-  IN UINTN              ExTokenNumber,\r
-  IN UINT32             Value\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber,\r
+  IN UINT32          Value\r
   )\r
 {\r
-  return  ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets an 64-bit value for a given PCD token.\r
+\r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
 \r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSet64Ex (\r
-  IN CONST EFI_GUID    *Guid,\r
-  IN UINTN             ExTokenNumber,\r
-  IN UINT64            Value\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber,\r
+  IN UINT64          Value\r
   )\r
 {\r
-  return  ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Sets a value of a specified size for a given PCD token.\r
 \r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.\r
+                              On input, if the SizeOfValue is greater than the maximum size supported\r
+                              for this TokenNumber then the output value of SizeOfValue will reflect\r
+                              the maximum size supported for this TokenNumber.\r
+  @param[in]  Buffer The buffer to set for the PCD token.\r
+\r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSetPtrEx (\r
-  IN            CONST EFI_GUID         *Guid,\r
-  IN            UINTN                  ExTokenNumber,\r
-  IN OUT        UINTN                  *SizeOfBuffer,\r
-  IN            VOID                   *Buffer\r
+  IN            CONST EFI_GUID  *Guid,\r
+  IN            UINTN           ExTokenNumber,\r
+  IN OUT        UINTN           *SizeOfBuffer,\r
+  IN            VOID            *Buffer\r
   )\r
 {\r
-  return  ExSetWorker(ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);\r
+  return ExSetWorker (ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);\r
 }\r
 \r
+/**\r
+  Sets an Boolean value for a given PCD token.\r
 \r
+  When the PCD service sets a value, it will check to ensure that the\r
+  size of the value being set is compatible with the Token's existing definition.\r
+  If it is not, an error will be returned.\r
 \r
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]  ExTokenNumber The PCD token number.\r
+  @param[in]  Value The value to set for the PCD token.\r
+\r
+  @retval EFI_SUCCESS  Procedure returned successfully.\r
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data\r
+                                  being set was incompatible with a call to this function.\r
+                                  Use GetSize() to retrieve the size of the target data.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdSetBoolEx (\r
-  IN CONST EFI_GUID    *Guid,\r
-  IN UINTN             ExTokenNumber,\r
-  IN BOOLEAN           Value\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN UINTN           ExTokenNumber,\r
+  IN BOOLEAN         Value\r
   )\r
 {\r
-  return  ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));\r
 }\r
 \r
+/**\r
+  Specifies a function to be called anytime the value of a designated token is changed.\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[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.\r
 \r
+  @retval EFI_SUCCESS  The PCD service has successfully established a call event\r
+                        for the CallBackToken requested.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.\r
 \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxeRegisterCallBackOnSet (\r
-  IN  CONST EFI_GUID          *Guid, OPTIONAL\r
-  IN  UINTN                   TokenNumber,\r
-  IN  PCD_PROTOCOL_CALLBACK   CallBackFunction\r
+  IN  CONST EFI_GUID         *Guid  OPTIONAL,\r
+  IN  UINTN                  TokenNumber,\r
+  IN  PCD_PROTOCOL_CALLBACK  CallBackFunction\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  \r
-  ASSERT (CallBackFunction != NULL);\r
-  \r
+  EFI_STATUS  Status;\r
+\r
+  if (CallBackFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
   //\r
@@ -490,97 +1069,137 @@ DxeRegisterCallBackOnSet (
   Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);\r
 \r
   EfiReleaseLock (&mPcdDatabaseLock);\r
-  \r
+\r
   return Status;\r
 }\r
 \r
+/**\r
+  Cancels a previously set callback function for a particular PCD token number.\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[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.\r
 \r
+  @retval EFI_SUCCESS  The PCD service has successfully established a call event\r
+                        for the CallBackToken requested.\r
+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxeUnRegisterCallBackOnSet (\r
-  IN  CONST EFI_GUID          *Guid, OPTIONAL\r
-  IN  UINTN                   TokenNumber,\r
-  IN  PCD_PROTOCOL_CALLBACK   CallBackFunction\r
+  IN  CONST EFI_GUID         *Guid  OPTIONAL,\r
+  IN  UINTN                  TokenNumber,\r
+  IN  PCD_PROTOCOL_CALLBACK  CallBackFunction\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  \r
-  ASSERT (CallBackFunction != NULL);\r
+  EFI_STATUS  Status;\r
+\r
+  if (CallBackFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   //\r
   // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
   //\r
   EfiAcquireLock (&mPcdDatabaseLock);\r
-  \r
+\r
   Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);\r
 \r
   EfiReleaseLock (&mPcdDatabaseLock);\r
-  \r
+\r
   return Status;\r
 }\r
 \r
+/**\r
+  Retrieves the next valid token number in a given namespace.\r
+\r
+  This is useful since the PCD infrastructure contains a sparse list of token numbers,\r
+  and one cannot a priori know what token numbers are valid in the database.\r
 \r
+  If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.\r
+  If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.\r
+  If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.\r
+  If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.\r
+  The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.\r
+  If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.\r
+  If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.\r
+  If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.\r
 \r
+\r
+  @param[in]      Guid    The 128-bit unique value that designates the namespace from which to retrieve the next token.\r
+                          This is an optional parameter that may be NULL.  If this parameter is NULL, then a request is\r
+                          being made to retrieve tokens from the default token space.\r
+  @param[in, out] TokenNumber\r
+                          A pointer to the PCD token number to use to find the subsequent token number.\r
+\r
+  @retval EFI_SUCCESS   The PCD service has retrieved the next valid token number.\r
+  @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdGetNextToken (\r
-  IN CONST EFI_GUID         *Guid, OPTIONAL\r
-  IN OUT   UINTN            *TokenNumber\r
+  IN CONST EFI_GUID  *Guid  OPTIONAL,\r
+  IN OUT   UINTN     *TokenNumber\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  BOOLEAN             PeiExMapTableEmpty;\r
-  BOOLEAN             DxeExMapTableEmpty;\r
+  EFI_STATUS  Status;\r
+  BOOLEAN     PeiExMapTableEmpty;\r
+  BOOLEAN     DxeExMapTableEmpty;\r
 \r
-  if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Status = EFI_NOT_FOUND;\r
-  PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;\r
-  DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;\r
+  Status             = EFI_NOT_FOUND;\r
+  PeiExMapTableEmpty = mPeiExMapTableEmpty;\r
+  DxeExMapTableEmpty = mDxeExMapTableEmpty;\r
 \r
   //\r
   // Scan the local token space\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
+    // between UINTN and 0 . So we add 1 in each size of the\r
     // comparison.\r
-    if (((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) && (*TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1)) ||\r
-        ((*TokenNumber + 1 > (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1)))) {\r
-        return EFI_NOT_FOUND;\r
+    if (((*TokenNumber + 1 > mPeiNexTokenCount + 1) && (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||\r
+        ((*TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1))))\r
+    {\r
+      return EFI_NOT_FOUND;\r
     }\r
-    \r
+\r
     (*TokenNumber)++;\r
-    if ((*TokenNumber + 1 > PEI_NEX_TOKEN_NUMBER + 1) &&\r
-        (*TokenNumber <= PEI_LOCAL_TOKEN_NUMBER)) {\r
+    if ((*TokenNumber + 1 > mPeiNexTokenCount + 1) &&\r
+        (*TokenNumber + 1 <= mPeiLocalTokenCount + 1))\r
+    {\r
       //\r
-      // The first Non-Ex type Token Number for DXE PCD \r
-      // database is PEI_LOCAL_TOKEN_NUMBER\r
+      // The first Non-Ex type Token Number for DXE PCD\r
+      // database is mPeiLocalTokenCount + 1\r
       //\r
-      *TokenNumber = PEI_LOCAL_TOKEN_NUMBER;\r
-    } else if (*TokenNumber + 1 > DXE_NEX_TOKEN_NUMBER + PEI_LOCAL_TOKEN_NUMBER + 1) {\r
+      if (mDxeNexTokenCount > 0) {\r
+        *TokenNumber = mPeiLocalTokenCount + 1;\r
+      } else {\r
+        *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
+        return EFI_NOT_FOUND;\r
+      }\r
+    } else if (*TokenNumber + 1 > mDxeNexTokenCount + mPeiLocalTokenCount + 1) {\r
       *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
+      return EFI_NOT_FOUND;\r
     }\r
+\r
     return EFI_SUCCESS;\r
   }\r
 \r
   if (PeiExMapTableEmpty && DxeExMapTableEmpty) {\r
-    *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
   if (!PeiExMapTableEmpty) {\r
     Status = ExGetNextTokeNumber (\r
-                        Guid,\r
-                        TokenNumber,\r
-                        mPcdDatabase->PeiDb.Init.GuidTable,\r
-                        sizeof(mPcdDatabase->PeiDb.Init.GuidTable),\r
-                        mPcdDatabase->PeiDb.Init.ExMapTable,\r
-                        sizeof(mPcdDatabase->PeiDb.Init.ExMapTable)\r
-                        );\r
+               Guid,\r
+               TokenNumber,\r
+               (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset),\r
+               mPeiGuidTableSize,\r
+               (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),\r
+               mPeiExMapppingTableSize\r
+               );\r
   }\r
 \r
   if (Status == EFI_SUCCESS) {\r
@@ -589,41 +1208,62 @@ DxePcdGetNextToken (
 \r
   if (!DxeExMapTableEmpty) {\r
     Status = ExGetNextTokeNumber (\r
-                        Guid,\r
-                        TokenNumber,\r
-                        mPcdDatabase->DxeDb.Init.GuidTable,\r
-                        sizeof(mPcdDatabase->DxeDb.Init.GuidTable),\r
-                        mPcdDatabase->DxeDb.Init.ExMapTable,\r
-                        sizeof(mPcdDatabase->DxeDb.Init.ExMapTable)\r
-                        );\r
+               Guid,\r
+               TokenNumber,\r
+               (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset),\r
+               mDxeGuidTableSize,\r
+               (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),\r
+               mDxeExMapppingTableSize\r
+               );\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-STATIC\r
+/**\r
+  Get all token space guid table which is different with given token space guid.\r
+\r
+  @param ExMapTableSize  The size of ExMapTable in item\r
+  @param ExMapTable      Token space guid table that want to be scaned.\r
+  @param GuidTable       Guid table\r
+\r
+  @return all token space guid table which is different with given token space guid.\r
+\r
+**/\r
 EFI_GUID **\r
 GetDistinctTokenSpace (\r
-  IN OUT    UINTN             *ExMapTableSize,\r
-  IN        DYNAMICEX_MAPPING *ExMapTable,\r
-  IN        EFI_GUID          *GuidTable\r
+  IN OUT    UINTN              *ExMapTableSize,\r
+  IN        DYNAMICEX_MAPPING  *ExMapTable,\r
+  IN        EFI_GUID           *GuidTable\r
   )\r
 {\r
   EFI_GUID  **DistinctTokenSpace;\r
   UINTN     OldGuidIndex;\r
   UINTN     TsIdx;\r
+  UINTN     TempTsIdx;\r
   UINTN     Idx;\r
-\r
+  BOOLEAN   Match;\r
 \r
   DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));\r
   ASSERT (DistinctTokenSpace != NULL);\r
 \r
-  TsIdx = 0;\r
-  OldGuidIndex = ExMapTable[0].ExGuidIndex;\r
+  TsIdx                     = 0;\r
+  OldGuidIndex              = ExMapTable[0].ExGuidIndex;\r
   DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];\r
   for (Idx = 1; Idx < *ExMapTableSize; Idx++) {\r
-    if (ExMapTable[Idx].ExGuidIndex != OldGuidIndex) {\r
-      OldGuidIndex = ExMapTable[Idx].ExGuidIndex;\r
+    Match        = FALSE;\r
+    OldGuidIndex = ExMapTable[Idx].ExGuidIndex;\r
+    for (TempTsIdx = 0; TempTsIdx <= TsIdx; TempTsIdx++) {\r
+      if (&GuidTable[OldGuidIndex] == DistinctTokenSpace[TempTsIdx]) {\r
+        //\r
+        // Have recorded this GUID.\r
+        //\r
+        Match = TRUE;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (!Match) {\r
       DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];\r
     }\r
   }\r
@@ -635,69 +1275,72 @@ GetDistinctTokenSpace (
   //\r
   *ExMapTableSize = TsIdx + 1;\r
   return DistinctTokenSpace;\r
-    \r
 }\r
-  \r
-//\r
-// Just pre-allocate a memory buffer that is big enough to\r
-// host all distinct TokenSpace guid in both\r
-// PEI ExMap and DXE ExMap.\r
-//\r
-STATIC EFI_GUID *TmpTokenSpaceBuffer[PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE] = { 0 };\r
 \r
+/**\r
+  Retrieves the next valid PCD token namespace for a given namespace.\r
+\r
+  Gets the next valid token namespace for a given namespace. This is useful to traverse the valid\r
+  token namespaces on a platform.\r
+\r
+  @param[in, out]   Guid    An indirect pointer to EFI_GUID. On input it designates a known token\r
+                            namespace from which the search will start. On output, it designates the next valid\r
+                            token namespace on the platform. If *Guid is NULL, then the GUID of the first token\r
+                            space of the current platform is returned. If the search cannot locate the next valid\r
+                            token namespace, an error is returned and the value of *Guid is undefined.\r
+\r
+  @retval  EFI_SUCCESS      The PCD service retrieved the value requested.\r
+  @retval  EFI_NOT_FOUND    The PCD service could not find the next valid token namespace.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 DxePcdGetNextTokenSpace (\r
-  IN OUT CONST EFI_GUID               **Guid\r
-  )\r
-{\r
-  UINTN               Idx;\r
-  UINTN               Idx2;\r
-  UINTN               Idx3;\r
-  UINTN               PeiTokenSpaceTableSize;\r
-  UINTN               DxeTokenSpaceTableSize;\r
-  EFI_GUID            **PeiTokenSpaceTable;\r
-  EFI_GUID            **DxeTokenSpaceTable;\r
-  BOOLEAN             Match;\r
-  BOOLEAN             PeiExMapTableEmpty;\r
-  BOOLEAN             DxeExMapTableEmpty;\r
-\r
-  if (!FeaturePcdGet (PcdDxePcdDatabaseTraverseEnabled)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  IN OUT CONST EFI_GUID  **Guid\r
+  )\r
+{\r
+  UINTN     Idx;\r
+  UINTN     Idx2;\r
+  UINTN     Idx3;\r
+  UINTN     PeiTokenSpaceTableSize;\r
+  UINTN     DxeTokenSpaceTableSize;\r
+  EFI_GUID  **PeiTokenSpaceTable;\r
+  EFI_GUID  **DxeTokenSpaceTable;\r
+  BOOLEAN   Match;\r
+  BOOLEAN   PeiExMapTableEmpty;\r
+  BOOLEAN   DxeExMapTableEmpty;\r
 \r
   ASSERT (Guid != NULL);\r
-  \r
-  PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;\r
-  DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY;\r
+\r
+  PeiExMapTableEmpty = mPeiExMapTableEmpty;\r
+  DxeExMapTableEmpty = mDxeExMapTableEmpty;\r
 \r
   if (PeiExMapTableEmpty && DxeExMapTableEmpty) {\r
-    if (*Guid != NULL) {\r
-      return EFI_NOT_FOUND;\r
-    } else {\r
-      return EFI_SUCCESS;\r
-    }\r
+    return EFI_NOT_FOUND;\r
   }\r
-  \r
-  \r
+\r
   if (TmpTokenSpaceBuffer[0] == NULL) {\r
     PeiTokenSpaceTableSize = 0;\r
 \r
     if (!PeiExMapTableEmpty) {\r
-      PeiTokenSpaceTableSize = PEI_EXMAPPING_TABLE_SIZE;\r
-      PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,\r
-                            mPcdDatabase->PeiDb.Init.ExMapTable,\r
-                            mPcdDatabase->PeiDb.Init.GuidTable\r
-                            );\r
-      CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);\r
+      PeiTokenSpaceTableSize = mPeiExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);\r
+      PeiTokenSpaceTable     = GetDistinctTokenSpace (\r
+                                 &PeiTokenSpaceTableSize,\r
+                                 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),\r
+                                 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset)\r
+                                 );\r
+      CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID *) * PeiTokenSpaceTableSize);\r
+      TmpTokenSpaceBufferCount = PeiTokenSpaceTableSize;\r
+      FreePool (PeiTokenSpaceTable);\r
     }\r
 \r
     if (!DxeExMapTableEmpty) {\r
-      DxeTokenSpaceTableSize = DXE_EXMAPPING_TABLE_SIZE;\r
-      DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,\r
-                            mPcdDatabase->DxeDb.Init.ExMapTable,\r
-                            mPcdDatabase->DxeDb.Init.GuidTable\r
-                            );\r
+      DxeTokenSpaceTableSize = mDxeExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);\r
+      DxeTokenSpaceTable     = GetDistinctTokenSpace (\r
+                                 &DxeTokenSpaceTableSize,\r
+                                 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),\r
+                                 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset)\r
+                                 );\r
 \r
       //\r
       // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable\r
@@ -710,10 +1353,14 @@ DxePcdGetNextTokenSpace (
             break;\r
           }\r
         }\r
+\r
         if (!Match) {\r
           TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];\r
         }\r
       }\r
+\r
+      TmpTokenSpaceBufferCount = Idx3;\r
+      FreePool (DxeTokenSpaceTable);\r
     }\r
   }\r
 \r
@@ -721,17 +1368,22 @@ DxePcdGetNextTokenSpace (
     *Guid = TmpTokenSpaceBuffer[0];\r
     return EFI_SUCCESS;\r
   }\r
-  \r
-  for (Idx = 0; Idx < (PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE); Idx++) {\r
-    if(CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {\r
-      Idx++;\r
-      *Guid = TmpTokenSpaceBuffer[Idx];\r
-      return EFI_SUCCESS;\r
+\r
+  for (Idx = 0; Idx < TmpTokenSpaceBufferCount; Idx++) {\r
+    if (CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {\r
+      if (Idx == TmpTokenSpaceBufferCount - 1) {\r
+        //\r
+        // It has been the last token namespace.\r
+        //\r
+        *Guid = NULL;\r
+        return EFI_NOT_FOUND;\r
+      } else {\r
+        Idx++;\r
+        *Guid = TmpTokenSpaceBuffer[Idx];\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
   }\r
 \r
   return EFI_NOT_FOUND;\r
-\r
 }\r
-\r
-\r