summaryrefslogtreecommitdiff
path: root/Core/MdeModulePkg/Universal/PCD
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2017-04-27 11:05:07 +0800
committerGuo Mang <mang.guo@intel.com>2017-04-27 11:05:07 +0800
commitc23f114d3cfbb29b8734b87213d1ec0de404197b (patch)
tree4f3612573be055139a88213559212a40b7862fee /Core/MdeModulePkg/Universal/PCD
parent001e57a103fce87245bfb7ae9c32ffb499a64135 (diff)
downloadedk2-platforms-c23f114d3cfbb29b8734b87213d1ec0de404197b.tar.xz
MdeModulePkg: Move to new location
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Core/MdeModulePkg/Universal/PCD')
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.c1354
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf352
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni297
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni19
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Dxe/Service.c2008
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Dxe/Service.h1202
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Pei/Pcd.c1433
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Pei/Pcd.inf352
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni296
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni19
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Pei/Service.c1209
-rw-r--r--Core/MdeModulePkg/Universal/PCD/Pei/Service.h1117
12 files changed, 9658 insertions, 0 deletions
diff --git a/Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.c b/Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
new file mode 100644
index 0000000000..9d710bbf1f
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
@@ -0,0 +1,1354 @@
+/** @file
+ PCD DXE driver manage all PCD entry initialized in PEI phase and DXE phase, and
+ produce the implementation of native PCD protocol and EFI_PCD_PROTOCOL defined in
+ PI 1.4a Vol3.
+
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Service.h"
+
+///
+/// PCD database lock.
+///
+EFI_LOCK mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_NOTIFY);
+
+///
+/// PCD_PROTOCOL the EDKII native implementation which support dynamic
+/// type and dynamicEx type PCDs.
+///
+PCD_PROTOCOL mPcdInstance = {
+ DxePcdSetSku,
+
+ DxePcdGet8,
+ DxePcdGet16,
+ DxePcdGet32,
+ DxePcdGet64,
+ DxePcdGetPtr,
+ DxePcdGetBool,
+ DxePcdGetSize,
+
+ DxePcdGet8Ex,
+ DxePcdGet16Ex,
+ DxePcdGet32Ex,
+ DxePcdGet64Ex,
+ DxePcdGetPtrEx,
+ DxePcdGetBoolEx,
+ DxePcdGetSizeEx,
+
+ DxePcdSet8,
+ DxePcdSet16,
+ DxePcdSet32,
+ DxePcdSet64,
+ DxePcdSetPtr,
+ DxePcdSetBool,
+
+ DxePcdSet8Ex,
+ DxePcdSet16Ex,
+ DxePcdSet32Ex,
+ DxePcdSet64Ex,
+ DxePcdSetPtrEx,
+ DxePcdSetBoolEx,
+
+ DxeRegisterCallBackOnSet,
+ DxeUnRegisterCallBackOnSet,
+ DxePcdGetNextToken,
+ DxePcdGetNextTokenSpace
+};
+
+///
+/// EFI_PCD_PROTOCOL is defined in PI 1.2 Vol 3 which only support dynamicEx type
+/// PCD.
+///
+EFI_PCD_PROTOCOL mEfiPcdInstance = {
+ DxePcdSetSku,
+ DxePcdGet8Ex,
+ DxePcdGet16Ex,
+ DxePcdGet32Ex,
+ DxePcdGet64Ex,
+ DxePcdGetPtrEx,
+ DxePcdGetBoolEx,
+ DxePcdGetSizeEx,
+ DxePcdSet8Ex,
+ DxePcdSet16Ex,
+ DxePcdSet32Ex,
+ DxePcdSet64Ex,
+ DxePcdSetPtrEx,
+ DxePcdSetBoolEx,
+ (EFI_PCD_PROTOCOL_CALLBACK_ON_SET) DxeRegisterCallBackOnSet,
+ (EFI_PCD_PROTOCOL_CANCEL_CALLBACK) DxeUnRegisterCallBackOnSet,
+ DxePcdGetNextToken,
+ DxePcdGetNextTokenSpace
+};
+
+///
+/// Instance of GET_PCD_INFO_PROTOCOL protocol is EDKII native implementation.
+/// This protocol instance support dynamic and dynamicEx type PCDs.
+///
+GET_PCD_INFO_PROTOCOL mGetPcdInfoInstance = {
+ DxeGetPcdInfoGetInfo,
+ DxeGetPcdInfoGetInfoEx,
+ DxeGetPcdInfoGetSku
+};
+
+///
+/// Instance of EFI_GET_PCD_INFO_PROTOCOL which is defined in PI 1.2.1 Vol 3.
+/// This PPI instance only support dyanmicEx type PCD.
+///
+EFI_GET_PCD_INFO_PROTOCOL mEfiGetPcdInfoInstance = {
+ DxeGetPcdInfoGetInfoEx,
+ DxeGetPcdInfoGetSku
+};
+
+EFI_HANDLE mPcdHandle = NULL;
+
+/**
+ Main entry for PCD DXE driver.
+
+ This routine initialize the PCD database and install PCD_PROTOCOL.
+
+ @param ImageHandle Image handle for PCD DXE driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @return Status of gBS->InstallProtocolInterface()
+
+**/
+EFI_STATUS
+EFIAPI
+PcdDxeInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+
+ //
+ // Make sure the Pcd Protocol is not already installed in the system
+ //
+
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);
+
+ BuildPcdDxeDataBase ();
+
+ //
+ // Install PCD_PROTOCOL to handle dynamic type PCD
+ // Install EFI_PCD_PROTOCOL to handle dynamicEx type PCD
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mPcdHandle,
+ &gPcdProtocolGuid, &mPcdInstance,
+ &gEfiPcdProtocolGuid, &mEfiPcdInstance,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install GET_PCD_INFO_PROTOCOL to handle dynamic type PCD
+ // Install EFI_GET_PCD_INFO_PROTOCOL to handle dynamicEx type PCD
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mPcdHandle,
+ &gGetPcdInfoProtocolGuid, &mGetPcdInfoInstance,
+ &gEfiGetPcdInfoProtocolGuid, &mEfiGetPcdInfoInstance,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register callback function upon VariableLockProtocol
+ // to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
+ //
+ EfiCreateProtocolNotifyEvent (
+ &gEdkiiVariableLockProtocolGuid,
+ TPL_CALLBACK,
+ VariableLockCallBack,
+ NULL,
+ &Registration
+ );
+
+ return Status;
+}
+
+/**
+ Retrieve additional information associated with a PCD token in the default token space.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+DxeGetPcdInfoGetInfo (
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ return DxeGetPcdInfo (NULL, TokenNumber, PcdInfo);
+}
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+DxeGetPcdInfoGetInfoEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ return DxeGetPcdInfo (Guid, TokenNumber, PcdInfo);
+}
+
+/**
+ Retrieve the currently set SKU Id.
+
+ @return The currently set SKU Id. If the platform has not set at a SKU Id, then the
+ default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
+ Id is returned.
+**/
+UINTN
+EFIAPI
+DxeGetPcdInfoGetSku (
+ VOID
+ )
+{
+ return (UINTN) mPcdDatabase.DxeDb->SystemSkuId;
+}
+
+/**
+ Sets the SKU value for subsequent calls to set or get PCD token values.
+
+ SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
+ SetSku() is normally called only once by the system.
+
+ For each item (token), the database can hold a single value that applies to all SKUs,
+ or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
+ SKU-specific values are called SKU enabled.
+
+ The SKU Id of zero is reserved as a default.
+ For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
+ single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
+ last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
+ the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
+ set for that Id, the results are unpredictable.
+
+ @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and
+ set values associated with a PCD token.
+
+**/
+VOID
+EFIAPI
+DxePcdSetSku (
+ IN UINTN SkuId
+ )
+{
+ SKU_ID *SkuIdTable;
+ UINTN Index;
+
+ if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) {
+ //
+ // The input SKU Id is equal to current SKU Id, return directly.
+ //
+ return;
+ }
+
+ if (mPcdDatabase.DxeDb->SystemSkuId != (SKU_ID) 0) {
+ DEBUG ((DEBUG_ERROR, "PcdDxe - The SKU Id could be changed only once."));
+ DEBUG ((
+ DEBUG_ERROR,
+ "PcdDxe - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",
+ mPcdDatabase.DxeDb->SystemSkuId,
+ (SKU_ID) SkuId
+ ));
+ ASSERT (FALSE);
+ return;
+ }
+
+ SkuIdTable = (SKU_ID *) ((UINT8 *) mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SkuIdTableOffset);
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (SkuId == SkuIdTable[Index + 1]) {
+ DEBUG ((EFI_D_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId));
+ mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID) SkuId;
+ return;
+ }
+ }
+
+ //
+ // Invalid input SkuId, the default SKU Id will be still used for the system.
+ //
+ DEBUG ((EFI_D_INFO, "PcdDxe - Invalid input SkuId, the default SKU Id will be still used.\n"));
+ return;
+}
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the current byte-sized value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT8 value.
+
+**/
+UINT8
+EFIAPI
+DxePcdGet8 (
+ IN UINTN TokenNumber
+ )
+{
+ return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
+}
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the current 16-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT16 value.
+
+**/
+UINT16
+EFIAPI
+DxePcdGet16 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
+}
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the current 32-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT32 value.
+
+**/
+UINT32
+EFIAPI
+DxePcdGet32 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
+}
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the current 64-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT64 value.
+
+**/
+UINT64
+EFIAPI
+DxePcdGet64 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned64(GetWorker (TokenNumber, sizeof (UINT64)));
+}
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrived.
+
+**/
+VOID *
+EFIAPI
+DxePcdGetPtr (
+ IN UINTN TokenNumber
+ )
+{
+ return GetWorker (TokenNumber, 0);
+}
+
+/**
+ Retrieves a Boolean value for a given PCD token.
+
+ Retrieves the current boolean value for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The Boolean value.
+
+**/
+BOOLEAN
+EFIAPI
+DxePcdGetBool (
+ IN UINTN TokenNumber
+ )
+{
+ return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+DxePcdGetSize (
+ IN UINTN TokenNumber
+ )
+{
+ UINTN Size;
+ UINT32 *LocalTokenNumberTable;
+ BOOLEAN IsPeiDb;
+ UINTN MaxSize;
+ UINTN TmpTokenNumber;
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ //
+ // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
+ //
+ TmpTokenNumber = TokenNumber;
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ IsPeiDb = (BOOLEAN) (TokenNumber + 1 < mPeiLocalTokenCount + 1);
+
+ TokenNumber = IsPeiDb ? TokenNumber :
+ (TokenNumber - mPeiLocalTokenCount);
+
+ LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset)
+ : (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
+
+ Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
+
+ if (Size == 0) {
+ //
+ // For pointer type, we need to scan the SIZE_TABLE to get the current size.
+ //
+ return GetPtrTypeSize (TmpTokenNumber, &MaxSize);
+ } else {
+ return Size;
+ }
+
+}
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the 8-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 8-bit value for the PCD token.
+
+**/
+UINT8
+EFIAPI
+DxePcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof(UINT8)));
+}
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the 16-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 16-bit value for the PCD token.
+
+**/
+UINT16
+EFIAPI
+DxePcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT16)));
+}
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the 32-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 32-bit value for the PCD token.
+
+**/
+UINT32
+EFIAPI
+DxePcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT32)));
+}
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the 64-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 64-bit value for the PCD token.
+
+**/
+UINT64
+EFIAPI
+DxePcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof(UINT64)));
+}
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrived.
+
+**/
+VOID *
+EFIAPI
+DxePcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ExGetWorker (Guid, ExTokenNumber, 0);
+}
+
+/**
+ Retrieves an Boolean value for a given PCD token.
+
+ Retrieves the Boolean value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size Boolean value for the PCD token.
+
+**/
+BOOLEAN
+EFIAPI
+DxePcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof(BOOLEAN)));
+}
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+DxePcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return DxePcdGetSize(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber));
+}
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetPtr (
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+{
+ return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
+}
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT8 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT16 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT32 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT64 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+{
+ return ExSetWorker(ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);
+}
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN BOOLEAN Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Specifies a function to be called anytime the value of a designated token is changed.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ )
+{
+ EFI_STATUS Status;
+
+ if (CallBackFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return Status;
+}
+
+/**
+ Cancels a previously set callback function for a particular PCD token number.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ )
+{
+ EFI_STATUS Status;
+
+ if (CallBackFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return Status;
+}
+
+/**
+ Retrieves the next valid token number in a given namespace.
+
+ This is useful since the PCD infrastructure contains a sparse list of token numbers,
+ and one cannot a priori know what token numbers are valid in the database.
+
+ If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
+ If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
+ If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
+ If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
+ The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
+ If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
+ If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+ If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to retrieve the next token.
+ This is an optional parameter that may be NULL. If this parameter is NULL, then a request is
+ being made to retrieve tokens from the default token space.
+ @param[in, out] TokenNumber
+ A pointer to the PCD token number to use to find the subsequent token number.
+
+ @retval EFI_SUCCESS The PCD service has retrieved the next valid token number.
+ @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN PeiExMapTableEmpty;
+ BOOLEAN DxeExMapTableEmpty;
+
+ Status = EFI_NOT_FOUND;
+ PeiExMapTableEmpty = mPeiExMapTableEmpty;
+ DxeExMapTableEmpty = mDxeExMapTableEmpty;
+
+ //
+ // Scan the local token space
+ //
+ if (Guid == NULL) {
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ if (((*TokenNumber + 1 > mPeiNexTokenCount + 1) && (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||
+ ((*TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1)))) {
+ return EFI_NOT_FOUND;
+ }
+
+ (*TokenNumber)++;
+ if ((*TokenNumber + 1 > mPeiNexTokenCount + 1) &&
+ (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) {
+ //
+ // The first Non-Ex type Token Number for DXE PCD
+ // database is mPeiLocalTokenCount + 1
+ //
+ if (mDxeNexTokenCount > 0) {
+ *TokenNumber = mPeiLocalTokenCount + 1;
+ } else {
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_NOT_FOUND;
+ }
+ } else if (*TokenNumber + 1 > mDxeNexTokenCount + mPeiLocalTokenCount + 1) {
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+ }
+
+ if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (!PeiExMapTableEmpty) {
+ Status = ExGetNextTokeNumber (
+ Guid,
+ TokenNumber,
+ (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset),
+ mPeiGuidTableSize,
+ (DYNAMICEX_MAPPING *)((UINT8 *) mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),
+ mPeiExMapppingTableSize
+ );
+ }
+
+ if (Status == EFI_SUCCESS) {
+ return Status;
+ }
+
+ if (!DxeExMapTableEmpty) {
+ Status = ExGetNextTokeNumber (
+ Guid,
+ TokenNumber,
+ (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset),
+ mDxeGuidTableSize,
+ (DYNAMICEX_MAPPING *)((UINT8 *) mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),
+ mDxeExMapppingTableSize
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Get all token space guid table which is different with given token space guid.
+
+ @param ExMapTableSize The size of ExMapTable in item
+ @param ExMapTable Token space guid table that want to be scaned.
+ @param GuidTable Guid table
+
+ @return all token space guid table which is different with given token space guid.
+
+**/
+EFI_GUID **
+GetDistinctTokenSpace (
+ IN OUT UINTN *ExMapTableSize,
+ IN DYNAMICEX_MAPPING *ExMapTable,
+ IN EFI_GUID *GuidTable
+ )
+{
+ EFI_GUID **DistinctTokenSpace;
+ UINTN OldGuidIndex;
+ UINTN TsIdx;
+ UINTN TempTsIdx;
+ UINTN Idx;
+ BOOLEAN Match;
+
+ DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));
+ ASSERT (DistinctTokenSpace != NULL);
+
+ TsIdx = 0;
+ OldGuidIndex = ExMapTable[0].ExGuidIndex;
+ DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];
+ for (Idx = 1; Idx < *ExMapTableSize; Idx++) {
+ Match = FALSE;
+ OldGuidIndex = ExMapTable[Idx].ExGuidIndex;
+ for (TempTsIdx = 0; TempTsIdx <= TsIdx; TempTsIdx++) {
+ if (&GuidTable[OldGuidIndex] == DistinctTokenSpace[TempTsIdx]) {
+ //
+ // Have recorded this GUID.
+ //
+ Match = TRUE;
+ break;
+ }
+ }
+ if (!Match) {
+ DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];
+ }
+ }
+
+ //
+ // The total number of Distinct Token Space
+ // is TsIdx + 1 because we use TsIdx as a index
+ // to the DistinctTokenSpace[]
+ //
+ *ExMapTableSize = TsIdx + 1;
+ return DistinctTokenSpace;
+
+}
+
+/**
+ Retrieves the next valid PCD token namespace for a given namespace.
+
+ Gets the next valid token namespace for a given namespace. This is useful to traverse the valid
+ token namespaces on a platform.
+
+ @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token
+ namespace from which the search will start. On output, it designates the next valid
+ token namespace on the platform. If *Guid is NULL, then the GUID of the first token
+ space of the current platform is returned. If the search cannot locate the next valid
+ token namespace, an error is returned and the value of *Guid is undefined.
+
+ @retval EFI_SUCCESS The PCD service retrieved the value requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdGetNextTokenSpace (
+ IN OUT CONST EFI_GUID **Guid
+ )
+{
+ UINTN Idx;
+ UINTN Idx2;
+ UINTN Idx3;
+ UINTN PeiTokenSpaceTableSize;
+ UINTN DxeTokenSpaceTableSize;
+ EFI_GUID **PeiTokenSpaceTable;
+ EFI_GUID **DxeTokenSpaceTable;
+ BOOLEAN Match;
+ BOOLEAN PeiExMapTableEmpty;
+ BOOLEAN DxeExMapTableEmpty;
+
+ ASSERT (Guid != NULL);
+
+ PeiExMapTableEmpty = mPeiExMapTableEmpty;
+ DxeExMapTableEmpty = mDxeExMapTableEmpty;
+
+ if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (TmpTokenSpaceBuffer[0] == NULL) {
+ PeiTokenSpaceTableSize = 0;
+
+ if (!PeiExMapTableEmpty) {
+ PeiTokenSpaceTableSize = mPeiExMapppingTableSize / sizeof(DYNAMICEX_MAPPING);
+ PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize,
+ (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),
+ (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset)
+ );
+ CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize);
+ FreePool (PeiTokenSpaceTable);
+ }
+
+ if (!DxeExMapTableEmpty) {
+ DxeTokenSpaceTableSize = mDxeExMapppingTableSize / sizeof(DYNAMICEX_MAPPING);
+ DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize,
+ (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),
+ (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset)
+ );
+
+ //
+ // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable
+ //
+ for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {
+ Match = FALSE;
+ for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {
+ if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {
+ Match = TRUE;
+ break;
+ }
+ }
+ if (!Match) {
+ TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];
+ }
+ }
+
+ TmpTokenSpaceBufferCount = Idx3;
+ FreePool (DxeTokenSpaceTable);
+ }
+ }
+
+ if (*Guid == NULL) {
+ *Guid = TmpTokenSpaceBuffer[0];
+ return EFI_SUCCESS;
+ }
+
+ for (Idx = 0; Idx < TmpTokenSpaceBufferCount; Idx++) {
+ if (CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {
+ if (Idx == TmpTokenSpaceBufferCount - 1) {
+ //
+ // It has been the last token namespace.
+ //
+ *Guid = NULL;
+ return EFI_NOT_FOUND;
+ } else {
+ Idx++;
+ *Guid = TmpTokenSpaceBuffer[Idx];
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf b/Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
new file mode 100644
index 0000000000..54cd8d9b9f
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
@@ -0,0 +1,352 @@
+## @file
+# PCD DXE driver manage database contains all dynamic PCD entries and produce the implementation of PCD protocol.
+#
+# This version PCD DXE depends on the external PCD database binary file, not built in PCD data base.
+# There are two PCD Protocols as follows:
+# 1) PCD_PROTOCOL
+# It is EDKII implementation which support Dynamic/DynamicEx type Pcds.
+# 2) EFI_PCD_PROTOCOL
+# It is defined by PI specification 1.2, Vol 3 which only support dynamicEx
+# type Pcd.
+#
+# For dynamicEx type PCD, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL.
+# PCD DXE driver will produce above two protocols at same time.
+#
+# PCD database is generated as the separate binary image at build time. The binary image
+# will be intergrated into Firmware volume together with PCD driver.
+#
+# ////////////////////////////////////////////////////////////////////////////////
+# // //
+# // Introduction of PCD database //
+# // //
+# ////////////////////////////////////////////////////////////////////////////////
+#
+# 1, Introduction
+# PCD database hold all dynamic type PCD information. The structure of PEI PCD
+# database is generated by build tools according to dynamic PCD usage for
+# specified platform.
+#
+# 2, Dynamic Type PCD
+# Dynamic type PCD is used for the configuration/setting which value is determined
+# dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,
+# PatchablePcd) is fixed in final generated FD image in build time.
+#
+# 2.1 The "dynamic" determination means one of below cases:
+# a) The PCD setting value is produced by someone driver and consumed by
+# other driver in execution time.
+# b) The PCD setting value is set/get by user from FrontPage.
+# c) The PCD setting value is produced by platform OEM vendor in specified area.
+#
+# 2.2 According to module distribution way, dynamic PCD could be classfied as:
+# a) Dynamic:
+# If module is released in source code and will be built with platform
+# DSC, the dynamic PCD used by this module can be accessed as:
+# PcdGetxx(PcdSampleDynamicPcd);
+# In building platform, build tools will translate PcdSampleDynamicPcd to
+# pair of {Token Space Guid: Token Number} for this PCD.
+# b) DynamicEx:
+# If module is release as binary and will not pariticpate platform building,
+# the dynamic PCD used by this module need be accessed as:
+# PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)
+# Developer need explicity gives {Token Space Guid:Token Number} as parameter
+# in writting source code.
+#
+# 2.3 According to PCD value's storage method, dynamic PCD could be classfied as:
+# a) Default Storage:
+# - The PCD value is stored in PCD database maintained by PCD driver in boot
+# time memory.
+# - This type is used for communication between PEIM/DXE driver, DXE/DXE
+# driver. But all set/get value will be losted after boot-time memory
+# is turn off.
+# - [PcdsDynamicDefault] is used as section name for this type PCD in
+# platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.
+#
+# b) Variable Storage:
+# - The PCD value is stored in variable area.
+# - As default storage type, this type PCD could be used for PEI/DXE driver
+# communication. But beside it, this type PCD could also be used to store
+# the value associate with a HII setting via variable interface.
+# - In PEI phase, the PCD value could only be got but can not be set due
+# to variable area is readonly.
+# - [PcdsDynamicHii] is used as section name for this type PCD in platform
+# DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.
+#
+# c) OEM specificed storage area:
+# - The PCD value is stored in OEM specified area which base address is
+# specified by a FixedAtBuild PCD setting - PcdVpdBaseAddress.
+# - The area is read only for PEI and DXE phase.
+# - [PcdsDynamicVpd] is used as section name for this type PCD in platform
+# DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.
+#
+# 2.4 When and how to use dynamic PCD
+# Module developer do not care the used PCD is dynamic or static when writting
+# source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator
+# in platform DSC file. Please ref section 2.3 to get matching between dynamic
+# PCD type and section name in DSC file.
+#
+# 3, PCD database:
+# Although dynamic PCD could be in different storage type as above description,
+# but the basic information and default value for all dynamic PCD is hold
+# by PCD database maintained by PEI/DXE driver.
+#
+# As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database
+# also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.
+# To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic
+# PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD
+# database contains all PCDs used in PEI/DXE phase in memory.
+#
+# Build tool will generate PCD database into the separate binary file for
+# PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.
+#
+# 3.1 PcdPeim and PcdDxe
+# PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver
+# build guid hob in temporary memory and copy the binary data base from flash
+# to temporary memory for PEI PCD database.
+# DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,
+# a new PCD database is allocated in boot-time memory which including all
+# PEI PCD and DXE PCD entry.
+#
+# Pcd driver should run as early as possible before any other driver access
+# dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by
+# making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.
+#
+# 3.2 Token space Guid/Token number, Platform token, Local token number
+# Dynamic PCD
+# +-----------+ +---------+
+# |TokenSpace | |Platform |
+# | Guid | build tool | Token |
+# | + +-------------->| Number |
+# | Token | +---------+`._
+# | Number | `.
+# +-----------+ `. +------+
+# `-|Local |
+# |Token |
+# DynamicEx PCD ,-|Number|
+# +-----------+ ,-' +------+
+# |TokenSpace | ,-'
+# | Guid | _,-'
+# | + +.'
+# | Token |
+# | Number |
+# +-----------+
+#
+#
+# 3.2.1 Pair of Token space guid + Token number
+# Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it
+# is not easy maintained by PCD driver, and hashed token number will make
+# searching slowly.
+#
+# 3.2.2 Platform Token Number
+# "Platform token number" concept is introduced for mapping to a pair of
+# "TokenSpaceGuid + TokenNumber". The platform token number is generated by
+# build tool in autogen.h and all of them are continual in a platform scope
+# started from 1.(0 meaning invalid internal token number)
+# With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)
+# in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)
+# in autogen.h.
+# Notes: The mapping between pair of "tokenspace guid + token number" and
+# "internal token number" need build tool establish, so "platform token number"
+# mechanism is not suitable for binary module which use DynamicEx type PCD.
+# To access a dynamicEx type PCD, pair of "token space guid/token number" all need
+# to be specificed for PcdSet/PcdGet accessing macro.
+#
+# Platform Token Number is started from 1, and inceased continuous. From whole
+# platform scope, there are two zones: PEI Zone and DXE Zone
+# | Platform Token Number
+# ----------|----------------------------------------------------------------
+# PEI Zone: | 1 ~ PEI_LOCAL_TOKEN_NUMBER
+# DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)
+#
+# 3.2.3 Local Token Number
+# To fast searching a PCD entry in PCD database, PCD driver translate
+# platform token number to local token number via a mapping table.
+# For binary DynamicEx type PCD, there is a another mapping table to translate
+# "token space guid + token number" to local token number directly.
+# Local token number is identifier for all internal interface in PCD PEI/DXE
+# driver.
+#
+# A local token number is a 32-bit value in following meaning:
+# 32 ------------- 28 ---------- 24 -------- 0
+# | PCD type mask | Datum Type | Offset |
+# +-----------------------------------------+
+# where:
+# PCd type mask: indicate Pcd type from following macro:
+# PCD_TYPE_DATA
+# PCD_TYPE_HII
+# PCD_TYPE_VPD
+# PCD_TYPE_SKU_ENABLED
+# PCD_TYPE_STRING
+# Datum Type : indicate PCD vaue type from following macro:
+# PCD_DATUM_TYPE_POINTER
+# PCD_DATUM_TYPE_UINT8
+# PCD_DATUM_TYPE_UINT16
+# PCD_DATUM_TYPE_UINT32
+# PCD_DATUM_TYPE_UINT64
+# Offset : indicate the related offset of PCD value in PCD database array.
+# Based on local token number, PCD driver could fast determine PCD type, value
+# type and get PCD entry from PCD database.
+#
+# 3.3 PCD Database binary file
+# PCD Database binary file will be created at build time as the standalone binary image.
+# To understand the binary image layout, PCD Database C structure is still generated
+# as comments by build tools in PCD driver's autogen.h/
+# autogen.c file. In generated C structure, following information is stored:
+# - ExMapTable: This table is used translate a binary dynamicex type PCD's
+# "tokenguid + token" to local token number.
+# - LocalTokenNumberTable:
+# This table stores all local token number in array, use "Internal
+# token number" as array index to get PCD entry's offset fastly.
+# - SizeTable: This table stores the size information for all PCD entry.
+# - GuidTable: This table stores guid value for DynamicEx's token space,
+# HII type PCD's variable GUID.
+# - SkuIdTable: TBD
+# - SystemSkuId: TBD
+# - PCD value structure:
+# Every PCD has a value record in PCD database. For different
+# datum type PCD has different record structure which will be
+# introduced in 3.3.1
+#
+# In a PCD database structure, there are two major area: Init and UnInit.
+# Init area is use stored above PCD internal structure such as ExMapTable,
+# LocalTokenNumberTable etc and the (default) value of PCD which has default
+# value specified in platform DSC file.
+# Unint area is used stored the value of PCD which has no default value in
+# platform DSC file, the value of NULL, 0 specified in platform DSC file can
+# be seemed as "no default value".
+#
+# 3.3.1 Simple Sample PCD Database C Structure
+# A general sample of PCD database structue is as follows:
+# typedef struct _PCD_DATABASE {
+# typedef struct _PCD_DATABASE_INIT {
+# //===== Following is PCD database internal maintain structures
+# DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];
+# UINT32 LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
+# GUID GuidTable[PEI_GUID_TABLE_SIZE];
+# SIZE_INFO SizeTable[PEI_SIZE_TABLE_SIZE];
+# UINT8 SkuIdTable[PEI_SKUID_TABLE_SIZE];
+# SKU_ID SystemSkuId;
+#
+# //===== Following is value structure for PCD with default value
+# ....
+# ....
+# ....
+# } Init;
+# typedef struct _PCD_DATABSE_UNINIT {
+# //==== Following is value structure for PCD without default value
+# ....
+# ....
+# } UnInit;
+# }
+#
+# 3.3.2 PCD value structure in PCD database C structure
+# The value's structure is generated by build tool in PCD database C structure.
+# The PCDs in different datum type has different value structure.
+#
+# 3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD
+# The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64
+# data member in PCD database, For example:
+# UINT16 PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;
+# Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"
+# Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration
+# in DEC file.
+#
+# 3.3.2.2 VOID* datum type PCD
+# The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.
+#
+# 3.3.2.2.1 VOID* - string type
+# If the default value for VOID* datum type PCD like L"xxx", the PCD is
+# used for unicode string, and C structure of this datum type PCD is
+# UINT16 string array in PCD database, for example:
+# UINT16 StringTable[29];
+# The number of 29 in above sample is max size of a unicode string.
+#
+# If the default value for VOID* datum type PCD like "xxx", the PCD is
+# used for ascii string, and C structure of this datum type PCD is
+# UINT8 string array in PCD database, for example:
+# UINT8 StringTable[20];
+# The number of 20 in above sample is max size of a ascii string.
+#
+# 3.3.2.2.2 VOID* - byte array
+# If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}
+# the PCD is used for byte array. The generated structrue is same as
+# above ascii string table,
+# UINT8 StringTable[13];
+# The number of 13 in above sample is max size of byte array.
+#
+# 3.3.3 Some utility structures in PCD Database
+# 3.3.3.1 GuidTable
+# GuidTable array is used to store all related GUID value in PCD database:
+# - Variable GUID for HII type PCD
+# - Token space GUID for dynamicex type PCD
+#
+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcdDxe
+ MODULE_UNI_FILE = PcdDxe.uni
+ FILE_GUID = 80CF7257-87AB-47f9-A3FE-D50B76D89541
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 4.0
+ PCD_IS_DRIVER = DXE_PCD_DRIVER
+ ENTRY_POINT = PcdDxeInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Pcd.c
+ Service.c
+ Service.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ HobLib
+ UefiDriverEntryPoint
+ UefiLib
+ DebugLib
+ BaseLib
+ PcdLib
+ DxeServicesLib
+
+[Guids]
+ gPcdDataBaseHobGuid ## SOMETIMES_CONSUMES ## HOB
+ gPcdDataBaseSignatureGuid ## CONSUMES ## GUID # PCD database signature GUID.
+
+[Protocols]
+ gPcdProtocolGuid ## PRODUCES
+ gEfiPcdProtocolGuid ## PRODUCES
+ gGetPcdInfoProtocolGuid ## SOMETIMES_PRODUCES
+ gEfiGetPcdInfoProtocolGuid ## SOMETIMES_PRODUCES
+ ## NOTIFY
+ ## SOMETIMES_CONSUMES
+ gEdkiiVariableLockProtocolGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress ## SOMETIMES_CONSUMES
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ PcdDxeExtra.uni
diff --git a/Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni b/Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni
new file mode 100644
index 0000000000..922391c3ce
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni
@@ -0,0 +1,297 @@
+// /** @file
+// PCD DXE driver manage database contains all dynamic PCD entries and produce the implementation of PCD protocol.
+//
+// This version PCD DXE depends on the external PCD database binary file, not built in PCD data base.
+// There are two PCD Protocols as follows:
+// 1) PCD_PROTOCOL
+// It is EDKII implementation which support Dynamic/DynamicEx type Pcds.
+// 2) EFI_PCD_PROTOCOL
+// It is defined by PI specification 1.2, Vol 3 which only support dynamicEx
+// type Pcd.
+//
+// For dynamicEx type PCD, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL.
+// PCD DXE driver will produce above two protocols at same time.
+//
+// PCD database is generated as the separate binary image at build time. The binary image
+// will be intergrated into Firmware volume together with PCD driver.
+//
+// ////////////////////////////////////////////////////////////////////////////////
+// // //
+// // Introduction of PCD database //
+// // //
+// ////////////////////////////////////////////////////////////////////////////////
+//
+// 1, Introduction
+// PCD database hold all dynamic type PCD information. The structure of PEI PCD
+// database is generated by build tools according to dynamic PCD usage for
+// specified platform.
+//
+// 2, Dynamic Type PCD
+// Dynamic type PCD is used for the configuration/setting which value is determined
+// dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,
+// PatchablePcd) is fixed in final generated FD image in build time.
+//
+// 2.1 The "dynamic" determination means one of below cases:
+// a) The PCD setting value is produced by someone driver and consumed by
+// other driver in execution time.
+// b) The PCD setting value is set/get by user from FrontPage.
+// c) The PCD setting value is produced by platform OEM vendor in specified area.
+//
+// 2.2 According to module distribution way, dynamic PCD could be classfied as:
+// a) Dynamic:
+// If module is released in source code and will be built with platform
+// DSC, the dynamic PCD used by this module can be accessed as:
+// PcdGetxx(PcdSampleDynamicPcd);
+// In building platform, build tools will translate PcdSampleDynamicPcd to
+// pair of {Token Space Guid: Token Number} for this PCD.
+// b) DynamicEx:
+// If module is release as binary and will not pariticpate platform building,
+// the dynamic PCD used by this module need be accessed as:
+// PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)
+// Developer need explicity gives {Token Space Guid:Token Number} as parameter
+// in writting source code.
+//
+// 2.3 According to PCD value's storage method, dynamic PCD could be classfied as:
+// a) Default Storage:
+// - The PCD value is stored in PCD database maintained by PCD driver in boot
+// time memory.
+// - This type is used for communication between PEIM/DXE driver, DXE/DXE
+// driver. But all set/get value will be losted after boot-time memory
+// is turn off.
+// - [PcdsDynamicDefault] is used as section name for this type PCD in
+// platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.
+//
+// b) Variable Storage:
+// - The PCD value is stored in variable area.
+// - As default storage type, this type PCD could be used for PEI/DXE driver
+// communication. But beside it, this type PCD could also be used to store
+// the value associate with a HII setting via variable interface.
+// - In PEI phase, the PCD value could only be got but can not be set due
+// to variable area is readonly.
+// - [PcdsDynamicHii] is used as section name for this type PCD in platform
+// DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.
+//
+// c) OEM specificed storage area:
+// - The PCD value is stored in OEM specified area which base address is
+// specified by a FixedAtBuild PCD setting - PcdVpdBaseAddress.
+// - The area is read only for PEI and DXE phase.
+// - [PcdsDynamicVpd] is used as section name for this type PCD in platform
+// DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.
+//
+// 2.4 When and how to use dynamic PCD
+// Module developer do not care the used PCD is dynamic or static when writting
+// source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator
+// in platform DSC file. Please ref section 2.3 to get matching between dynamic
+// PCD type and section name in DSC file.
+//
+// 3, PCD database:
+// Although dynamic PCD could be in different storage type as above description,
+// but the basic information and default value for all dynamic PCD is hold
+// by PCD database maintained by PEI/DXE driver.
+//
+// As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database
+// also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.
+// To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic
+// PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD
+// database contains all PCDs used in PEI/DXE phase in memory.
+//
+// Build tool will generate PCD database into the separate binary file for
+// PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.
+//
+// 3.1 PcdPeim and PcdDxe
+// PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver
+// build guid hob in temporary memory and copy the binary data base from flash
+// to temporary memory for PEI PCD database.
+// DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,
+// a new PCD database is allocated in boot-time memory which including all
+// PEI PCD and DXE PCD entry.
+//
+// Pcd driver should run as early as possible before any other driver access
+// dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by
+// making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.
+//
+// 3.2 Token space Guid/Token number, Platform token, Local token number
+// Dynamic PCD
+// +-----------+ +---------+
+// |TokenSpace | |Platform |
+// | Guid | build tool | Token |
+// | + +-------------->| Number |
+// | Token | +---------+`._
+// | Number | `.
+// +-----------+ `. +------+
+// `-|Local |
+// |Token |
+// DynamicEx PCD ,-|Number|
+// +-----------+ ,-' +------+
+// |TokenSpace | ,-'
+// | Guid | _,-'
+// | + +.'
+// | Token |
+// | Number |
+// +-----------+
+//
+//
+// 3.2.1 Pair of Token space guid + Token number
+// Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it
+// is not easy maintained by PCD driver, and hashed token number will make
+// searching slowly.
+//
+// 3.2.2 Platform Token Number
+// "Platform token number" concept is introduced for mapping to a pair of
+// "TokenSpaceGuid + TokenNumber". The platform token number is generated by
+// build tool in autogen.h and all of them are continual in a platform scope
+// started from 1.(0 meaning invalid internal token number)
+// With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)
+// in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)
+// in autogen.h.
+// Notes: The mapping between pair of "tokenspace guid + token number" and
+// "internal token number" need build tool establish, so "platform token number"
+// mechanism is not suitable for binary module which use DynamicEx type PCD.
+// To access a dynamicEx type PCD, pair of "token space guid/token number" all need
+// to be specificed for PcdSet/PcdGet accessing macro.
+//
+// Platform Token Number is started from 1, and inceased continuous. From whole
+// platform scope, there are two zones: PEI Zone and DXE Zone
+// | Platform Token Number
+// ----------|----------------------------------------------------------------
+// PEI Zone: | 1 ~ PEI_LOCAL_TOKEN_NUMBER
+// DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)
+//
+// 3.2.3 Local Token Number
+// To fast searching a PCD entry in PCD database, PCD driver translate
+// platform token number to local token number via a mapping table.
+// For binary DynamicEx type PCD, there is a another mapping table to translate
+// "token space guid + token number" to local token number directly.
+// Local token number is identifier for all internal interface in PCD PEI/DXE
+// driver.
+//
+// A local token number is a 32-bit value in following meaning:
+// 32 ------------- 28 ---------- 24 -------- 0
+// | PCD type mask | Datum Type | Offset |
+// +-----------------------------------------+
+// where:
+// PCd type mask: indicate Pcd type from following macro:
+// PCD_TYPE_DATA
+// PCD_TYPE_HII
+// PCD_TYPE_VPD
+// PCD_TYPE_SKU_ENABLED
+// PCD_TYPE_STRING
+// Datum Type : indicate PCD vaue type from following macro:
+// PCD_DATUM_TYPE_POINTER
+// PCD_DATUM_TYPE_UINT8
+// PCD_DATUM_TYPE_UINT16
+// PCD_DATUM_TYPE_UINT32
+// PCD_DATUM_TYPE_UINT64
+// Offset : indicate the related offset of PCD value in PCD database array.
+// Based on local token number, PCD driver could fast determine PCD type, value
+// type and get PCD entry from PCD database.
+//
+// 3.3 PCD Database binary file
+// PCD Database binary file will be created at build time as the standalone binary image.
+// To understand the binary image layout, PCD Database C structure is still generated
+// as comments by build tools in PCD driver's autogen.h/
+// autogen.c file. In generated C structure, following information is stored:
+// - ExMapTable: This table is used translate a binary dynamicex type PCD's
+// "tokenguid + token" to local token number.
+// - LocalTokenNumberTable:
+// This table stores all local token number in array, use "Internal
+// token number" as array index to get PCD entry's offset fastly.
+// - SizeTable: This table stores the size information for all PCD entry.
+// - GuidTable: This table stores guid value for DynamicEx's token space,
+// HII type PCD's variable GUID.
+// - SkuIdTable: TBD
+// - SystemSkuId: TBD
+// - PCD value structure:
+// Every PCD has a value record in PCD database. For different
+// datum type PCD has different record structure which will be
+// introduced in 3.3.1
+//
+// In a PCD database structure, there are two major area: Init and UnInit.
+// Init area is use stored above PCD internal structure such as ExMapTable,
+// LocalTokenNumberTable etc and the (default) value of PCD which has default
+// value specified in platform DSC file.
+// Unint area is used stored the value of PCD which has no default value in
+// platform DSC file, the value of NULL, 0 specified in platform DSC file can
+// be seemed as "no default value".
+//
+// 3.3.1 Simple Sample PCD Database C Structure
+// A general sample of PCD database structue is as follows:
+// typedef struct _PCD_DATABASE {
+// typedef struct _PCD_DATABASE_INIT {
+// //===== Following is PCD database internal maintain structures
+// DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];
+// UINT32 LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
+// GUID GuidTable[PEI_GUID_TABLE_SIZE];
+// SIZE_INFO SizeTable[PEI_SIZE_TABLE_SIZE];
+// UINT8 SkuIdTable[PEI_SKUID_TABLE_SIZE];
+// SKU_ID SystemSkuId;
+//
+// //===== Following is value structure for PCD with default value
+// ....
+// ....
+// ....
+// } Init;
+// typedef struct _PCD_DATABSE_UNINIT {
+// //==== Following is value structure for PCD without default value
+// ....
+// ....
+// } UnInit;
+// }
+//
+// 3.3.2 PCD value structure in PCD database C structure
+// The value's structure is generated by build tool in PCD database C structure.
+// The PCDs in different datum type has different value structure.
+//
+// 3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD
+// The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64
+// data member in PCD database, For example:
+// UINT16 PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;
+// Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"
+// Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration
+// in DEC file.
+//
+// 3.3.2.2 VOID* datum type PCD
+// The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.
+//
+// 3.3.2.2.1 VOID* - string type
+// If the default value for VOID* datum type PCD like L"xxx", the PCD is
+// used for unicode string, and C structure of this datum type PCD is
+// UINT16 string array in PCD database, for example:
+// UINT16 StringTable[29];
+// The number of 29 in above sample is max size of a unicode string.
+//
+// If the default value for VOID* datum type PCD like "xxx", the PCD is
+// used for ascii string, and C structure of this datum type PCD is
+// UINT8 string array in PCD database, for example:
+// UINT8 StringTable[20];
+// The number of 20 in above sample is max size of a ascii string.
+//
+// 3.3.2.2.2 VOID* - byte array
+// If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}
+// the PCD is used for byte array. The generated structrue is same as
+// above ascii string table,
+// UINT8 StringTable[13];
+// The number of 13 in above sample is max size of byte array.
+//
+// 3.3.3 Some utility structures in PCD Database
+// 3.3.3.1 GuidTable
+// GuidTable array is used to store all related GUID value in PCD database:
+// - Variable GUID for HII type PCD
+// - Token space GUID for dynamicex type PCD
+//
+// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "PCD DXE driver manages the database that contains all dynamic PCD entries and produce the implementation of PCD protocol"
+
+#string STR_MODULE_DESCRIPTION #language en-US "PCD DXE driver manages the database that contains all dynamic PCD entries and produces the implementation of PCD protocol."
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni b/Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni
new file mode 100644
index 0000000000..729312a2d8
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// PcdDxe Localized Strings and Content
+//
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Platform Configuration Database DXE Driver"
+
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Dxe/Service.c b/Core/MdeModulePkg/Universal/PCD/Dxe/Service.c
new file mode 100644
index 0000000000..efe72483c5
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Dxe/Service.c
@@ -0,0 +1,2008 @@
+/** @file
+ Help functions used by PCD DXE driver.
+
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Service.h"
+#include <Library/DxeServicesLib.h>
+
+PCD_DATABASE mPcdDatabase;
+
+UINT32 mPcdTotalTokenCount;
+UINT32 mPeiLocalTokenCount;
+UINT32 mDxeLocalTokenCount;
+UINT32 mPeiNexTokenCount;
+UINT32 mDxeNexTokenCount;
+UINT32 mPeiExMapppingTableSize;
+UINT32 mDxeExMapppingTableSize;
+UINT32 mPeiGuidTableSize;
+UINT32 mDxeGuidTableSize;
+
+BOOLEAN mPeiExMapTableEmpty;
+BOOLEAN mDxeExMapTableEmpty;
+BOOLEAN mPeiDatabaseEmpty;
+
+LIST_ENTRY *mCallbackFnTable;
+EFI_GUID **TmpTokenSpaceBuffer;
+UINTN TmpTokenSpaceBufferCount;
+
+/**
+ Get Local Token Number by Token Number.
+
+ @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
+ If FALSE, the pcd entry is initialized in DXE phase.
+ @param[in] TokenNumber The PCD token number.
+
+ @return Local Token Number.
+**/
+UINT32
+GetLocalTokenNumber (
+ IN BOOLEAN IsPeiDb,
+ IN UINTN TokenNumber
+ )
+{
+ UINTN TmpTokenNumber;
+ UINT32 *LocalTokenNumberTable;
+ UINT32 LocalTokenNumber;
+ UINTN Size;
+ UINTN MaxSize;
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ //
+ // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
+ //
+ TmpTokenNumber = TokenNumber;
+
+ LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) :
+ (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
+ TokenNumber = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount;
+
+ LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
+
+ Size = (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
+ if (Size == 0) {
+ GetPtrTypeSize (TmpTokenNumber, &MaxSize);
+ } else {
+ MaxSize = Size;
+ }
+ LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);
+ }
+
+ return LocalTokenNumber;
+}
+
+/**
+ Get PCD type by Local Token Number.
+
+ @param[in] LocalTokenNumber The PCD local token number.
+
+ @return PCD type.
+**/
+EFI_PCD_TYPE
+GetPcdType (
+ IN UINT32 LocalTokenNumber
+ )
+{
+ switch (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) {
+ case PCD_DATUM_TYPE_POINTER:
+ return EFI_PCD_TYPE_PTR;
+ case PCD_DATUM_TYPE_UINT8:
+ if ((LocalTokenNumber & PCD_DATUM_TYPE_UINT8_BOOLEAN) == PCD_DATUM_TYPE_UINT8_BOOLEAN) {
+ return EFI_PCD_TYPE_BOOL;
+ } else {
+ return EFI_PCD_TYPE_8;
+ }
+ case PCD_DATUM_TYPE_UINT16:
+ return EFI_PCD_TYPE_16;
+ case PCD_DATUM_TYPE_UINT32:
+ return EFI_PCD_TYPE_32;
+ case PCD_DATUM_TYPE_UINT64:
+ return EFI_PCD_TYPE_64;
+ default:
+ ASSERT (FALSE);
+ return EFI_PCD_TYPE_8;
+ }
+}
+
+/**
+ Get PCD name.
+
+ @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.
+ If FALSE, need to get the full PCD name.
+ @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
+ If FALSE, the pcd entry is initialized in DXE phase.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The TokenSpaceCName or full PCD name.
+**/
+CHAR8 *
+GetPcdName (
+ IN BOOLEAN OnlyTokenSpaceName,
+ IN BOOLEAN IsPeiDb,
+ IN UINTN TokenNumber
+ )
+{
+ PCD_DATABASE_INIT *Database;
+ UINT8 *StringTable;
+ UINTN NameSize;
+ PCD_NAME_INDEX *PcdNameIndex;
+ CHAR8 *TokenSpaceName;
+ CHAR8 *PcdName;
+ CHAR8 *Name;
+
+ //
+ // Return NULL when PCD name table is absent.
+ //
+ if (IsPeiDb) {
+ if (mPcdDatabase.PeiDb->PcdNameTableOffset == 0) {
+ return NULL;
+ }
+ } else {
+ if (mPcdDatabase.DxeDb->PcdNameTableOffset == 0) {
+ return NULL;
+ }
+ }
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;
+ TokenNumber = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount;
+
+ StringTable = (UINT8 *) Database + Database->StringTableOffset;
+
+ //
+ // Get the PCD name index.
+ //
+ PcdNameIndex = (PCD_NAME_INDEX *)((UINT8 *) Database + Database->PcdNameTableOffset) + TokenNumber;
+ TokenSpaceName = (CHAR8 *)&StringTable[PcdNameIndex->TokenSpaceCNameIndex];
+ PcdName = (CHAR8 *)&StringTable[PcdNameIndex->PcdCNameIndex];
+
+ if (OnlyTokenSpaceName) {
+ //
+ // Only need to get the TokenSpaceCName.
+ //
+ Name = AllocateCopyPool (AsciiStrSize (TokenSpaceName), TokenSpaceName);
+ } else {
+ //
+ // Need to get the full PCD name.
+ //
+ NameSize = AsciiStrSize (TokenSpaceName) + AsciiStrSize (PcdName);
+ Name = AllocateZeroPool (NameSize);
+ ASSERT (Name != NULL);
+ //
+ // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
+ //
+ AsciiStrCatS (Name, NameSize, TokenSpaceName);
+ Name[AsciiStrSize (TokenSpaceName) - sizeof (CHAR8)] = '.';
+ AsciiStrCatS (Name, NameSize, PcdName);
+ }
+
+ return Name;
+}
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
+ If FALSE, the pcd entry is initialized in DXE phase.
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+ExGetPcdInfo (
+ IN BOOLEAN IsPeiDb,
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ PCD_DATABASE_INIT *Database;
+ UINTN GuidTableIdx;
+ EFI_GUID *MatchGuid;
+ EFI_GUID *GuidTable;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+ UINT32 LocalTokenNumber;
+
+ Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;
+
+ GuidTable = (EFI_GUID *)((UINT8 *)Database + Database->GuidTableOffset);
+ MatchGuid = ScanGuid (GuidTable, Database->GuidTableCount * sizeof(EFI_GUID), Guid);
+
+ if (MatchGuid == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ GuidTableIdx = MatchGuid - GuidTable;
+
+ ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)Database + Database->ExMapTableOffset);
+
+ //
+ // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
+ //
+ for (Index = 0; Index < Database->ExTokenCount; Index++) {
+ if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ //
+ // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
+ // PcdSize to 0 and PcdName to the null-terminated ASCII string
+ // associated with the token's namespace Guid.
+ //
+ PcdInfo->PcdType = EFI_PCD_TYPE_8;
+ PcdInfo->PcdSize = 0;
+ //
+ // Here use one representative in the token space to get the TokenSpaceCName.
+ //
+ PcdInfo->PcdName = GetPcdName (TRUE, IsPeiDb, ExMapTable[Index].TokenNumber);
+ return EFI_SUCCESS;
+ } else if (ExMapTable[Index].ExTokenNumber == TokenNumber) {
+ PcdInfo->PcdSize = DxePcdGetSize (ExMapTable[Index].TokenNumber);
+ LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, ExMapTable[Index].TokenNumber);
+ PcdInfo->PcdType = GetPcdType (LocalTokenNumber);
+ PcdInfo->PcdName = GetPcdName (FALSE, IsPeiDb, ExMapTable[Index].TokenNumber);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+DxeGetPcdInfo (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN PeiExMapTableEmpty;
+ BOOLEAN DxeExMapTableEmpty;
+ UINT32 LocalTokenNumber;
+ BOOLEAN IsPeiDb;
+
+ ASSERT (PcdInfo != NULL);
+
+ Status = EFI_NOT_FOUND;
+ PeiExMapTableEmpty = mPeiExMapTableEmpty;
+ DxeExMapTableEmpty = mDxeExMapTableEmpty;
+
+ if (Guid == NULL) {
+ if (((TokenNumber + 1 > mPeiNexTokenCount + 1) && (TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||
+ ((TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1)))) {
+ return EFI_NOT_FOUND;
+ } else if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ //
+ // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
+ // PcdSize to 0 and PcdName to NULL for default Token Space.
+ //
+ PcdInfo->PcdType = EFI_PCD_TYPE_8;
+ PcdInfo->PcdSize = 0;
+ PcdInfo->PcdName = NULL;
+ } else {
+ PcdInfo->PcdSize = DxePcdGetSize (TokenNumber);
+ IsPeiDb = FALSE;
+ if ((TokenNumber + 1 <= mPeiNexTokenCount + 1)) {
+ IsPeiDb = TRUE;
+ }
+ LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber);
+ PcdInfo->PcdType = GetPcdType (LocalTokenNumber);
+ PcdInfo->PcdName = GetPcdName (FALSE, IsPeiDb, TokenNumber);
+ }
+ return EFI_SUCCESS;
+ }
+
+ if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (!PeiExMapTableEmpty) {
+ Status = ExGetPcdInfo (
+ TRUE,
+ Guid,
+ TokenNumber,
+ PcdInfo
+ );
+ }
+
+ if (Status == EFI_SUCCESS) {
+ return Status;
+ }
+
+ if (!DxeExMapTableEmpty) {
+ Status = ExGetPcdInfo (
+ FALSE,
+ Guid,
+ TokenNumber,
+ PcdInfo
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Get the PCD entry pointer in PCD database.
+
+ This routine will visit PCD database to find the PCD entry according to given
+ token number. The given token number is autogened by build tools and it will be
+ translated to local token number. Local token number contains PCD's type and
+ offset of PCD entry in PCD database.
+
+ @param TokenNumber Token's number, it is autogened by build tools
+ @param GetSize The size of token's value
+
+ @return PCD entry pointer in PCD database
+
+**/
+VOID *
+GetWorker (
+ IN UINTN TokenNumber,
+ IN UINTN GetSize
+ )
+{
+ EFI_GUID *GuidTable;
+ UINT8 *StringTable;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ VARIABLE_HEAD *VariableHead;
+ UINT8 *VaraiableDefaultBuffer;
+ UINT8 *Data;
+ VPD_HEAD *VpdHead;
+ UINT8 *PcdDb;
+ VOID *RetPtr;
+ UINTN TmpTokenNumber;
+ UINTN DataSize;
+ EFI_STATUS Status;
+ UINT32 LocalTokenNumber;
+ UINT32 Offset;
+ STRING_HEAD StringTableIdx;
+ BOOLEAN IsPeiDb;
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ RetPtr = NULL;
+
+ ASSERT (TokenNumber > 0);
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ TmpTokenNumber = TokenNumber;
+
+ //
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ //
+ ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);
+
+ ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);
+
+ LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);
+
+ PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);
+
+ if (IsPeiDb) {
+ StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);
+ } else {
+ StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);
+ }
+
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);
+ RetPtr = (VOID *) ((UINTN) PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);
+
+ break;
+
+ case PCD_TYPE_HII|PCD_TYPE_STRING:
+ case PCD_TYPE_HII:
+ if (IsPeiDb) {
+ GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);
+ } else {
+ GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);
+ }
+
+ VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
+ Guid = GuidTable + VariableHead->GuidTableIndex;
+ Name = (UINT16*)(StringTable + VariableHead->StringIndex);
+
+ if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {
+ //
+ // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
+ // string array in string table.
+ //
+ StringTableIdx = *(STRING_HEAD*)((UINT8 *) PcdDb + VariableHead->DefaultValueOffset);
+ VaraiableDefaultBuffer = (UINT8 *) (StringTable + StringTableIdx);
+ } else {
+ VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;
+ }
+ Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
+ if (Status == EFI_SUCCESS) {
+ if (DataSize >= (VariableHead->Offset + GetSize)) {
+ if (GetSize == 0) {
+ //
+ // It is a pointer type. So get the MaxSize reserved for
+ // this PCD entry.
+ //
+ GetPtrTypeSize (TmpTokenNumber, &GetSize);
+ if (GetSize > (DataSize - VariableHead->Offset)) {
+ //
+ // Use actual valid size.
+ //
+ GetSize = DataSize - VariableHead->Offset;
+ }
+ }
+ //
+ // If the operation is successful, we copy the data
+ // to the default value buffer in the PCD Database.
+ // So that we can free the Data allocated in GetHiiVariable.
+ //
+ CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);
+ }
+ FreePool (Data);
+ }
+ RetPtr = (VOID *) VaraiableDefaultBuffer;
+ break;
+
+ case PCD_TYPE_STRING:
+ StringTableIdx = *(STRING_HEAD*)((UINT8 *) PcdDb + Offset);
+ RetPtr = (VOID *) (StringTable + StringTableIdx);
+ break;
+
+ case PCD_TYPE_DATA:
+ RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+
+ }
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return RetPtr;
+
+}
+
+/**
+ Register the callback function for a PCD entry.
+
+ This routine will register a callback function to a PCD entry by given token number
+ and token space guid.
+
+ @param TokenNumber PCD token's number, it is autogened by build tools.
+ @param Guid PCD token space's guid,
+ if not NULL, this PCD is dynamicEx type PCD.
+ @param CallBackFunction Callback function pointer
+
+ @return EFI_SUCCESS Always success for registering callback function.
+
+**/
+EFI_STATUS
+DxeRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+)
+{
+ CALLBACK_FN_ENTRY *FnTableEntry;
+ LIST_ENTRY *ListHead;
+ LIST_ENTRY *ListNode;
+
+ if (Guid != NULL) {
+ TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
+ }
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index of mCallbackFnTable[].
+ //
+ ListHead = &mCallbackFnTable[TokenNumber - 1];
+ ListNode = GetFirstNode (ListHead);
+
+ while (ListNode != ListHead) {
+ FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
+
+ if (FnTableEntry->CallbackFn == CallBackFunction) {
+ //
+ // We only allow a Callback function to be register once
+ // for a TokenNumber. So just return EFI_SUCCESS
+ //
+ return EFI_SUCCESS;
+ }
+ ListNode = GetNextNode (ListHead, ListNode);
+ }
+
+ FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));
+ ASSERT (FnTableEntry != NULL);
+
+ FnTableEntry->CallbackFn = CallBackFunction;
+ InsertTailList (ListHead, &FnTableEntry->Node);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ UnRegister the callback function for a PCD entry.
+
+ This routine will unregister a callback function to a PCD entry by given token number
+ and token space guid.
+
+ @param TokenNumber PCD token's number, it is autogened by build tools.
+ @param Guid PCD token space's guid.
+ if not NULL, this PCD is dynamicEx type PCD.
+ @param CallBackFunction Callback function pointer
+
+ @retval EFI_SUCCESS Callback function is success to be unregister.
+ @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.
+**/
+EFI_STATUS
+DxeUnRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+)
+{
+ CALLBACK_FN_ENTRY *FnTableEntry;
+ LIST_ENTRY *ListHead;
+ LIST_ENTRY *ListNode;
+
+ if (Guid != NULL) {
+ TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);
+ }
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index of mCallbackFnTable[].
+ //
+ ListHead = &mCallbackFnTable[TokenNumber - 1];
+ ListNode = GetFirstNode (ListHead);
+
+ while (ListNode != ListHead) {
+ FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
+
+ if (FnTableEntry->CallbackFn == CallBackFunction) {
+ //
+ // We only allow a Callback function to be register once
+ // for a TokenNumber. So we can safely remove the Node from
+ // the Link List and return EFI_SUCCESS.
+ //
+ RemoveEntryList (ListNode);
+ FreePool (FnTableEntry);
+
+ return EFI_SUCCESS;
+ }
+ ListNode = GetNextNode (ListHead, ListNode);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Get next token number in given token space.
+
+ This routine is used for dynamicEx type PCD. It will firstly scan token space
+ table to get token space according to given token space guid. Then scan given
+ token number in found token space, if found, then return next token number in
+ this token space.
+
+ @param Guid Token space guid. Next token number will be scaned in
+ this token space.
+ @param TokenNumber Token number.
+ If PCD_INVALID_TOKEN_NUMBER, return first token number in
+ token space table.
+ If not PCD_INVALID_TOKEN_NUMBER, return next token number
+ in token space table.
+ @param GuidTable Token space guid table. It will be used for scan token space
+ by given token space guid.
+ @param SizeOfGuidTable The size of guid table.
+ @param ExMapTable DynamicEx token number mapping table.
+ @param SizeOfExMapTable The size of dynamicEx token number mapping table.
+
+ @retval EFI_NOT_FOUND Can not given token space or token number.
+ @retval EFI_SUCCESS Success to get next token number.
+
+**/
+EFI_STATUS
+ExGetNextTokeNumber (
+ IN CONST EFI_GUID *Guid,
+ IN OUT UINTN *TokenNumber,
+ IN EFI_GUID *GuidTable,
+ IN UINTN SizeOfGuidTable,
+ IN DYNAMICEX_MAPPING *ExMapTable,
+ IN UINTN SizeOfExMapTable
+ )
+{
+ EFI_GUID *MatchGuid;
+ UINTN Index;
+ UINTN GuidTableIdx;
+ BOOLEAN Found;
+ UINTN ExMapTableCount;
+
+ //
+ // Scan token space guid
+ //
+ MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);
+ if (MatchGuid == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the token space table in dynamicEx mapping table.
+ //
+ Found = FALSE;
+ GuidTableIdx = MatchGuid - GuidTable;
+ ExMapTableCount = SizeOfExMapTable / sizeof(ExMapTable[0]);
+ for (Index = 0; Index < ExMapTableCount; Index++) {
+ if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (Found) {
+ //
+ // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
+ // token number in found token space.
+ //
+ if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ *TokenNumber = ExMapTable[Index].ExTokenNumber;
+ return EFI_SUCCESS;
+ }
+
+ for ( ; Index < ExMapTableCount; Index++) {
+ if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {
+ break;
+ }
+ }
+
+ while (Index < ExMapTableCount) {
+ Index++;
+ if (Index == ExMapTableCount) {
+ //
+ // Exceed the length of ExMap Table
+ //
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_NOT_FOUND;
+ } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ //
+ // Found the next match
+ //
+ *TokenNumber = ExMapTable[Index].ExTokenNumber;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Find the PCD database.
+
+ @retval The base address of external PCD database binary.
+ @retval NULL Return NULL if not find.
+**/
+DXE_PCD_DATABASE *
+LocateExPcdBinary (
+ VOID
+)
+{
+ DXE_PCD_DATABASE *DxePcdDbBinary;
+ UINTN DxePcdDbSize;
+ EFI_STATUS Status;
+
+ DxePcdDbBinary = NULL;
+ //
+ // Search the External Pcd database from one section of current FFS,
+ // and read it to memory
+ //
+ Status = GetSectionFromFfs (
+ EFI_SECTION_RAW,
+ 0,
+ (VOID **) &DxePcdDbBinary,
+ &DxePcdDbSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Check the first bytes (Header Signature Guid) and build version.
+ //
+ if (!CompareGuid ((VOID *)DxePcdDbBinary, &gPcdDataBaseSignatureGuid) ||
+ (DxePcdDbBinary->BuildVersion != PCD_SERVICE_DXE_VERSION)) {
+ ASSERT (FALSE);
+ }
+
+ return DxePcdDbBinary;
+}
+
+/**
+ Initialize the PCD database in DXE phase.
+
+ PCD database in DXE phase also contains PCD database in PEI phase which is copied
+ from GUID Hob.
+
+**/
+VOID
+BuildPcdDxeDataBase (
+ VOID
+ )
+{
+ PEI_PCD_DATABASE *PeiDatabase;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINTN Index;
+ UINT32 PcdDxeDbLen;
+ VOID *PcdDxeDb;
+
+ //
+ // Assign PCD Entries with default value to PCD DATABASE
+ //
+ mPcdDatabase.DxeDb = LocateExPcdBinary ();
+ ASSERT(mPcdDatabase.DxeDb != NULL);
+ PcdDxeDbLen = mPcdDatabase.DxeDb->Length + mPcdDatabase.DxeDb->UninitDataBaseSize;
+ PcdDxeDb = AllocateZeroPool (PcdDxeDbLen);
+ ASSERT (PcdDxeDb != NULL);
+ CopyMem (PcdDxeDb, mPcdDatabase.DxeDb, mPcdDatabase.DxeDb->Length);
+ FreePool (mPcdDatabase.DxeDb);
+ mPcdDatabase.DxeDb = PcdDxeDb;
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ if (GuidHob != NULL) {
+
+ //
+ // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
+ // should not be included at all. So the GuidHob could
+ // be NULL. If it is NULL, we just copy over the DXE Default
+ // Value to PCD Database.
+ //
+
+ PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
+ //
+ // Assign PCD Entries refereneced in PEI phase to PCD DATABASE
+ //
+ mPcdDatabase.PeiDb = PeiDatabase;
+ //
+ // Inherit the SystemSkuId from PEI phase.
+ //
+ mPcdDatabase.DxeDb->SystemSkuId = mPcdDatabase.PeiDb->SystemSkuId;
+ } else {
+ mPcdDatabase.PeiDb = AllocateZeroPool (sizeof (PEI_PCD_DATABASE));
+ ASSERT(mPcdDatabase.PeiDb != NULL);
+ }
+
+ //
+ // Initialized the external PCD database local variables
+ //
+ mPeiLocalTokenCount = mPcdDatabase.PeiDb->LocalTokenCount;
+ mDxeLocalTokenCount = mPcdDatabase.DxeDb->LocalTokenCount;
+
+ mPeiExMapppingTableSize = mPcdDatabase.PeiDb->ExTokenCount * sizeof (DYNAMICEX_MAPPING);
+ mDxeExMapppingTableSize = mPcdDatabase.DxeDb->ExTokenCount * sizeof (DYNAMICEX_MAPPING);
+ mPeiGuidTableSize = mPcdDatabase.PeiDb->GuidTableCount * sizeof(GUID);
+ mDxeGuidTableSize = mPcdDatabase.DxeDb->GuidTableCount * sizeof (GUID);
+
+ mPcdTotalTokenCount = mPeiLocalTokenCount + mDxeLocalTokenCount;
+ mPeiNexTokenCount = mPeiLocalTokenCount - mPcdDatabase.PeiDb->ExTokenCount;
+ mDxeNexTokenCount = mDxeLocalTokenCount - mPcdDatabase.DxeDb->ExTokenCount;
+
+ mPeiExMapTableEmpty = (mPcdDatabase.PeiDb->ExTokenCount == 0) ? TRUE : FALSE;
+ mDxeExMapTableEmpty = (mPcdDatabase.DxeDb->ExTokenCount == 0) ? TRUE : FALSE;
+ mPeiDatabaseEmpty = (mPeiLocalTokenCount == 0) ? TRUE : FALSE;
+
+ TmpTokenSpaceBufferCount = mPcdDatabase.PeiDb->ExTokenCount + mPcdDatabase.DxeDb->ExTokenCount;
+ TmpTokenSpaceBuffer = (EFI_GUID **)AllocateZeroPool(TmpTokenSpaceBufferCount * sizeof (EFI_GUID *));
+
+ //
+ // Initialized the Callback Function Table
+ //
+ mCallbackFnTable = AllocateZeroPool (mPcdTotalTokenCount * sizeof (LIST_ENTRY));
+ ASSERT(mCallbackFnTable != NULL);
+
+ //
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ //
+ for (Index = 0; Index + 1 < mPcdTotalTokenCount + 1; Index++) {
+ InitializeListHead (&mCallbackFnTable[Index]);
+ }
+}
+
+/**
+ Get Variable which contains HII type PCD entry.
+
+ @param VariableGuid Variable's guid
+ @param VariableName Variable's unicode name string
+ @param VariableData Variable's data pointer,
+ @param VariableSize Variable's size.
+
+ @return the status of gRT->GetVariable
+**/
+EFI_STATUS
+GetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT UINT8 **VariableData,
+ OUT UINTN *VariableSize
+ )
+{
+ UINTN Size;
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+
+ Size = 0;
+ Buffer = NULL;
+
+ //
+ // Firstly get the real size of HII variable
+ //
+ Status = gRT->GetVariable (
+ (UINT16 *)VariableName,
+ VariableGuid,
+ NULL,
+ &Size,
+ Buffer
+ );
+
+ //
+ // Allocate buffer to hold whole variable data according to variable size.
+ //
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = (UINT8 *) AllocatePool (Size);
+
+ ASSERT (Buffer != NULL);
+
+ Status = gRT->GetVariable (
+ VariableName,
+ VariableGuid,
+ NULL,
+ &Size,
+ Buffer
+ );
+
+ ASSERT (Status == EFI_SUCCESS);
+ *VariableData = Buffer;
+ *VariableSize = Size;
+ } else {
+ //
+ // Use Default Data only when variable is not found.
+ // For other error status, correct data can't be got, and trig ASSERT().
+ //
+ ASSERT (Status == EFI_NOT_FOUND);
+ }
+
+ return Status;
+}
+
+/**
+ Find the local token number according to system SKU ID.
+
+ @param LocalTokenNumber PCD token number
+ @param Size The size of PCD entry.
+ @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.
+ If False, the PCD entry is initialized in DXE phase.
+
+ @return Token number according to system SKU ID.
+
+**/
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size,
+ BOOLEAN IsPeiDb
+ )
+{
+ SKU_HEAD *SkuHead;
+ SKU_ID *SkuIdTable;
+ UINTN Index;
+ UINT8 *Value;
+ UINT8 *PcdDb;
+ BOOLEAN FoundSku;
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
+
+ PcdDb = IsPeiDb ? (UINT8 *) mPcdDatabase.PeiDb : (UINT8 *) mPcdDatabase.DxeDb;
+
+ SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+ Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset);
+
+ SkuIdTable = (SKU_ID *)(PcdDb + SkuHead->SkuIdTableOffset);
+ //
+ // Find the current system's SKU ID entry in SKU ID table.
+ //
+ FoundSku = FALSE;
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (mPcdDatabase.DxeDb->SystemSkuId == SkuIdTable[Index + 1]) {
+ FoundSku = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Find the default SKU ID entry in SKU ID table.
+ //
+
+ if(!FoundSku) {
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (0 == SkuIdTable[Index + 1]) {
+ break;
+ }
+ }
+ }
+ ASSERT (Index < SkuIdTable[0]);
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);
+
+ case PCD_TYPE_HII:
+ Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);
+
+ case PCD_TYPE_HII|PCD_TYPE_STRING:
+ Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII | PCD_TYPE_STRING);
+
+ case PCD_TYPE_STRING:
+ Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);
+
+ case PCD_TYPE_DATA:
+ Value += Size * Index;
+ return (UINT32) ((Value - PcdDb) | PCD_TYPE_DATA);
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+
+}
+
+/**
+ Invoke the callback function when dynamic PCD entry was set, if this PCD entry
+ has registered callback function.
+
+ @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
+ type PCD.
+ @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
+ PCD.
+ @param TokenNumber PCD token number generated by build tools.
+ @param Data Value want to be set for this PCD entry
+ @param Size The size of value
+
+**/
+VOID
+InvokeCallbackOnSet (
+ UINT32 ExTokenNumber,
+ CONST EFI_GUID *Guid, OPTIONAL
+ UINTN TokenNumber,
+ VOID *Data,
+ UINTN Size
+ )
+{
+ CALLBACK_FN_ENTRY *FnTableEntry;
+ LIST_ENTRY *ListHead;
+ LIST_ENTRY *ListNode;
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index of mCallbackFnTable[].
+ //
+ ListHead = &mCallbackFnTable[TokenNumber - 1];
+ ListNode = GetFirstNode (ListHead);
+
+ while (ListNode != ListHead) {
+ FnTableEntry = CR_FNENTRY_FROM_LISTNODE (ListNode, CALLBACK_FN_ENTRY, Node);
+
+ FnTableEntry->CallbackFn(Guid,
+ (Guid == NULL) ? TokenNumber : ExTokenNumber,
+ Data,
+ Size);
+
+ ListNode = GetNextNode (ListHead, ListNode);
+ }
+
+ return;
+}
+
+
+/**
+ Wrapper function for setting non-pointer type value for a PCD entry.
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+
+ @return status of SetWorker.
+
+**/
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ return SetWorker (TokenNumber, Data, &Size, FALSE);
+}
+
+
+/**
+ Set value for an PCD entry
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+ @param PtrType If TRUE, the type of PCD entry's value is Pointer.
+ If False, the type of PCD entry's value is not Pointer.
+
+ @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
+ @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
+ @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
+ @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
+ range of UINT8, UINT16, UINT32, UINT64
+ @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
+**/
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+{
+ BOOLEAN IsPeiDb;
+ UINT32 LocalTokenNumber;
+ EFI_GUID *GuidTable;
+ UINT8 *StringTable;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ UINTN VariableOffset;
+ UINT32 Attributes;
+ VOID *InternalData;
+ VARIABLE_HEAD *VariableHead;
+ UINTN Offset;
+ UINT8 *PcdDb;
+ EFI_STATUS Status;
+ UINTN MaxSize;
+ UINTN TmpTokenNumber;
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ TmpTokenNumber = TokenNumber;
+
+ //
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ //
+ ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);
+
+ if (PtrType) {
+ //
+ // Get MaxSize first, then check new size with max buffer size.
+ //
+ GetPtrTypeSize (TokenNumber, &MaxSize);
+ if (*Size > MaxSize) {
+ *Size = MaxSize;
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (*Size != DxePcdGetSize (TokenNumber + 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ //
+ if ((TokenNumber + 1 < mPeiNexTokenCount + 1) ||
+ (TokenNumber + 1 >= mPeiLocalTokenCount + 1 && TokenNumber + 1 < (mPeiLocalTokenCount + mDxeNexTokenCount + 1))) {
+ InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
+ }
+
+ //
+ // Aquire lock to prevent reentrance from TPL_CALLBACK level
+ //
+ EfiAcquireLock (&mPcdDatabaseLock);
+
+ //
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ //
+ IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);
+
+ LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber + 1);
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+
+ PcdDb = IsPeiDb ? ((UINT8 *) mPcdDatabase.PeiDb) : ((UINT8 *) mPcdDatabase.DxeDb);
+
+ if (IsPeiDb) {
+ StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->StringTableOffset);
+ } else {
+ StringTable = (UINT8 *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->StringTableOffset);
+ }
+
+
+ InternalData = PcdDb + Offset;
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case PCD_TYPE_STRING:
+ if (SetPtrTypeSize (TmpTokenNumber, Size)) {
+ CopyMem (StringTable + *((STRING_HEAD *)InternalData), Data, *Size);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ case PCD_TYPE_HII|PCD_TYPE_STRING:
+ case PCD_TYPE_HII:
+ if (PtrType) {
+ if (!SetPtrTypeSize (TmpTokenNumber, Size)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ if (IsPeiDb) {
+ GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);
+ } else {
+ GuidTable = (EFI_GUID *) ((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);
+ }
+
+ VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
+
+ Guid = GuidTable + VariableHead->GuidTableIndex;
+ Name = (UINT16*) (StringTable + VariableHead->StringIndex);
+ VariableOffset = VariableHead->Offset;
+ Attributes = VariableHead->Attributes;
+ Status = SetHiiVariable (Guid, Name, Attributes, Data, *Size, VariableOffset);
+ break;
+
+ case PCD_TYPE_DATA:
+ if (PtrType) {
+ if (SetPtrTypeSize (TmpTokenNumber, Size)) {
+ CopyMem (InternalData, Data, *Size);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ Status = EFI_SUCCESS;
+ switch (*Size) {
+ case sizeof(UINT8):
+ *((UINT8 *) InternalData) = *((UINT8 *) Data);
+ break;
+
+ case sizeof(UINT16):
+ *((UINT16 *) InternalData) = *((UINT16 *) Data);
+ break;
+
+ case sizeof(UINT32):
+ *((UINT32 *) InternalData) = *((UINT32 *) Data);
+ break;
+
+ case sizeof(UINT64):
+ *((UINT64 *) InternalData) = *((UINT64 *) Data);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ break;
+
+ default:
+ ASSERT (FALSE);
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ EfiReleaseLock (&mPcdDatabaseLock);
+
+ return Status;
+}
+
+/**
+ Wrapper function for get PCD value for dynamic-ex PCD.
+
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+ @param GetSize The size of dynamic-ex PCD value.
+
+ @return PCD entry in PCD database.
+
+**/
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ )
+{
+ return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);
+}
+
+/**
+ Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
+
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data Value want to be set.
+ @param SetSize The size of value.
+
+ @return status of ExSetWorker().
+
+**/
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN SetSize
+ )
+{
+ return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);
+}
+
+/**
+ Set value for a dynamic-ex PCD entry.
+
+ This routine find the local token number according to dynamic-ex PCD's token
+ space guid and token number firstly, and invoke callback function if this PCD
+ entry registered callback function. Finally, invoken general SetWorker to set
+ PCD value.
+
+ @param ExTokenNumber Dynamic-ex PCD token number.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data PCD value want to be set
+ @param SetSize Size of value.
+ @param PtrType If TRUE, this PCD entry is pointer type.
+ If FALSE, this PCD entry is not pointer type.
+
+ @return status of SetWorker().
+
+**/
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *SetSize,
+ IN BOOLEAN PtrType
+ )
+{
+ UINTN TokenNumber;
+
+ TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);
+
+ InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);
+
+ return SetWorker (TokenNumber, Data, SetSize, PtrType);
+
+}
+
+/**
+ Get variable size and data from HII-type PCDs.
+
+ @param[in] VariableGuid Guid of variable which stored value of a HII-type PCD.
+ @param[in] VariableName Unicode name of variable which stored value of a HII-type PCD.
+ @param[out] VariableSize Pointer to variable size got from HII-type PCDs.
+ @param[out] VariableData Pointer to variable data got from HII-type PCDs.
+
+**/
+VOID
+GetVariableSizeAndDataFromHiiPcd (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT UINTN *VariableSize,
+ OUT VOID *VariableData OPTIONAL
+ )
+{
+ BOOLEAN IsPeiDb;
+ PCD_DATABASE_INIT *Database;
+ UINTN TokenNumber;
+ UINT32 LocalTokenNumber;
+ UINTN Offset;
+ EFI_GUID *GuidTable;
+ UINT8 *StringTable;
+ VARIABLE_HEAD *VariableHead;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ UINTN PcdDataSize;
+ UINTN Size;
+ UINT8 *VaraiableDefaultBuffer;
+ STRING_HEAD StringTableIdx;
+
+ *VariableSize = 0;
+
+ //
+ // Go through PCD database to find out DynamicHii PCDs.
+ //
+ for (TokenNumber = 1; TokenNumber <= mPcdTotalTokenCount; TokenNumber++) {
+ IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);
+ Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;
+ LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber);
+ if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {
+ //
+ // Get the Variable Guid and Name pointer.
+ //
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+ VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);
+ StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);
+ GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);
+ Guid = GuidTable + VariableHead->GuidTableIndex;
+ Name = (UINT16*) (StringTable + VariableHead->StringIndex);
+ if (CompareGuid (VariableGuid, Guid) && (StrCmp (VariableName, Name) == 0)) {
+ //
+ // It is the matched DynamicHii PCD.
+ //
+ PcdDataSize = DxePcdGetSize (TokenNumber);
+ Size = VariableHead->Offset + PcdDataSize;
+ if (Size > *VariableSize) {
+ *VariableSize = Size;
+ }
+ if (VariableData != NULL) {
+ if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {
+ //
+ // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
+ // string array in string table.
+ //
+ StringTableIdx = *(STRING_HEAD *) ((UINT8 *) Database + VariableHead->DefaultValueOffset);
+ VaraiableDefaultBuffer = (UINT8 *) (StringTable + StringTableIdx);
+ } else {
+ VaraiableDefaultBuffer = (UINT8 *) Database + VariableHead->DefaultValueOffset;
+ }
+ CopyMem ((UINT8 *) VariableData + VariableHead->Offset, VaraiableDefaultBuffer, PcdDataSize);
+ }
+ }
+ }
+ }
+}
+
+/**
+ Set value for HII-type PCD.
+
+ A HII-type PCD's value is stored in a variable. Setting/Getting the value of
+ HII-type PCD is to visit this variable.
+
+ @param VariableGuid Guid of variable which stored value of a HII-type PCD.
+ @param VariableName Unicode name of variable which stored value of a HII-type PCD.
+ @param SetAttributes Attributes bitmask to set for the variable.
+ @param Data Value want to be set.
+ @param DataSize Size of value
+ @param Offset Value offset of HII-type PCD in variable.
+
+ @return status of GetVariable()/SetVariable().
+
+**/
+EFI_STATUS
+SetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ IN UINT32 SetAttributes,
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ IN UINTN Offset
+ )
+{
+ UINTN Size;
+ VOID *Buffer;
+ EFI_STATUS Status;
+ UINT32 Attribute;
+ UINTN SetSize;
+
+ Size = 0;
+ SetSize = 0;
+
+ //
+ // Try to get original variable size information.
+ //
+ Status = gRT->GetVariable (
+ (UINT16 *)VariableName,
+ VariableGuid,
+ NULL,
+ &Size,
+ NULL
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Patch new PCD's value to offset in given HII variable.
+ //
+ if (Size >= (DataSize + Offset)) {
+ SetSize = Size;
+ } else {
+ SetSize = DataSize + Offset;
+ }
+ Buffer = AllocatePool (SetSize);
+ ASSERT (Buffer != NULL);
+
+ Status = gRT->GetVariable (
+ VariableName,
+ VariableGuid,
+ &Attribute,
+ &Size,
+ Buffer
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
+
+ if (SetAttributes == 0) {
+ SetAttributes = Attribute;
+ }
+
+ Status = gRT->SetVariable (
+ VariableName,
+ VariableGuid,
+ SetAttributes,
+ SetSize,
+ Buffer
+ );
+
+ FreePool (Buffer);
+ return Status;
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // If variable does not exist, a new variable need to be created.
+ //
+
+ //
+ // Get size, allocate buffer and get data.
+ //
+ GetVariableSizeAndDataFromHiiPcd (VariableGuid, VariableName, &Size, NULL);
+ Buffer = AllocateZeroPool (Size);
+ ASSERT (Buffer != NULL);
+ GetVariableSizeAndDataFromHiiPcd (VariableGuid, VariableName, &Size, Buffer);
+
+ //
+ // Update buffer.
+ //
+ CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
+
+ if (SetAttributes == 0) {
+ SetAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
+ }
+
+ Status = gRT->SetVariable (
+ VariableName,
+ VariableGuid,
+ SetAttributes,
+ Size,
+ Buffer
+ );
+
+ FreePool (Buffer);
+ return Status;
+ }
+
+ //
+ // If we drop to here, the value is failed to be written in to variable area.
+ //
+ return Status;
+}
+
+/**
+ Get Token Number according to dynamic-ex PCD's {token space guid:token number}
+
+ A dynamic-ex type PCD, developer must provide pair of token space guid: token number
+ in DEC file. PCD database maintain a mapping table that translate pair of {token
+ space guid: token number} to Token Number.
+
+ @param Guid Token space guid for dynamic-ex PCD entry.
+ @param ExTokenNumber Dynamic-ex PCD token number.
+
+ @return Token Number for dynamic-ex PCD.
+
+**/
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINT32 ExTokenNumber
+ )
+{
+ UINT32 Index;
+ DYNAMICEX_MAPPING *ExMap;
+ EFI_GUID *GuidTable;
+ EFI_GUID *MatchGuid;
+ UINTN MatchGuidIdx;
+
+ if (!mPeiDatabaseEmpty) {
+ ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset);
+ GuidTable = (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset);
+
+ MatchGuid = ScanGuid (GuidTable, mPeiGuidTableSize, Guid);
+
+ if (MatchGuid != NULL) {
+
+ MatchGuidIdx = MatchGuid - GuidTable;
+
+ for (Index = 0; Index < mPcdDatabase.PeiDb->ExTokenCount; Index++) {
+ if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&
+ (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {
+ return ExMap[Index].TokenNumber;
+ }
+ }
+ }
+ }
+
+ ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset);
+ GuidTable = (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset);
+
+ MatchGuid = ScanGuid (GuidTable, mDxeGuidTableSize, Guid);
+ //
+ // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
+ // error in the BUILD system.
+ //
+ ASSERT (MatchGuid != NULL);
+
+ MatchGuidIdx = MatchGuid - GuidTable;
+
+ for (Index = 0; Index < mPcdDatabase.DxeDb->ExTokenCount; Index++) {
+ if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&
+ (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {
+ return ExMap[Index].TokenNumber;
+ }
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+}
+
+/**
+ Get SKU ID table from PCD database.
+
+ @param LocalTokenNumberTableIdx Index of local token number in token number table.
+ @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
+ If FALSE, the pcd entry is initialized in DXE phase.
+ @return Pointer to SKU ID array table
+
+**/
+SKU_ID *
+GetSkuIdArray (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN BOOLEAN IsPeiDb
+ )
+{
+ SKU_HEAD *SkuHead;
+ UINTN LocalTokenNumber;
+ UINT8 *Database;
+
+ if (IsPeiDb) {
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+ Database = (UINT8 *) mPcdDatabase.PeiDb;
+ } else {
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+ Database = (UINT8 *) mPcdDatabase.DxeDb;
+ }
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
+
+ SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+
+ return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);
+
+}
+
+/**
+ Wrapper function of getting index of PCD entry in size table.
+
+ @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
+ @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
+ If FALSE, the pcd entry is initialized in DXE phase.
+
+ @return index of PCD entry in size table.
+**/
+UINTN
+GetSizeTableIndex (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN BOOLEAN IsPeiDb
+ )
+{
+ UINT32 *LocalTokenNumberTable;
+ UINTN LocalTokenNumber;
+ UINTN Index;
+ UINTN SizeTableIdx;
+ SKU_ID *SkuIdTable;
+
+ if (IsPeiDb) {
+ LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);
+ } else {
+ LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
+ }
+
+ SizeTableIdx = 0;
+
+ for (Index = 0; Index < LocalTokenNumberTableIdx; Index ++) {
+ LocalTokenNumber = LocalTokenNumberTable[Index];
+
+ if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
+ //
+ // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+ // PCD entry.
+ //
+ if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+ //
+ // We have only two entry for VPD enabled PCD entry:
+ // 1) MAX Size.
+ // 2) Current Size
+ // Current size is equal to MAX size.
+ //
+ SizeTableIdx += 2;
+ } else {
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
+ //
+ // We have only two entry for Non-Sku enabled PCD entry:
+ // 1) MAX SIZE
+ // 2) Current Size
+ //
+ SizeTableIdx += 2;
+ } else {
+ //
+ // We have these entry for SKU enabled PCD entry
+ // 1) MAX SIZE
+ // 2) Current Size for each SKU_ID (It is equal to MaxSku).
+ //
+ SkuIdTable = GetSkuIdArray (Index, IsPeiDb);
+ SizeTableIdx += (UINTN)*SkuIdTable + 1;
+ }
+ }
+ }
+
+ }
+
+ return SizeTableIdx;
+}
+
+/**
+ Get size of POINTER type PCD value.
+
+ @param LocalTokenNumberTableIdx Index of local token number in local token number table.
+ @param MaxSize Maxmium size of POINTER type PCD value.
+
+ @return size of POINTER type PCD value.
+
+**/
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize
+ )
+{
+ INTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+ SIZE_INFO *SizeTable;
+ UINTN Index;
+ BOOLEAN IsPeiDb;
+ UINT32 *LocalTokenNumberTable;
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);
+
+
+ if (IsPeiDb) {
+ LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);
+ SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);
+ } else {
+ LocalTokenNumberTableIdx -= mPeiLocalTokenCount;
+ LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
+ SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);
+ }
+
+ LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
+
+ ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+ SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
+
+ *MaxSize = SizeTable[SizeTableIdx];
+ //
+ // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+ // PCD entry.
+ //
+ if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+ //
+ // We have only two entry for VPD enabled PCD entry:
+ // 1) MAX Size.
+ // 2) Current Size
+ // We consider current size is equal to MAX size.
+ //
+ return *MaxSize;
+ } else {
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
+ //
+ // We have only two entry for Non-Sku enabled PCD entry:
+ // 1) MAX SIZE
+ // 2) Current Size
+ //
+ return SizeTable[SizeTableIdx + 1];
+ } else {
+ //
+ // We have these entry for SKU enabled PCD entry
+ // 1) MAX SIZE
+ // 2) Current Size for each SKU_ID (It is equal to MaxSku).
+ //
+ SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (SkuIdTable[1 + Index] == mPcdDatabase.DxeDb->SystemSkuId) {
+ return SizeTable[SizeTableIdx + 1 + Index];
+ }
+ }
+ return SizeTable[SizeTableIdx + 1];
+ }
+ }
+}
+
+/**
+ Set size of POINTER type PCD value. The size should not exceed the maximum size
+ of this PCD value.
+
+ @param LocalTokenNumberTableIdx Index of local token number in local token number table.
+ @param CurrentSize Size of POINTER type PCD value.
+
+ @retval TRUE Success to set size of PCD value.
+ @retval FALSE Fail to set size of PCD value.
+**/
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize
+ )
+{
+ INTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+ SIZE_INFO *SizeTable;
+ UINTN Index;
+ UINTN MaxSize;
+ BOOLEAN IsPeiDb;
+ UINT32 *LocalTokenNumberTable;
+
+ //
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ //
+ IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < mPeiLocalTokenCount + 1);
+
+ if (IsPeiDb) {
+ LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset);
+ SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->SizeTableOffset);
+ } else {
+ LocalTokenNumberTableIdx -= mPeiLocalTokenCount;
+ LocalTokenNumberTable = (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
+ SizeTable = (SIZE_INFO *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SizeTableOffset);
+ }
+
+ LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];
+
+ ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+ SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);
+
+ MaxSize = SizeTable[SizeTableIdx];
+ //
+ // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+ // PCD entry.
+ //
+ if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+ //
+ // We shouldn't come here as we don't support SET for VPD
+ //
+ ASSERT (FALSE);
+ return FALSE;
+ } else {
+ if ((*CurrentSize > MaxSize) ||
+ (*CurrentSize == MAX_ADDRESS)) {
+ *CurrentSize = MaxSize;
+ return FALSE;
+ }
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
+ //
+ // We have only two entry for Non-Sku enabled PCD entry:
+ // 1) MAX SIZE
+ // 2) Current Size
+ //
+ SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ } else {
+ //
+ // We have these entry for SKU enabled PCD entry
+ // 1) MAX SIZE
+ // 2) Current Size for each SKU_ID (It is equal to MaxSku).
+ //
+ SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (SkuIdTable[1 + Index] == mPcdDatabase.DxeDb->SystemSkuId) {
+ SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ }
+ }
+ SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ }
+ }
+}
+
+/**
+ VariableLock DynamicHiiPcd.
+
+ @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
+ If FALSE, the pcd entry is initialized in DXE phase.
+ @param[in] VariableLock Pointer to VariableLockProtocol.
+
+**/
+VOID
+VariableLockDynamicHiiPcd (
+ IN BOOLEAN IsPeiDb,
+ IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock
+ )
+{
+ EFI_STATUS Status;
+ PCD_DATABASE_INIT *Database;
+ UINT32 LocalTokenCount;
+ UINTN TokenNumber;
+ UINT32 LocalTokenNumber;
+ UINTN Offset;
+ EFI_GUID *GuidTable;
+ UINT8 *StringTable;
+ VARIABLE_HEAD *VariableHead;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+
+ Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;
+ LocalTokenCount = IsPeiDb ? mPeiLocalTokenCount: mDxeLocalTokenCount;
+
+ //
+ // Go through PCD database to find out DynamicHii PCDs.
+ //
+ for (TokenNumber = 1; TokenNumber <= LocalTokenCount; TokenNumber++) {
+ if (IsPeiDb) {
+ LocalTokenNumber = GetLocalTokenNumber (TRUE, TokenNumber);
+ } else {
+ LocalTokenNumber = GetLocalTokenNumber (FALSE, TokenNumber + mPeiLocalTokenCount);
+ }
+ if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+ VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);
+ //
+ // Why not to set property by VarCheckProtocol with Attributes and Property directly here?
+ // It is because that set property by VarCheckProtocol will indicate the variable to
+ // be a system variable, but the unknown max size of the variable is dangerous to
+ // the system variable region.
+ //
+ if ((VariableHead->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0) {
+ //
+ // DynamicHii PCD with RO property set in *.dsc.
+ //
+ StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);
+ GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);
+ Guid = GuidTable + VariableHead->GuidTableIndex;
+ Name = (UINT16*) (StringTable + VariableHead->StringIndex);
+ Status = VariableLock->RequestToLock (VariableLock, Name, Guid);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+}
+
+/**
+ VariableLockProtocol callback
+ to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+VariableLockCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
+
+ Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
+ if (!EFI_ERROR (Status)) {
+ VariableLockDynamicHiiPcd (TRUE, VariableLock);
+ VariableLockDynamicHiiPcd (FALSE, VariableLock);
+ }
+}
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Dxe/Service.h b/Core/MdeModulePkg/Universal/PCD/Dxe/Service.h
new file mode 100644
index 0000000000..0257a3487c
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Dxe/Service.h
@@ -0,0 +1,1202 @@
+/** @file
+Private functions used by PCD DXE driver.
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCD_DXE_SERVICE_H_
+#define _PCD_DXE_SERVICE_H_
+
+#include <PiDxe.h>
+#include <Guid/PcdDataBaseHobGuid.h>
+#include <Guid/PcdDataBaseSignatureGuid.h>
+#include <Protocol/Pcd.h>
+#include <Protocol/PiPcd.h>
+#include <Protocol/PcdInfo.h>
+#include <Protocol/PiPcdInfo.h>
+#include <Protocol/VarCheck.h>
+#include <Protocol/VariableLock.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+//
+// Please make sure the PCD Serivce DXE Version is consistent with
+// the version of the generated DXE PCD Database by build tool.
+//
+#define PCD_SERVICE_DXE_VERSION 6
+
+//
+// PCD_DXE_SERVICE_DRIVER_VERSION is defined in Autogen.h.
+//
+#if (PCD_SERVICE_DXE_VERSION != PCD_DXE_SERVICE_DRIVER_VERSION)
+ #error "Please make sure the version of PCD DXE Service and the generated PCD DXE Database match."
+#endif
+
+/**
+ Retrieve additional information associated with a PCD token in the default token space.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+DxeGetPcdInfoGetInfo (
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ );
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+DxeGetPcdInfoGetInfoEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ );
+
+/**
+ Retrieve the currently set SKU Id.
+
+ @return The currently set SKU Id. If the platform has not set at a SKU Id, then the
+ default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
+ Id is returned.
+**/
+UINTN
+EFIAPI
+DxeGetPcdInfoGetSku (
+ VOID
+ );
+
+//
+// Protocol Interface function declaration.
+//
+/**
+ Sets the SKU value for subsequent calls to set or get PCD token values.
+
+ SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
+ SetSku() is normally called only once by the system.
+
+ For each item (token), the database can hold a single value that applies to all SKUs,
+ or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
+ SKU-specific values are called SKU enabled.
+
+ The SKU Id of zero is reserved as a default. The valid SkuId range is 1 to 255.
+ For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
+ single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
+ last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
+ the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
+ set for that Id, the results are unpredictable.
+
+ @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and
+ set values associated with a PCD token.
+
+**/
+VOID
+EFIAPI
+DxePcdSetSku (
+ IN UINTN SkuId
+ );
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the current byte-sized value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT8 value.
+
+**/
+UINT8
+EFIAPI
+DxePcdGet8 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the current 16-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT16 value.
+
+**/
+UINT16
+EFIAPI
+DxePcdGet16 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the current 32-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT32 value.
+
+**/
+UINT32
+EFIAPI
+DxePcdGet32 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the current 64-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT64 value.
+
+**/
+UINT64
+EFIAPI
+DxePcdGet64 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrieved.
+
+**/
+VOID *
+EFIAPI
+DxePcdGetPtr (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves a Boolean value for a given PCD token.
+
+ Retrieves the current boolean value for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The Boolean value.
+
+**/
+BOOLEAN
+EFIAPI
+DxePcdGetBool (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+DxePcdGetSize (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the 8-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 8-bit value for the PCD token.
+
+**/
+UINT8
+EFIAPI
+DxePcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the 16-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 16-bit value for the PCD token.
+
+**/
+UINT16
+EFIAPI
+DxePcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the 32-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 32-bit value for the PCD token.
+
+**/
+UINT32
+EFIAPI
+DxePcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the 64-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 64-bit value for the PCD token.
+
+**/
+UINT64
+EFIAPI
+DxePcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrieved.
+
+**/
+VOID *
+EFIAPI
+DxePcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an Boolean value for a given PCD token.
+
+ Retrieves the Boolean value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size Boolean value for the PCD token.
+
+**/
+BOOLEAN
+EFIAPI
+DxePcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+DxePcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ );
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ );
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ );
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ );
+
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetPtr (
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ );
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ );
+
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ );
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ );
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ );
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ );
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ );
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ );
+
+/**
+ Specifies a function to be called anytime the value of a designated token is changed.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ );
+
+/**
+ Cancels a previously set callback function for a particular PCD token number.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ );
+
+/**
+ Retrieves the next valid token number in a given namespace.
+
+ This is useful since the PCD infrastructure contains a sparse list of token numbers,
+ and one cannot a priori know what token numbers are valid in the database.
+
+ If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
+ If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
+ If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
+ If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
+ The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
+ If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
+ If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+ If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to retrieve the next token.
+ This is an optional parameter that may be NULL. If this parameter is NULL, then a request is
+ being made to retrieve tokens from the default token space.
+ @param[in, out] TokenNumber
+ A pointer to the PCD token number to use to find the subsequent token number.
+
+ @retval EFI_SUCCESS The PCD service retrieved the next valid token number. Or the input token number
+ is already the last valid token number in the PCD database.
+ In the later case, *TokenNumber is updated with the value of 0.
+ @retval EFI_NOT_FOUND If this input token number and token namespace does not exist on the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ );
+
+/**
+ Get next token space in PCD database according to given token space guid.
+
+ @param Guid Given token space guid. If NULL, then Guid will be set to
+ the first PCD token space in PCD database, If not NULL, then
+ Guid will be set to next PCD token space.
+
+ @retval EFI_NOT_FOUND If PCD database has no token space table or can not find given
+ token space in PCD database.
+ @retval EFI_SUCCESS Success to get next token space guid.
+**/
+EFI_STATUS
+EFIAPI
+DxePcdGetNextTokenSpace (
+ IN OUT CONST EFI_GUID **Guid
+ );
+
+typedef struct {
+ LIST_ENTRY Node;
+ PCD_PROTOCOL_CALLBACK CallbackFn;
+} CALLBACK_FN_ENTRY;
+
+#define CR_FNENTRY_FROM_LISTNODE(Record, Type, Field) BASE_CR(Record, Type, Field)
+
+//
+// Internal Functions
+//
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+DxeGetPcdInfo (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ );
+
+/**
+ Wrapper function for setting non-pointer type value for a PCD entry.
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+
+ @return status of SetWorker.
+
+**/
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ );
+
+/**
+ Set value for an PCD entry
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+ @param PtrType If TRUE, the type of PCD entry's value is Pointer.
+ If False, the type of PCD entry's value is not Pointer.
+
+ @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
+ @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
+ @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
+ @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
+ range of UINT8, UINT16, UINT32, UINT64
+ @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
+**/
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ );
+
+/**
+ Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
+
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data Value want to be set.
+ @param SetSize The size of value.
+
+ @return status of ExSetWorker().
+
+**/
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN SetSize
+ );
+
+/**
+ Set value for a dynamic PCD entry.
+
+ This routine find the local token number according to dynamic-ex PCD's token
+ space guid and token number firstly, and invoke callback function if this PCD
+ entry registered callback function. Finally, invoken general SetWorker to set
+ PCD value.
+
+ @param ExTokenNumber Dynamic-ex PCD token number.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data PCD value want to be set
+ @param SetSize Size of value.
+ @param PtrType If TRUE, this PCD entry is pointer type.
+ If FALSE, this PCD entry is not pointer type.
+
+ @return status of SetWorker().
+
+**/
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ );
+
+/**
+ Get the PCD entry pointer in PCD database.
+
+ This routine will visit PCD database to find the PCD entry according to given
+ token number. The given token number is autogened by build tools and it will be
+ translated to local token number. Local token number contains PCD's type and
+ offset of PCD entry in PCD database.
+
+ @param TokenNumber Token's number, it is autogened by build tools
+ @param GetSize The size of token's value
+
+ @return PCD entry pointer in PCD database
+
+**/
+VOID *
+GetWorker (
+ IN UINTN TokenNumber,
+ IN UINTN GetSize
+ );
+
+/**
+ Wrapper function for get PCD value for dynamic-ex PCD.
+
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+ @param GetSize The size of dynamic-ex PCD value.
+
+ @return PCD entry in PCD database.
+
+**/
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ );
+
+/**
+ Find the local token number according to system SKU ID.
+
+ @param LocalTokenNumber PCD token number
+ @param Size The size of PCD entry.
+ @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.
+ If False, the PCD entry is initialized in DXE phase.
+
+ @return Token number according to system SKU ID.
+
+**/
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size,
+ BOOLEAN IsPeiDb
+ );
+
+/**
+ Get Variable which contains HII type PCD entry.
+
+ @param VariableGuid Variable's guid
+ @param VariableName Variable's unicode name string
+ @param VariableData Variable's data pointer,
+ @param VariableSize Variable's size.
+
+ @return the status of gRT->GetVariable
+**/
+EFI_STATUS
+GetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT UINT8 **VariableData,
+ OUT UINTN *VariableSize
+ );
+
+/**
+ Set value for HII-type PCD.
+
+ A HII-type PCD's value is stored in a variable. Setting/Getting the value of
+ HII-type PCD is to visit this variable.
+
+ @param VariableGuid Guid of variable which stored value of a HII-type PCD.
+ @param VariableName Unicode name of variable which stored value of a HII-type PCD.
+ @param SetAttributes Attributes bitmask to set for the variable.
+ @param Data Value want to be set.
+ @param DataSize Size of value
+ @param Offset Value offset of HII-type PCD in variable.
+
+ @return status of GetVariable()/SetVariable().
+
+**/
+EFI_STATUS
+SetHiiVariable (
+ IN EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ IN UINT32 SetAttributes,
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ IN UINTN Offset
+ );
+
+/**
+ Register the callback function for a PCD entry.
+
+ This routine will register a callback function to a PCD entry by given token number
+ and token space guid.
+
+ @param TokenNumber PCD token's number, it is autogened by build tools.
+ @param Guid PCD token space's guid,
+ if not NULL, this PCD is dynamicEx type PCD.
+ @param CallBackFunction Callback function pointer
+
+ @return EFI_SUCCESS Always success for registering callback function.
+
+**/
+EFI_STATUS
+DxeRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ );
+
+/**
+ UnRegister the callback function for a PCD entry.
+
+ This routine will unregister a callback function to a PCD entry by given token number
+ and token space guid.
+
+ @param TokenNumber PCD token's number, it is autogened by build tools.
+ @param Guid PCD token space's guid.
+ if not NULL, this PCD is dynamicEx type PCD.
+ @param CallBackFunction Callback function pointer
+
+ @retval EFI_SUCCESS Callback function is success to be unregister.
+ @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.
+**/
+EFI_STATUS
+DxeUnRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PROTOCOL_CALLBACK CallBackFunction
+ );
+
+/**
+ Initialize the PCD database in DXE phase.
+
+ PCD database in DXE phase also contains PCD database in PEI phase which is copied
+ from GUID Hob.
+
+**/
+VOID
+BuildPcdDxeDataBase (
+ VOID
+ );
+
+/**
+ Get Token Number according to dynamic-ex PCD's {token space guid:token number}
+
+ A dynamic-ex type PCD, developer must provide pair of token space guid: token number
+ in DEC file. PCD database maintain a mapping table that translate pair of {token
+ space guid: token number} to Token Number.
+
+ @param Guid Token space guid for dynamic-ex PCD entry.
+ @param ExTokenNumber Dynamic-ex PCD token number.
+
+ @return Token Number for dynamic-ex PCD.
+
+**/
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINT32 ExTokenNumber
+ );
+
+/**
+ Get next token number in given token space.
+
+ This routine is used for dynamicEx type PCD. It will firstly scan token space
+ table to get token space according to given token space guid. Then scan given
+ token number in found token space, if found, then return next token number in
+ this token space.
+
+ @param Guid Token space guid. Next token number will be scaned in
+ this token space.
+ @param TokenNumber Token number.
+ If PCD_INVALID_TOKEN_NUMBER, return first token number in
+ token space table.
+ If not PCD_INVALID_TOKEN_NUMBER, return next token number
+ in token space table.
+ @param GuidTable Token space guid table. It will be used for scan token space
+ by given token space guid.
+ @param SizeOfGuidTable The size of guid table.
+ @param ExMapTable DynamicEx token number mapping table.
+ @param SizeOfExMapTable The size of dynamicEx token number mapping table.
+
+ @retval EFI_NOT_FOUND Can not given token space or token number.
+ @retval EFI_SUCCESS Success to get next token number.
+
+**/
+EFI_STATUS
+ExGetNextTokeNumber (
+ IN CONST EFI_GUID *Guid,
+ IN OUT UINTN *TokenNumber,
+ IN EFI_GUID *GuidTable,
+ IN UINTN SizeOfGuidTable,
+ IN DYNAMICEX_MAPPING *ExMapTable,
+ IN UINTN SizeOfExMapTable
+ );
+
+/**
+ Get size of POINTER type PCD value.
+
+ @param LocalTokenNumberTableIdx Index of local token number in local token number table.
+ @param MaxSize Maximum size of POINTER type PCD value.
+
+ @return size of POINTER type PCD value.
+
+**/
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize
+ );
+
+/**
+ Set size of POINTER type PCD value. The size should not exceed the maximum size
+ of this PCD value.
+
+ @param LocalTokenNumberTableIdx Index of local token number in local token number table.
+ @param CurrentSize Size of POINTER type PCD value.
+
+ @retval TRUE Success to set size of PCD value.
+ @retval FALSE Fail to set size of PCD value.
+**/
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize
+ );
+
+/**
+ VariableLockProtocol callback
+ to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+VariableLockCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+extern PCD_DATABASE mPcdDatabase;
+
+extern UINT32 mPcdTotalTokenCount;
+extern UINT32 mPeiLocalTokenCount;
+extern UINT32 mDxeLocalTokenCount;
+extern UINT32 mPeiNexTokenCount;
+extern UINT32 mDxeNexTokenCount;
+extern UINT32 mPeiExMapppingTableSize;
+extern UINT32 mDxeExMapppingTableSize;
+extern UINT32 mPeiGuidTableSize;
+extern UINT32 mDxeGuidTableSize;
+
+extern BOOLEAN mPeiExMapTableEmpty;
+extern BOOLEAN mDxeExMapTableEmpty;
+extern BOOLEAN mPeiDatabaseEmpty;
+
+extern EFI_GUID **TmpTokenSpaceBuffer;
+extern UINTN TmpTokenSpaceBufferCount;
+
+extern EFI_LOCK mPcdDatabaseLock;
+
+#endif
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Pei/Pcd.c b/Core/MdeModulePkg/Universal/PCD/Pei/Pcd.c
new file mode 100644
index 0000000000..a3f7337cec
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Pei/Pcd.c
@@ -0,0 +1,1433 @@
+/** @file
+ All Pcd Ppi services are implemented here.
+
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Service.h"
+
+///
+/// Instance of PCD_PPI protocol is EDKII native implementation.
+/// This protocol instance support dynamic and dynamicEx type PCDs.
+///
+PCD_PPI mPcdPpiInstance = {
+ PeiPcdSetSku,
+
+ PeiPcdGet8,
+ PeiPcdGet16,
+ PeiPcdGet32,
+ PeiPcdGet64,
+ PeiPcdGetPtr,
+ PeiPcdGetBool,
+ PeiPcdGetSize,
+
+ PeiPcdGet8Ex,
+ PeiPcdGet16Ex,
+ PeiPcdGet32Ex,
+ PeiPcdGet64Ex,
+ PeiPcdGetPtrEx,
+ PeiPcdGetBoolEx,
+ PeiPcdGetSizeEx,
+
+ PeiPcdSet8,
+ PeiPcdSet16,
+ PeiPcdSet32,
+ PeiPcdSet64,
+ PeiPcdSetPtr,
+ PeiPcdSetBool,
+
+ PeiPcdSet8Ex,
+ PeiPcdSet16Ex,
+ PeiPcdSet32Ex,
+ PeiPcdSet64Ex,
+ PeiPcdSetPtrEx,
+ PeiPcdSetBoolEx,
+
+ PeiRegisterCallBackOnSet,
+ PcdUnRegisterCallBackOnSet,
+ PeiPcdGetNextToken,
+ PeiPcdGetNextTokenSpace
+};
+
+///
+/// Instance of EFI_PEI_PCD_PPI which is defined in PI 1.2 Vol 3.
+/// This PPI instance only support dyanmicEx type PCD.
+///
+EFI_PEI_PCD_PPI mEfiPcdPpiInstance = {
+ PeiPcdSetSku,
+
+ PeiPcdGet8Ex,
+ PeiPcdGet16Ex,
+ PeiPcdGet32Ex,
+ PeiPcdGet64Ex,
+ PeiPcdGetPtrEx,
+ PeiPcdGetBoolEx,
+ PeiPcdGetSizeEx,
+ PeiPcdSet8Ex,
+ PeiPcdSet16Ex,
+ PeiPcdSet32Ex,
+ PeiPcdSet64Ex,
+ PeiPcdSetPtrEx,
+ PeiPcdSetBoolEx,
+ (EFI_PEI_PCD_PPI_CALLBACK_ON_SET) PeiRegisterCallBackOnSet,
+ (EFI_PEI_PCD_PPI_CANCEL_CALLBACK) PcdUnRegisterCallBackOnSet,
+ PeiPcdGetNextToken,
+ PeiPcdGetNextTokenSpace
+};
+
+///
+/// Instance of GET_PCD_INFO_PPI protocol is EDKII native implementation.
+/// This protocol instance support dynamic and dynamicEx type PCDs.
+///
+GET_PCD_INFO_PPI mGetPcdInfoInstance = {
+ PeiGetPcdInfoGetInfo,
+ PeiGetPcdInfoGetInfoEx,
+ PeiGetPcdInfoGetSku
+};
+
+///
+/// Instance of EFI_GET_PCD_INFO_PPI which is defined in PI 1.2.1 Vol 3.
+/// This PPI instance only support dyanmicEx type PCD.
+///
+EFI_GET_PCD_INFO_PPI mEfiGetPcdInfoInstance = {
+ PeiGetPcdInfoGetInfoEx,
+ PeiGetPcdInfoGetSku
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gPcdPpiGuid,
+ &mPcdPpiInstance
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiPcdPpiGuid,
+ &mEfiPcdPpiInstance
+ }
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList2[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gGetPcdInfoPpiGuid,
+ &mGetPcdInfoInstance
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiGetPcdInfoPpiGuid,
+ &mEfiGetPcdInfoInstance
+ }
+};
+
+/**
+ Main entry for PCD PEIM driver.
+
+ This routine initialize the PCD database for PEI phase and install PCD_PPI/EFI_PEI_PCD_PPI.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return Status of install PCD_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+PcdPeimInit (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ BuildPcdDatabase (FileHandle);
+
+ //
+ // Install PCD_PPI and EFI_PEI_PCD_PPI.
+ //
+ Status = PeiServicesInstallPpi (&mPpiList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install GET_PCD_INFO_PPI and EFI_GET_PCD_INFO_PPI.
+ //
+ Status = PeiServicesInstallPpi (&mPpiList2[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Retrieve additional information associated with a PCD token in the default token space.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetPcdInfoGetInfo (
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ return PeiGetPcdInfo (NULL, TokenNumber, PcdInfo);
+}
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetPcdInfoGetInfoEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ return PeiGetPcdInfo (Guid, TokenNumber, PcdInfo);
+}
+
+/**
+ Retrieve the currently set SKU Id.
+
+ @return The currently set SKU Id. If the platform has not set at a SKU Id, then the
+ default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
+ Id is returned.
+**/
+UINTN
+EFIAPI
+PeiGetPcdInfoGetSku (
+ VOID
+ )
+{
+ return (UINTN) GetPcdDatabase()->SystemSkuId;
+}
+
+/**
+ Sets the SKU value for subsequent calls to set or get PCD token values.
+
+ SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
+ SetSku() is normally called only once by the system.
+
+ For each item (token), the database can hold a single value that applies to all SKUs,
+ or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
+ SKU-specific values are called SKU enabled.
+
+ The SKU Id of zero is reserved as a default.
+ For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
+ single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
+ last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
+ the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
+ set for that Id, the results are unpredictable.
+
+ @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and
+ set values associated with a PCD token.
+
+**/
+VOID
+EFIAPI
+PeiPcdSetSku (
+ IN UINTN SkuId
+ )
+{
+ PEI_PCD_DATABASE *PeiPcdDb;
+ SKU_ID *SkuIdTable;
+ UINTN Index;
+
+ PeiPcdDb = GetPcdDatabase();
+
+ if (SkuId == PeiPcdDb->SystemSkuId) {
+ //
+ // The input SKU Id is equal to current SKU Id, return directly.
+ //
+ return;
+ }
+
+ if (PeiPcdDb->SystemSkuId != (SKU_ID) 0) {
+ DEBUG ((DEBUG_ERROR, "PcdPei - The SKU Id could be changed only once."));
+ DEBUG ((
+ DEBUG_ERROR,
+ "PcdPei - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",
+ PeiPcdDb->SystemSkuId,
+ (SKU_ID) SkuId
+ ));
+ ASSERT (FALSE);
+ return;
+ }
+
+ SkuIdTable = (SKU_ID *) ((UINT8 *) PeiPcdDb + PeiPcdDb->SkuIdTableOffset);
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (SkuId == SkuIdTable[Index + 1]) {
+ DEBUG ((EFI_D_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId));
+ PeiPcdDb->SystemSkuId = (SKU_ID) SkuId;
+ return;
+ }
+ }
+
+ //
+ // Invalid input SkuId, the default SKU Id will be still used for the system.
+ //
+ DEBUG ((EFI_D_INFO, "PcdPei - Invalid input SkuId, the default SKU Id will be still used.\n"));
+ return;
+}
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the current byte-sized value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT8 value.
+
+**/
+UINT8
+EFIAPI
+PeiPcdGet8 (
+ IN UINTN TokenNumber
+ )
+{
+ return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
+}
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the current 16-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT16 value.
+
+**/
+UINT16
+EFIAPI
+PeiPcdGet16 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
+}
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the current 32-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT32 value.
+
+**/
+UINT32
+EFIAPI
+PeiPcdGet32 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
+}
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the current 64-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT64 value.
+
+**/
+UINT64
+EFIAPI
+PeiPcdGet64 (
+ IN UINTN TokenNumber
+ )
+{
+ return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
+}
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrieved.
+
+**/
+VOID *
+EFIAPI
+PeiPcdGetPtr (
+ IN UINTN TokenNumber
+ )
+{
+ return GetWorker (TokenNumber, 0);
+}
+
+/**
+ Retrieves a Boolean value for a given PCD token.
+
+ Retrieves the current boolean value for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The Boolean value.
+
+**/
+BOOLEAN
+EFIAPI
+PeiPcdGetBool (
+ IN UINTN TokenNumber
+ )
+{
+ return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+PeiPcdGetSize (
+ IN UINTN TokenNumber
+ )
+{
+ PEI_PCD_DATABASE *PeiPcdDb;
+ UINTN Size;
+ UINTN MaxSize;
+ UINT32 LocalTokenCount;
+
+ PeiPcdDb = GetPcdDatabase ();
+ LocalTokenCount = PeiPcdDb->LocalTokenCount;
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));
+
+ Size = (*((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber) & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
+
+ if (Size == 0) {
+ //
+ // For pointer type, we need to scan the SIZE_TABLE to get the current size.
+ //
+ return GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
+ } else {
+ return Size;
+ }
+
+}
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the 8-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 8-bit value for the PCD token.
+
+**/
+UINT8
+EFIAPI
+PeiPcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
+}
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the 16-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 16-bit value for the PCD token.
+
+**/
+UINT16
+EFIAPI
+PeiPcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
+}
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the 32-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 32-bit value for the PCD token.
+
+**/
+UINT32
+EFIAPI
+PeiPcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
+}
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the 64-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size 64-bit value for the PCD token.
+
+**/
+UINT64
+EFIAPI
+PeiPcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
+}
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrieved.
+
+**/
+VOID *
+EFIAPI
+PeiPcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return ExGetWorker (Guid, ExTokenNumber, 0);
+}
+
+/**
+ Retrieves an Boolean value for a given PCD token.
+
+ Retrieves the Boolean value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size Boolean value for the PCD token.
+
+**/
+BOOLEAN
+EFIAPI
+PeiPcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] ExTokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+PeiPcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ return PeiPcdGetSize (GetExPcdTokenNumber (Guid, ExTokenNumber));
+}
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtr (
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ )
+{
+ return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
+}
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ )
+{
+ return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT8 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT16 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT32 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINT64 Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Value The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Value
+ )
+{
+ return ExSetWorker (ExTokenNumber, Guid, Value, SizeOfBuffer, TRUE);
+}
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param [in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param [in] ExTokenNumber The PCD token number.
+ @param [in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN BOOLEAN Value
+ )
+{
+ return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+ Specifies a function to be called anytime the value of a designated token is changed.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN ExTokenNumber,
+ IN PCD_PPI_CALLBACK CallBackFunction
+ )
+{
+ if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (CallBackFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, TRUE);
+}
+
+/**
+ Cancels a previously set callback function for a particular PCD token number.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] ExTokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PcdUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN ExTokenNumber,
+ IN PCD_PPI_CALLBACK CallBackFunction
+ )
+{
+ if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (CallBackFunction == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, FALSE);
+}
+
+/**
+ Retrieves the next valid token number in a given namespace.
+
+ This is useful since the PCD infrastructure contains a sparse list of token numbers,
+ and one cannot a priori know what token numbers are valid in the database.
+
+ If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
+ If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
+ If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
+ If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
+ The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
+ If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
+ If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+ If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ This is an optional parameter that may be NULL. If this parameter is NULL, then a request
+ is being made to retrieve tokens from the default token space.
+ @param[in, out] TokenNumber A pointer to the PCD token number to use to find the subsequent token number.
+
+ @retval EFI_SUCCESS The PCD service has retrieved the next valid token number.
+ @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ )
+{
+ UINTN GuidTableIdx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ EFI_GUID *MatchGuid;
+ EFI_GUID *GuidTable;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+ BOOLEAN Found;
+ BOOLEAN PeiExMapTableEmpty;
+ UINTN PeiNexTokenNumber;
+
+ if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PeiPcdDb = GetPcdDatabase ();
+ PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;
+ GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
+
+ if (PeiPcdDb->ExTokenCount == 0) {
+ PeiExMapTableEmpty = TRUE;
+ } else {
+ PeiExMapTableEmpty = FALSE;
+ }
+ if (Guid == NULL) {
+ if (*TokenNumber > PeiNexTokenNumber) {
+ return EFI_NOT_FOUND;
+ }
+ (*TokenNumber)++;
+ if (*TokenNumber > PeiNexTokenNumber) {
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+ } else {
+ if (PeiExMapTableEmpty) {
+ return EFI_NOT_FOUND;
+ }
+
+ MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(EFI_GUID), Guid);
+
+ if (MatchGuid == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ GuidTableIdx = MatchGuid - GuidTable;
+
+ ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
+
+ Found = FALSE;
+ //
+ // Locate the GUID in ExMapTable first.
+ //
+ for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
+ if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (Found) {
+ //
+ // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
+ // token number in found token space.
+ //
+ if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ *TokenNumber = ExMapTable[Index].ExTokenNumber;
+ return EFI_SUCCESS;
+ }
+
+ for ( ; Index < PeiPcdDb->ExTokenCount; Index++) {
+ if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {
+ break;
+ }
+ }
+
+ while (Index < PeiPcdDb->ExTokenCount) {
+ Index++;
+ if (Index == PeiPcdDb->ExTokenCount) {
+ //
+ // Exceed the length of ExMap Table
+ //
+ *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+ return EFI_NOT_FOUND;
+ } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ //
+ // Found the next match
+ //
+ *TokenNumber = ExMapTable[Index].ExTokenNumber;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Retrieves the next valid PCD token namespace for a given namespace.
+
+ Gets the next valid token namespace for a given namespace. This is useful to traverse the valid
+ token namespaces on a platform.
+
+ @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token
+ namespace from which the search will start. On output, it designates the next valid
+ token namespace on the platform. If *Guid is NULL, then the GUID of the first token
+ space of the current platform is returned. If the search cannot locate the next valid
+ token namespace, an error is returned and the value of *Guid is undefined.
+
+ @retval EFI_SUCCESS The PCD service retrieved the value requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextTokenSpace (
+ IN OUT CONST EFI_GUID **Guid
+ )
+{
+ UINTN GuidTableIdx;
+ EFI_GUID *MatchGuid;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+ UINTN Index2;
+ BOOLEAN Found;
+ BOOLEAN PeiExMapTableEmpty;
+ EFI_GUID *GuidTable;
+
+ if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ASSERT (Guid != NULL);
+
+ PeiPcdDb = GetPcdDatabase ();
+
+ if (PeiPcdDb->ExTokenCount == 0) {
+ PeiExMapTableEmpty = TRUE;
+ } else {
+ PeiExMapTableEmpty = FALSE;
+ }
+
+ if (PeiExMapTableEmpty) {
+ return EFI_NOT_FOUND;
+ }
+
+ ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
+ GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
+
+ if (*Guid == NULL) {
+ //
+ // return the first Token Space Guid.
+ //
+ *Guid = GuidTable + ExMapTable[0].ExGuidIndex;
+ return EFI_SUCCESS;
+ }
+
+ MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(GuidTable[0]), *Guid);
+
+ if (MatchGuid == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ GuidTableIdx = MatchGuid - GuidTable;
+
+ Found = FALSE;
+ for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
+ if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (Found) {
+ Index++;
+ for ( ; Index < PeiPcdDb->ExTokenCount; Index++ ) {
+ if (ExMapTable[Index].ExGuidIndex != GuidTableIdx) {
+ Found = FALSE;
+ for (Index2 = 0 ; Index2 < Index; Index2++) {
+ if (ExMapTable[Index2].ExGuidIndex == ExMapTable[Index].ExGuidIndex) {
+ //
+ // This token namespace should have been found and output at preceding getting.
+ //
+ Found = TRUE;
+ break;
+ }
+ }
+ if (!Found) {
+ *Guid = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + ExMapTable[Index].ExGuidIndex;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ *Guid = NULL;
+ }
+
+ return EFI_NOT_FOUND;
+
+}
+
+/**
+ Get PCD value's size for POINTER type PCD.
+
+ The POINTER type PCD's value will be stored into a buffer in specified size.
+ The max size of this PCD's value is described in PCD's definition in DEC file.
+
+ @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
+ @param MaxSize Maximum size of PCD's value
+ @param Database Pcd database in PEI phase.
+
+ @return PCD value's size for POINTER type PCD.
+
+**/
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize,
+ IN PEI_PCD_DATABASE *Database
+ )
+{
+ INTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+ SIZE_INFO *SizeTable;
+ UINTN Index;
+
+ SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
+
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+
+ ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+ SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);
+
+ *MaxSize = SizeTable[SizeTableIdx];
+ //
+ // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+ // PCD entry.
+ //
+ if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+ //
+ // We have only two entry for VPD enabled PCD entry:
+ // 1) MAX Size.
+ // 2) Current Size
+ // We consider current size is equal to MAX size.
+ //
+ return *MaxSize;
+ } else {
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
+ //
+ // We have only two entry for Non-Sku enabled PCD entry:
+ // 1) MAX SIZE
+ // 2) Current Size
+ //
+ return SizeTable[SizeTableIdx + 1];
+ } else {
+ //
+ // We have these entry for SKU enabled PCD entry
+ // 1) MAX SIZE
+ // 2) Current Size for each SKU_ID (It is equal to MaxSku).
+ //
+ SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (SkuIdTable[1 + Index] == Database->SystemSkuId) {
+ return SizeTable[SizeTableIdx + 1 + Index];
+ }
+ }
+ return SizeTable[SizeTableIdx + 1];
+ }
+ }
+}
+
+/**
+ Set PCD value's size for POINTER type PCD.
+
+ The POINTER type PCD's value will be stored into a buffer in specified size.
+ The max size of this PCD's value is described in PCD's definition in DEC file.
+
+ @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
+ @param CurrentSize Maximum size of PCD's value
+ @param Database Pcd database in PEI phase.
+
+ @retval TRUE Success to set PCD's value size, which is not exceed maximum size
+ @retval FALSE Fail to set PCD's value size, which maybe exceed maximum size
+
+**/
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize,
+ IN PEI_PCD_DATABASE *Database
+ )
+{
+ INTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+ SIZE_INFO *SizeTable;
+ UINTN Index;
+ UINTN MaxSize;
+
+ SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
+
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+
+ ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+ SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);
+
+ MaxSize = SizeTable[SizeTableIdx];
+ //
+ // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+ // PCD entry.
+ //
+ if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+ //
+ // We shouldn't come here as we don't support SET for VPD
+ //
+ ASSERT (FALSE);
+ return FALSE;
+ } else {
+ if ((*CurrentSize > MaxSize) ||
+ (*CurrentSize == MAX_ADDRESS)) {
+ *CurrentSize = MaxSize;
+ return FALSE;
+ }
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
+ //
+ // We have only two entry for Non-Sku enabled PCD entry:
+ // 1) MAX SIZE
+ // 2) Current Size
+ //
+ SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ } else {
+ //
+ // We have these entry for SKU enabled PCD entry
+ // 1) MAX SIZE
+ // 2) Current Size for each SKU_ID (It is equal to MaxSku).
+ //
+ SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (SkuIdTable[1 + Index] == Database->SystemSkuId) {
+ SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ }
+ }
+ SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
+ return TRUE;
+ }
+ }
+
+}
diff --git a/Core/MdeModulePkg/Universal/PCD/Pei/Pcd.inf b/Core/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
new file mode 100644
index 0000000000..1d9c9242d9
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
@@ -0,0 +1,352 @@
+## @file
+# PCD PEIM produces PCD database to manage all dynamic PCD in PEI phase and install Pcd Ppi service.
+#
+# This version PCD PEIM depends on the external PCD database binary file, not built in PCD data base.
+# There are two PCD PPIs as follows:
+# 1) PCD_PPI
+# It is EDKII implementation which support Dynamic/DynamicEx Pcds.
+# 2) EFI_PEI_PCD_PPI
+# It is defined by PI specification 1.2, Vol 3 which only support dynamicEx
+# type Pcd.
+# For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI.
+# PCD PEIM driver will produce above two PPIs at same time.
+#
+# PCD database is generated as the separate binary image at build time. The binary image
+# will be intergrated into Firmware volume together with PCD driver.
+#
+# ////////////////////////////////////////////////////////////////////////////////
+# // //
+# // Introduction of PCD database //
+# // //
+# ////////////////////////////////////////////////////////////////////////////////
+#
+# 1, Introduction
+# PCD database hold all dynamic type PCD information. The structure of PEI PCD
+# database is generated by build tools according to dynamic PCD usage for
+# specified platform.
+#
+# 2, Dynamic Type PCD
+# Dynamic type PCD is used for the configuration/setting which value is determined
+# dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,
+# PatchablePcd) is fixed in final generated FD image in build time.
+#
+# 2.1 The "dynamic" determination means one of below cases:
+# a) The PCD setting value is produced by someone driver and consumed by
+# other driver in execution time.
+# b) The PCD setting value is set/get by user from FrontPage.
+# c) The PCD setting value is produced by platform OEM vendor in specified area.
+#
+# 2.2 According to module distribution way, dynamic PCD could be classfied as:
+# a) Dynamic:
+# If module is released in source code and will be built with platform
+# DSC, the dynamic PCD used by this module can be accessed as:
+# PcdGetxx(PcdSampleDynamicPcd);
+# In building platform, build tools will translate PcdSampleDynamicPcd to
+# pair of {Token Space Guid: Token Number} for this PCD.
+# b) DynamicEx:
+# If module is release as binary and will not pariticpate platform building,
+# the dynamic PCD used by this module need be accessed as:
+# PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)
+# Developer need explicity gives {Token Space Guid:Token Number} as parameter
+# in writting source code.
+#
+# 2.3 According to PCD value's storage method, dynamic PCD could be classfied as:
+# a) Default Storage:
+# - The PCD value is stored in PCD database maintained by PCD driver in boot
+# time memory.
+# - This type is used for communication between PEIM/DXE driver, DXE/DXE
+# driver. But all set/get value will be losted after boot-time memory
+# is turn off.
+# - [PcdsDynamicDefault] is used as section name for this type PCD in
+# platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.
+#
+# b) Variable Storage:
+# - The PCD value is stored in variable area.
+# - As default storage type, this type PCD could be used for PEI/DXE driver
+# communication. But beside it, this type PCD could also be used to store
+# the value associate with a HII setting via variable interface.
+# - In PEI phase, the PCD value could only be got but can not be set due
+# to variable area is readonly.
+# - [PcdsDynamicHii] is used as section name for this type PCD in platform
+# DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.
+#
+# c) OEM specificed storage area:
+# - The PCD value is stored in OEM specified area which base address is
+# specified by a FixedAtBuild PCD setting - PcdVpdBaseAddress.
+# - The area is read only for PEI and DXE phase.
+# - [PcdsDynamicVpd] is used as section name for this type PCD in platform
+# DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.
+#
+# 2.4 When and how to use dynamic PCD
+# Module developer do not care the used PCD is dynamic or static when writting
+# source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator
+# in platform DSC file. Please ref section 2.3 to get matching between dynamic
+# PCD type and section name in DSC file.
+#
+# 3, PCD database:
+# Although dynamic PCD could be in different storage type as above description,
+# but the basic information and default value for all dynamic PCD is hold
+# by PCD database maintained by PEI/DXE driver.
+#
+# As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database
+# also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.
+# To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic
+# PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD
+# database contains all PCDs used in PEI/DXE phase in memory.
+#
+# Build tool will generate PCD database into the separate binary file for
+# PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.
+#
+# 3.1 PcdPeim and PcdDxe
+# PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver
+# build guid hob in temporary memory and copy the binary data base from flash
+# to temporary memory for PEI PCD database.
+# DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,
+# a new PCD database is allocated in boot-time memory which including all
+# PEI PCD and DXE PCD entry.
+#
+# Pcd driver should run as early as possible before any other driver access
+# dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by
+# making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.
+#
+# 3.2 Token space Guid/Token number, Platform token, Local token number
+# Dynamic PCD
+# +-----------+ +---------+
+# |TokenSpace | |Platform |
+# | Guid | build tool | Token |
+# | + +-------------->| Number |
+# | Token | +---------+`._
+# | Number | `.
+# +-----------+ `. +------+
+# `-|Local |
+# |Token |
+# DynamicEx PCD ,-|Number|
+# +-----------+ ,-' +------+
+# |TokenSpace | ,-'
+# | Guid | _,-'
+# | + +.'
+# | Token |
+# | Number |
+# +-----------+
+#
+#
+# 3.2.1 Pair of Token space guid + Token number
+# Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it
+# is not easy maintained by PCD driver, and hashed token number will make
+# searching slowly.
+#
+# 3.2.2 Platform Token Number
+# "Platform token number" concept is introduced for mapping to a pair of
+# "TokenSpaceGuid + TokenNumber". The platform token number is generated by
+# build tool in autogen.h and all of them are continual in a platform scope
+# started from 1.(0 meaning invalid internal token number)
+# With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)
+# in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)
+# in autogen.h.
+# Notes: The mapping between pair of "tokenspace guid + token number" and
+# "internal token number" need build tool establish, so "platform token number"
+# mechanism is not suitable for binary module which use DynamicEx type PCD.
+# To access a dynamicEx type PCD, pair of "token space guid/token number" all need
+# to be specificed for PcdSet/PcdGet accessing macro.
+#
+# Platform Token Number is started from 1, and inceased continuous. From whole
+# platform scope, there are two zones: PEI Zone and DXE Zone
+# | Platform Token Number
+# ----------|----------------------------------------------------------------
+# PEI Zone: | 1 ~ PEI_LOCAL_TOKEN_NUMBER
+# DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)
+#
+# 3.2.3 Local Token Number
+# To fast searching a PCD entry in PCD database, PCD driver translate
+# platform token number to local token number via a mapping table.
+# For binary DynamicEx type PCD, there is a another mapping table to translate
+# "token space guid + token number" to local token number directly.
+# Local token number is identifier for all internal interface in PCD PEI/DXE
+# driver.
+#
+# A local token number is a 32-bit value in following meaning:
+# 32 ------------- 28 ---------- 24 -------- 0
+# | PCD type mask | Datum Type | Offset |
+# +-----------------------------------------+
+# where:
+# PCd type mask: indicate Pcd type from following macro:
+# PCD_TYPE_DATA
+# PCD_TYPE_HII
+# PCD_TYPE_VPD
+# PCD_TYPE_SKU_ENABLED
+# PCD_TYPE_STRING
+# Datum Type : indicate PCD vaue type from following macro:
+# PCD_DATUM_TYPE_POINTER
+# PCD_DATUM_TYPE_UINT8
+# PCD_DATUM_TYPE_UINT16
+# PCD_DATUM_TYPE_UINT32
+# PCD_DATUM_TYPE_UINT64
+# Offset : indicate the related offset of PCD value in PCD database array.
+# Based on local token number, PCD driver could fast determine PCD type, value
+# type and get PCD entry from PCD database.
+#
+# 3.3 PCD Database binary file
+# PCD Database binary file will be created at build time as the standalone binary image.
+# To understand the binary image layout, PCD Database C structure is still generated
+# as comments by build tools in PCD driver's autogen.h/
+# autogen.c file. In generated C structure, following information is stored:
+# - ExMapTable: This table is used translate a binary dynamicex type PCD's
+# "tokenguid + token" to local token number.
+# - LocalTokenNumberTable:
+# This table stores all local token number in array, use "Internal
+# token number" as array index to get PCD entry's offset fastly.
+# - SizeTable: This table stores the size information for all PCD entry.
+# - GuidTable: This table stores guid value for DynamicEx's token space,
+# HII type PCD's variable GUID.
+# - SkuIdTable: TBD
+# - SystemSkuId: TBD
+# - PCD value structure:
+# Every PCD has a value record in PCD database. For different
+# datum type PCD has different record structure which will be
+# introduced in 3.3.1
+#
+# In a PCD database structure, there are two major area: Init and UnInit.
+# Init area is use stored above PCD internal structure such as ExMapTable,
+# LocalTokenNumberTable etc and the (default) value of PCD which has default
+# value specified in platform DSC file.
+# Unint area is used stored the value of PCD which has no default value in
+# platform DSC file, the value of NULL, 0 specified in platform DSC file can
+# be seemed as "no default value".
+#
+# 3.3.1 Simple Sample PCD Database C Structure
+# A general sample of PCD database structue is as follows:
+# typedef struct _PCD_DATABASE {
+# typedef struct _PCD_DATABASE_INIT {
+# //===== Following is PCD database internal maintain structures
+# DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];
+# UINT32 LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
+# GUID GuidTable[PEI_GUID_TABLE_SIZE];
+# SIZE_INFO SizeTable[PEI_SIZE_TABLE_SIZE];
+# UINT8 SkuIdTable[PEI_SKUID_TABLE_SIZE];
+# SKU_ID SystemSkuId;
+#
+# //===== Following is value structure for PCD with default value
+# ....
+# ....
+# ....
+# } Init;
+# typedef struct _PCD_DATABSE_UNINIT {
+# //==== Following is value structure for PCD without default value
+# ....
+# ....
+# } UnInit;
+# }
+#
+# 3.3.2 PCD value structure in PCD database C structure
+# The value's structure is generated by build tool in PCD database C structure.
+# The PCDs in different datum type has different value structure.
+#
+# 3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD
+# The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64
+# data member in PCD database, For example:
+# UINT16 PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;
+# Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"
+# Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration
+# in DEC file.
+#
+# 3.3.2.2 VOID* datum type PCD
+# The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.
+#
+# 3.3.2.2.1 VOID* - string type
+# If the default value for VOID* datum type PCD like L"xxx", the PCD is
+# used for unicode string, and C structure of this datum type PCD is
+# UINT16 string array in PCD database, for example:
+# UINT16 StringTable[29];
+# The number of 29 in above sample is max size of a unicode string.
+#
+# If the default value for VOID* datum type PCD like "xxx", the PCD is
+# used for ascii string, and C structure of this datum type PCD is
+# UINT8 string array in PCD database, for example:
+# UINT8 StringTable[20];
+# The number of 20 in above sample is max size of a ascii string.
+#
+# 3.3.2.2.2 VOID* - byte array
+# If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}
+# the PCD is used for byte array. The generated structrue is same as
+# above ascii string table,
+# UINT8 StringTable[13];
+# The number of 13 in above sample is max size of byte array.
+#
+# 3.3.3 Some utility structures in PCD Database
+# 3.3.3.1 GuidTable
+# GuidTable array is used to store all related GUID value in PCD database:
+# - Variable GUID for HII type PCD
+# - Token space GUID for dynamicex type PCD
+#
+# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcdPeim
+ MODULE_UNI_FILE = PcdPeim.uni
+ FILE_GUID = 9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 4.0
+ PCD_IS_DRIVER = PEI_PCD_DRIVER
+ ENTRY_POINT = PcdPeimInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only)
+#
+
+[Sources]
+ Service.c
+ Service.h
+ Pcd.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ PcdLib
+ PeiServicesLib
+ HobLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ MemoryAllocationLib
+
+[Guids]
+ ## PRODUCES ## HOB
+ ## SOMETIMES_CONSUMES ## HOB
+ gPcdDataBaseHobGuid
+ gPcdDataBaseSignatureGuid ## CONSUMES ## GUID # PCD database signature GUID.
+
+[Ppis]
+ gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES
+ gPcdPpiGuid ## PRODUCES
+ gEfiPeiPcdPpiGuid ## PRODUCES
+ gGetPcdInfoPpiGuid ## SOMETIMES_PRODUCES
+ gEfiGetPcdInfoPpiGuid ## SOMETIMES_PRODUCES
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPeiFullPcdDatabaseEnable ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry ## SOMETIMES_CONSUMES
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ PcdPeimExtra.uni
diff --git a/Core/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni b/Core/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni
new file mode 100644
index 0000000000..b0d3f1f79a
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni
@@ -0,0 +1,296 @@
+// /** @file
+// PCD PEIM produces PCD database to manage all dynamic PCD in PEI phase and install Pcd Ppi service.
+//
+// This version PCD PEIM depends on the external PCD database binary file, not built in PCD data base.
+// There are two PCD PPIs as follows:
+// 1) PCD_PPI
+// It is EDKII implementation which support Dynamic/DynamicEx Pcds.
+// 2) EFI_PEI_PCD_PPI
+// It is defined by PI specification 1.2, Vol 3 which only support dynamicEx
+// type Pcd.
+// For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI.
+// PCD PEIM driver will produce above two PPIs at same time.
+//
+// PCD database is generated as the separate binary image at build time. The binary image
+// will be intergrated into Firmware volume together with PCD driver.
+//
+// ////////////////////////////////////////////////////////////////////////////////
+// // //
+// // Introduction of PCD database //
+// // //
+// ////////////////////////////////////////////////////////////////////////////////
+//
+// 1, Introduction
+// PCD database hold all dynamic type PCD information. The structure of PEI PCD
+// database is generated by build tools according to dynamic PCD usage for
+// specified platform.
+//
+// 2, Dynamic Type PCD
+// Dynamic type PCD is used for the configuration/setting which value is determined
+// dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,
+// PatchablePcd) is fixed in final generated FD image in build time.
+//
+// 2.1 The "dynamic" determination means one of below cases:
+// a) The PCD setting value is produced by someone driver and consumed by
+// other driver in execution time.
+// b) The PCD setting value is set/get by user from FrontPage.
+// c) The PCD setting value is produced by platform OEM vendor in specified area.
+//
+// 2.2 According to module distribution way, dynamic PCD could be classfied as:
+// a) Dynamic:
+// If module is released in source code and will be built with platform
+// DSC, the dynamic PCD used by this module can be accessed as:
+// PcdGetxx(PcdSampleDynamicPcd);
+// In building platform, build tools will translate PcdSampleDynamicPcd to
+// pair of {Token Space Guid: Token Number} for this PCD.
+// b) DynamicEx:
+// If module is release as binary and will not pariticpate platform building,
+// the dynamic PCD used by this module need be accessed as:
+// PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)
+// Developer need explicity gives {Token Space Guid:Token Number} as parameter
+// in writting source code.
+//
+// 2.3 According to PCD value's storage method, dynamic PCD could be classfied as:
+// a) Default Storage:
+// - The PCD value is stored in PCD database maintained by PCD driver in boot
+// time memory.
+// - This type is used for communication between PEIM/DXE driver, DXE/DXE
+// driver. But all set/get value will be losted after boot-time memory
+// is turn off.
+// - [PcdsDynamicDefault] is used as section name for this type PCD in
+// platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.
+//
+// b) Variable Storage:
+// - The PCD value is stored in variable area.
+// - As default storage type, this type PCD could be used for PEI/DXE driver
+// communication. But beside it, this type PCD could also be used to store
+// the value associate with a HII setting via variable interface.
+// - In PEI phase, the PCD value could only be got but can not be set due
+// to variable area is readonly.
+// - [PcdsDynamicHii] is used as section name for this type PCD in platform
+// DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.
+//
+// c) OEM specificed storage area:
+// - The PCD value is stored in OEM specified area which base address is
+// specified by a FixedAtBuild PCD setting - PcdVpdBaseAddress.
+// - The area is read only for PEI and DXE phase.
+// - [PcdsDynamicVpd] is used as section name for this type PCD in platform
+// DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.
+//
+// 2.4 When and how to use dynamic PCD
+// Module developer do not care the used PCD is dynamic or static when writting
+// source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator
+// in platform DSC file. Please ref section 2.3 to get matching between dynamic
+// PCD type and section name in DSC file.
+//
+// 3, PCD database:
+// Although dynamic PCD could be in different storage type as above description,
+// but the basic information and default value for all dynamic PCD is hold
+// by PCD database maintained by PEI/DXE driver.
+//
+// As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database
+// also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.
+// To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic
+// PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD
+// database contains all PCDs used in PEI/DXE phase in memory.
+//
+// Build tool will generate PCD database into the separate binary file for
+// PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.
+//
+// 3.1 PcdPeim and PcdDxe
+// PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver
+// build guid hob in temporary memory and copy the binary data base from flash
+// to temporary memory for PEI PCD database.
+// DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,
+// a new PCD database is allocated in boot-time memory which including all
+// PEI PCD and DXE PCD entry.
+//
+// Pcd driver should run as early as possible before any other driver access
+// dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by
+// making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.
+//
+// 3.2 Token space Guid/Token number, Platform token, Local token number
+// Dynamic PCD
+// +-----------+ +---------+
+// |TokenSpace | |Platform |
+// | Guid | build tool | Token |
+// | + +-------------->| Number |
+// | Token | +---------+`._
+// | Number | `.
+// +-----------+ `. +------+
+// `-|Local |
+// |Token |
+// DynamicEx PCD ,-|Number|
+// +-----------+ ,-' +------+
+// |TokenSpace | ,-'
+// | Guid | _,-'
+// | + +.'
+// | Token |
+// | Number |
+// +-----------+
+//
+//
+// 3.2.1 Pair of Token space guid + Token number
+// Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it
+// is not easy maintained by PCD driver, and hashed token number will make
+// searching slowly.
+//
+// 3.2.2 Platform Token Number
+// "Platform token number" concept is introduced for mapping to a pair of
+// "TokenSpaceGuid + TokenNumber". The platform token number is generated by
+// build tool in autogen.h and all of them are continual in a platform scope
+// started from 1.(0 meaning invalid internal token number)
+// With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)
+// in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)
+// in autogen.h.
+// Notes: The mapping between pair of "tokenspace guid + token number" and
+// "internal token number" need build tool establish, so "platform token number"
+// mechanism is not suitable for binary module which use DynamicEx type PCD.
+// To access a dynamicEx type PCD, pair of "token space guid/token number" all need
+// to be specificed for PcdSet/PcdGet accessing macro.
+//
+// Platform Token Number is started from 1, and inceased continuous. From whole
+// platform scope, there are two zones: PEI Zone and DXE Zone
+// | Platform Token Number
+// ----------|----------------------------------------------------------------
+// PEI Zone: | 1 ~ PEI_LOCAL_TOKEN_NUMBER
+// DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)
+//
+// 3.2.3 Local Token Number
+// To fast searching a PCD entry in PCD database, PCD driver translate
+// platform token number to local token number via a mapping table.
+// For binary DynamicEx type PCD, there is a another mapping table to translate
+// "token space guid + token number" to local token number directly.
+// Local token number is identifier for all internal interface in PCD PEI/DXE
+// driver.
+//
+// A local token number is a 32-bit value in following meaning:
+// 32 ------------- 28 ---------- 24 -------- 0
+// | PCD type mask | Datum Type | Offset |
+// +-----------------------------------------+
+// where:
+// PCd type mask: indicate Pcd type from following macro:
+// PCD_TYPE_DATA
+// PCD_TYPE_HII
+// PCD_TYPE_VPD
+// PCD_TYPE_SKU_ENABLED
+// PCD_TYPE_STRING
+// Datum Type : indicate PCD vaue type from following macro:
+// PCD_DATUM_TYPE_POINTER
+// PCD_DATUM_TYPE_UINT8
+// PCD_DATUM_TYPE_UINT16
+// PCD_DATUM_TYPE_UINT32
+// PCD_DATUM_TYPE_UINT64
+// Offset : indicate the related offset of PCD value in PCD database array.
+// Based on local token number, PCD driver could fast determine PCD type, value
+// type and get PCD entry from PCD database.
+//
+// 3.3 PCD Database binary file
+// PCD Database binary file will be created at build time as the standalone binary image.
+// To understand the binary image layout, PCD Database C structure is still generated
+// as comments by build tools in PCD driver's autogen.h/
+// autogen.c file. In generated C structure, following information is stored:
+// - ExMapTable: This table is used translate a binary dynamicex type PCD's
+// "tokenguid + token" to local token number.
+// - LocalTokenNumberTable:
+// This table stores all local token number in array, use "Internal
+// token number" as array index to get PCD entry's offset fastly.
+// - SizeTable: This table stores the size information for all PCD entry.
+// - GuidTable: This table stores guid value for DynamicEx's token space,
+// HII type PCD's variable GUID.
+// - SkuIdTable: TBD
+// - SystemSkuId: TBD
+// - PCD value structure:
+// Every PCD has a value record in PCD database. For different
+// datum type PCD has different record structure which will be
+// introduced in 3.3.1
+//
+// In a PCD database structure, there are two major area: Init and UnInit.
+// Init area is use stored above PCD internal structure such as ExMapTable,
+// LocalTokenNumberTable etc and the (default) value of PCD which has default
+// value specified in platform DSC file.
+// Unint area is used stored the value of PCD which has no default value in
+// platform DSC file, the value of NULL, 0 specified in platform DSC file can
+// be seemed as "no default value".
+//
+// 3.3.1 Simple Sample PCD Database C Structure
+// A general sample of PCD database structue is as follows:
+// typedef struct _PCD_DATABASE {
+// typedef struct _PCD_DATABASE_INIT {
+// //===== Following is PCD database internal maintain structures
+// DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];
+// UINT32 LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
+// GUID GuidTable[PEI_GUID_TABLE_SIZE];
+// SIZE_INFO SizeTable[PEI_SIZE_TABLE_SIZE];
+// UINT8 SkuIdTable[PEI_SKUID_TABLE_SIZE];
+// SKU_ID SystemSkuId;
+//
+// //===== Following is value structure for PCD with default value
+// ....
+// ....
+// ....
+// } Init;
+// typedef struct _PCD_DATABSE_UNINIT {
+// //==== Following is value structure for PCD without default value
+// ....
+// ....
+// } UnInit;
+// }
+//
+// 3.3.2 PCD value structure in PCD database C structure
+// The value's structure is generated by build tool in PCD database C structure.
+// The PCDs in different datum type has different value structure.
+//
+// 3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD
+// The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64
+// data member in PCD database, For example:
+// UINT16 PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;
+// Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"
+// Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration
+// in DEC file.
+//
+// 3.3.2.2 VOID* datum type PCD
+// The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.
+//
+// 3.3.2.2.1 VOID* - string type
+// If the default value for VOID* datum type PCD like L"xxx", the PCD is
+// used for unicode string, and C structure of this datum type PCD is
+// UINT16 string array in PCD database, for example:
+// UINT16 StringTable[29];
+// The number of 29 in above sample is max size of a unicode string.
+//
+// If the default value for VOID* datum type PCD like "xxx", the PCD is
+// used for ascii string, and C structure of this datum type PCD is
+// UINT8 string array in PCD database, for example:
+// UINT8 StringTable[20];
+// The number of 20 in above sample is max size of a ascii string.
+//
+// 3.3.2.2.2 VOID* - byte array
+// If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}
+// the PCD is used for byte array. The generated structrue is same as
+// above ascii string table,
+// UINT8 StringTable[13];
+// The number of 13 in above sample is max size of byte array.
+//
+// 3.3.3 Some utility structures in PCD Database
+// 3.3.3.1 GuidTable
+// GuidTable array is used to store all related GUID value in PCD database:
+// - Variable GUID for HII type PCD
+// - Token space GUID for dynamicex type PCD
+//
+// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "PCD PEIM produces PCD database to manage all dynamic PCD in PEI phase and install Pcd Ppi service."
+
+#string STR_MODULE_DESCRIPTION #language en-US "PCD PEIM produces PCD database to manage all dynamic PCD in PEI phase and install Pcd Ppi service."
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni b/Core/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni
new file mode 100644
index 0000000000..a618943612
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// PcdPeim Localized Strings and Content
+//
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Platform Configuration Database PEI Module"
+
+
diff --git a/Core/MdeModulePkg/Universal/PCD/Pei/Service.c b/Core/MdeModulePkg/Universal/PCD/Pei/Service.c
new file mode 100644
index 0000000000..5e1cb72ba5
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Pei/Service.c
@@ -0,0 +1,1209 @@
+/** @file
+ The driver internal functions are implmented here.
+ They build Pei PCD database, and provide access service to PCD database.
+
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Service.h"
+
+/**
+ Get Local Token Number by Token Number.
+
+ @param[in] Database PCD database.
+ @param[in] TokenNumber The PCD token number.
+
+ @return Local Token Number.
+**/
+UINT32
+GetLocalTokenNumber (
+ IN PEI_PCD_DATABASE *Database,
+ IN UINTN TokenNumber
+ )
+{
+ UINT32 LocalTokenNumber;
+ UINTN Size;
+ UINTN MaxSize;
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + TokenNumber);
+
+ Size = (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
+
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
+ if (Size == 0) {
+ GetPtrTypeSize (TokenNumber, &MaxSize, Database);
+ } else {
+ MaxSize = Size;
+ }
+ LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);
+ }
+
+ return LocalTokenNumber;
+}
+
+/**
+ Get PCD type by Local Token Number.
+
+ @param[in] LocalTokenNumber The PCD local token number.
+
+ @return PCD type.
+**/
+EFI_PCD_TYPE
+GetPcdType (
+ IN UINT32 LocalTokenNumber
+ )
+{
+ switch (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) {
+ case PCD_DATUM_TYPE_POINTER:
+ return EFI_PCD_TYPE_PTR;
+ case PCD_DATUM_TYPE_UINT8:
+ if ((LocalTokenNumber & PCD_DATUM_TYPE_UINT8_BOOLEAN) == PCD_DATUM_TYPE_UINT8_BOOLEAN) {
+ return EFI_PCD_TYPE_BOOL;
+ } else {
+ return EFI_PCD_TYPE_8;
+ }
+ case PCD_DATUM_TYPE_UINT16:
+ return EFI_PCD_TYPE_16;
+ case PCD_DATUM_TYPE_UINT32:
+ return EFI_PCD_TYPE_32;
+ case PCD_DATUM_TYPE_UINT64:
+ return EFI_PCD_TYPE_64;
+ default:
+ ASSERT (FALSE);
+ return EFI_PCD_TYPE_8;
+ }
+}
+
+/**
+ Get PCD name.
+
+ @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.
+ If FALSE, need to get the full PCD name.
+ @param[in] Database PCD database.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The TokenSpaceCName or full PCD name.
+**/
+CHAR8 *
+GetPcdName (
+ IN BOOLEAN OnlyTokenSpaceName,
+ IN PEI_PCD_DATABASE *Database,
+ IN UINTN TokenNumber
+ )
+{
+ UINT8 *StringTable;
+ UINTN NameSize;
+ PCD_NAME_INDEX *PcdNameIndex;
+ CHAR8 *TokenSpaceName;
+ CHAR8 *PcdName;
+ CHAR8 *Name;
+
+ //
+ // Return NULL when PCD name table is absent.
+ //
+ if (Database->PcdNameTableOffset == 0) {
+ return NULL;
+ }
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ StringTable = (UINT8 *) Database + Database->StringTableOffset;
+
+ //
+ // Get the PCD name index.
+ //
+ PcdNameIndex = (PCD_NAME_INDEX *)((UINT8 *) Database + Database->PcdNameTableOffset) + TokenNumber;
+ TokenSpaceName = (CHAR8 *)&StringTable[PcdNameIndex->TokenSpaceCNameIndex];
+ PcdName = (CHAR8 *)&StringTable[PcdNameIndex->PcdCNameIndex];
+
+ if (OnlyTokenSpaceName) {
+ //
+ // Only need to get the TokenSpaceCName.
+ //
+ Name = AllocateCopyPool (AsciiStrSize (TokenSpaceName), TokenSpaceName);
+ } else {
+ //
+ // Need to get the full PCD name.
+ //
+ NameSize = AsciiStrSize (TokenSpaceName) + AsciiStrSize (PcdName);
+ Name = AllocateZeroPool (NameSize);
+ ASSERT (Name != NULL);
+ //
+ // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
+ //
+ AsciiStrCatS (Name, NameSize, TokenSpaceName);
+ Name[AsciiStrSize (TokenSpaceName) - sizeof (CHAR8)] = '.';
+ AsciiStrCatS (Name, NameSize, PcdName);
+ }
+
+ return Name;
+}
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Database PCD database.
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+ExGetPcdInfo (
+ IN PEI_PCD_DATABASE *Database,
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ UINTN GuidTableIdx;
+ EFI_GUID *MatchGuid;
+ EFI_GUID *GuidTable;
+ DYNAMICEX_MAPPING *ExMapTable;
+ UINTN Index;
+ UINT32 LocalTokenNumber;
+
+ GuidTable = (EFI_GUID *)((UINT8 *)Database + Database->GuidTableOffset);
+ MatchGuid = ScanGuid (GuidTable, Database->GuidTableCount * sizeof(EFI_GUID), Guid);
+
+ if (MatchGuid == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ GuidTableIdx = MatchGuid - GuidTable;
+
+ ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)Database + Database->ExMapTableOffset);
+
+ //
+ // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
+ //
+ for (Index = 0; Index < Database->ExTokenCount; Index++) {
+ if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+ if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ //
+ // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
+ // PcdSize to 0 and PcdName to the null-terminated ASCII string
+ // associated with the token's namespace Guid.
+ //
+ PcdInfo->PcdType = EFI_PCD_TYPE_8;
+ PcdInfo->PcdSize = 0;
+ //
+ // Here use one representative in the token space to get the TokenSpaceCName.
+ //
+ PcdInfo->PcdName = GetPcdName (TRUE, Database, ExMapTable[Index].TokenNumber);
+ return EFI_SUCCESS;
+ } else if (ExMapTable[Index].ExTokenNumber == TokenNumber) {
+ PcdInfo->PcdSize = PeiPcdGetSize (ExMapTable[Index].TokenNumber);
+ LocalTokenNumber = GetLocalTokenNumber (Database, ExMapTable[Index].TokenNumber);
+ PcdInfo->PcdType = GetPcdType (LocalTokenNumber);
+ PcdInfo->PcdName = GetPcdName (FALSE, Database, ExMapTable[Index].TokenNumber);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+PeiGetPcdInfo (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ )
+{
+ PEI_PCD_DATABASE *PeiPcdDb;
+ BOOLEAN PeiExMapTableEmpty;
+ UINTN PeiNexTokenNumber;
+ UINT32 LocalTokenNumber;
+
+ ASSERT (PcdInfo != NULL);
+
+ PeiPcdDb = GetPcdDatabase ();
+ PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;
+
+ if (PeiPcdDb->ExTokenCount == 0) {
+ PeiExMapTableEmpty = TRUE;
+ } else {
+ PeiExMapTableEmpty = FALSE;
+ }
+
+ if (Guid == NULL) {
+ if (TokenNumber > PeiNexTokenNumber) {
+ return EFI_NOT_FOUND;
+ } else if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ //
+ // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
+ // PcdSize to 0 and PcdName to NULL for default Token Space.
+ //
+ PcdInfo->PcdType = EFI_PCD_TYPE_8;
+ PcdInfo->PcdSize = 0;
+ PcdInfo->PcdName = NULL;
+ } else {
+ PcdInfo->PcdSize = PeiPcdGetSize (TokenNumber);
+ LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber);
+ PcdInfo->PcdType = GetPcdType (LocalTokenNumber);
+ PcdInfo->PcdName = GetPcdName (FALSE, PeiPcdDb, TokenNumber);
+ }
+ return EFI_SUCCESS;
+ } else {
+ if (PeiExMapTableEmpty) {
+ return EFI_NOT_FOUND;
+ }
+ return ExGetPcdInfo (
+ PeiPcdDb,
+ Guid,
+ TokenNumber,
+ PcdInfo
+ );
+ }
+}
+
+/**
+ The function registers the CallBackOnSet fucntion
+ according to TokenNumber and EFI_GUID space.
+
+ @param ExTokenNumber The token number.
+ @param Guid The GUID space.
+ @param CallBackFunction The Callback function to be registered.
+ @param Register To register or unregister the callback function.
+
+ @retval EFI_SUCCESS If the Callback function is registered.
+ @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
+ @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
+ slot left in the CallbackFnTable.
+ @retval EFI_INVALID_PARAMETER If the callback function want to be de-registered can not be found.
+**/
+EFI_STATUS
+PeiRegisterCallBackWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PPI_CALLBACK CallBackFunction,
+ IN BOOLEAN Register
+)
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ PCD_PPI_CALLBACK *CallbackTable;
+ PCD_PPI_CALLBACK Compare;
+ PCD_PPI_CALLBACK Assign;
+ UINT32 LocalTokenNumber;
+ UINT32 LocalTokenCount;
+ UINTN PeiNexTokenNumber;
+ UINTN TokenNumber;
+ UINTN Idx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+
+ PeiPcdDb = GetPcdDatabase();
+ LocalTokenCount = PeiPcdDb->LocalTokenCount;
+ PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;
+
+ if (Guid == NULL) {
+ TokenNumber = ExTokenNumber;
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+ ASSERT (TokenNumber + 1 < (PeiNexTokenNumber + 1));
+ } else {
+ TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
+ if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ ASSERT ((TokenNumber + 1) < (LocalTokenCount + 1));
+ }
+
+
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);
+
+ //
+ // We don't support SET for HII and VPD type PCD entry in PEI phase.
+ // So we will assert if any register callback for such PCD entry.
+ //
+ ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);
+ ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);
+
+ GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ ASSERT (GuidHob != NULL);
+
+ CallbackTable = GET_GUID_HOB_DATA (GuidHob);
+ CallbackTable = CallbackTable + (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));
+
+ Compare = Register? NULL: CallBackFunction;
+ Assign = Register? CallBackFunction: NULL;
+
+
+ for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
+ if (CallbackTable[Idx] == Compare) {
+ CallbackTable[Idx] = Assign;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return Register? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER;
+
+}
+
+
+/**
+ Find the Pcd database.
+
+ @param FileHandle Handle of the file the external PCD database binary located.
+
+ @retval The base address of external PCD database binary.
+ @retval NULL Return NULL if not find.
+**/
+VOID *
+LocateExPcdBinary (
+ IN EFI_PEI_FILE_HANDLE FileHandle
+ )
+{
+ EFI_STATUS Status;
+ VOID *PcdDb;
+
+ PcdDb = NULL;
+
+ ASSERT (FileHandle != NULL);
+
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Check the first bytes (Header Signature Guid) and build version.
+ //
+ if (!CompareGuid (PcdDb, &gPcdDataBaseSignatureGuid) ||
+ (((PEI_PCD_DATABASE *) PcdDb)->BuildVersion != PCD_SERVICE_PEIM_VERSION)) {
+ ASSERT (FALSE);
+ }
+ return PcdDb;
+}
+
+
+/**
+ The function builds the PCD database.
+
+ @param FileHandle Handle of the file the external PCD database binary located.
+
+ @return Pointer to PCD database.
+**/
+PEI_PCD_DATABASE *
+BuildPcdDatabase (
+ IN EFI_PEI_FILE_HANDLE FileHandle
+ )
+{
+ PEI_PCD_DATABASE *Database;
+ PEI_PCD_DATABASE *PeiPcdDbBinary;
+ VOID *CallbackFnTable;
+ UINTN SizeOfCallbackFnTable;
+
+ //
+ // Locate the external PCD database binary for one section of current FFS
+ //
+ PeiPcdDbBinary = LocateExPcdBinary (FileHandle);
+
+ ASSERT(PeiPcdDbBinary != NULL);
+
+ Database = BuildGuidHob (&gPcdDataBaseHobGuid, PeiPcdDbBinary->Length + PeiPcdDbBinary->UninitDataBaseSize);
+
+ ZeroMem (Database, PeiPcdDbBinary->Length + PeiPcdDbBinary->UninitDataBaseSize);
+
+ //
+ // PeiPcdDbBinary is smaller than Database
+ //
+ CopyMem (Database, PeiPcdDbBinary, PeiPcdDbBinary->Length);
+
+ SizeOfCallbackFnTable = Database->LocalTokenCount * sizeof (PCD_PPI_CALLBACK) * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry);
+
+ CallbackFnTable = BuildGuidHob (&gEfiCallerIdGuid, SizeOfCallbackFnTable);
+
+ ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);
+
+ return Database;
+}
+
+/**
+ The function is provided by PCD PEIM and PCD DXE driver to
+ do the work of reading a HII variable from variable service.
+
+ @param VariableGuid The Variable GUID.
+ @param VariableName The Variable Name.
+ @param VariableData The output data.
+ @param VariableSize The size of the variable.
+
+ @retval EFI_SUCCESS Operation successful.
+ @retval EFI_NOT_FOUND Variablel not found.
+**/
+EFI_STATUS
+GetHiiVariable (
+ IN CONST EFI_GUID *VariableGuid,
+ IN UINT16 *VariableName,
+ OUT VOID **VariableData,
+ OUT UINTN *VariableSize
+ )
+{
+ UINTN Size;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;
+
+ Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);
+ ASSERT_EFI_ERROR (Status);
+
+ Size = 0;
+ Status = VariablePpi->GetVariable (
+ VariablePpi,
+ VariableName,
+ (EFI_GUID *) VariableGuid,
+ NULL,
+ &Size,
+ NULL
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Status = PeiServicesAllocatePool (Size, &Buffer);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = VariablePpi->GetVariable (
+ VariablePpi,
+ (UINT16 *) VariableName,
+ (EFI_GUID *) VariableGuid,
+ NULL,
+ &Size,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *VariableSize = Size;
+ *VariableData = Buffer;
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Find the local token number according to system SKU ID.
+
+ @param LocalTokenNumber PCD token number
+ @param Size The size of PCD entry.
+
+ @return Token number according to system SKU ID.
+
+**/
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size
+ )
+{
+ PEI_PCD_DATABASE *PeiPcdDb;
+ SKU_HEAD *SkuHead;
+ SKU_ID *SkuIdTable;
+ UINTN Index;
+ UINT8 *Value;
+ BOOLEAN FoundSku;
+
+ PeiPcdDb = GetPcdDatabase ();
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
+
+ SkuHead = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+ Value = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));
+ SkuIdTable = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));
+
+ //
+ // Find the current system's SKU ID entry in SKU ID table.
+ //
+ FoundSku = FALSE;
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (PeiPcdDb->SystemSkuId == SkuIdTable[Index + 1]) {
+ FoundSku = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Find the default SKU ID entry in SKU ID table.
+ //
+ if(!FoundSku) {
+ for (Index = 0; Index < SkuIdTable[0]; Index++) {
+ if (0 == SkuIdTable[Index + 1]) {
+ break;
+ }
+ }
+ }
+ ASSERT (Index < SkuIdTable[0]);
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ Value = (UINT8 *) &(((VPD_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);
+
+ case PCD_TYPE_HII:
+ Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);
+
+ case PCD_TYPE_HII|PCD_TYPE_STRING:
+ Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII | PCD_TYPE_STRING);
+
+ case PCD_TYPE_STRING:
+ Value = (UINT8 *) &(((STRING_HEAD *) Value)[Index]);
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);
+
+ case PCD_TYPE_DATA:
+ Value += Size * Index;
+ return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_DATA);
+
+ default:
+ ASSERT (FALSE);
+ }
+
+ ASSERT (FALSE);
+
+ return 0;
+}
+
+/**
+ Invoke the callback function when dynamic PCD entry was set, if this PCD entry
+ has registered callback function.
+
+ @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
+ type PCD.
+ @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
+ PCD.
+ @param TokenNumber PCD token number generated by build tools.
+ @param Data Value want to be set for this PCD entry
+ @param Size The size of value
+
+**/
+VOID
+InvokeCallbackOnSet (
+ UINTN ExTokenNumber,
+ CONST EFI_GUID *Guid, OPTIONAL
+ UINTN TokenNumber,
+ VOID *Data,
+ UINTN Size
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ PCD_PPI_CALLBACK *CallbackTable;
+ UINTN Idx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ UINT32 LocalTokenCount;
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ PeiPcdDb = GetPcdDatabase ();
+ LocalTokenCount = PeiPcdDb->LocalTokenCount;
+
+ if (Guid == NULL) {
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));
+ }
+
+ GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ ASSERT (GuidHob != NULL);
+
+ CallbackTable = GET_GUID_HOB_DATA (GuidHob);
+
+ CallbackTable += (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));
+
+ for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
+ if (CallbackTable[Idx] != NULL) {
+ CallbackTable[Idx] (Guid,
+ (Guid == NULL) ? (TokenNumber + 1) : ExTokenNumber,
+ Data,
+ Size
+ );
+ }
+ }
+}
+
+/**
+ Wrapper function for setting non-pointer type value for a PCD entry.
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+
+ @return status of SetWorker.
+
+**/
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ return SetWorker (TokenNumber, Data, &Size, FALSE);
+}
+
+/**
+ Set value for an PCD entry
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+ @param PtrType If TRUE, the type of PCD entry's value is Pointer.
+ If False, the type of PCD entry's value is not Pointer.
+
+ @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
+ @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
+ @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
+ @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
+ range of UINT8, UINT16, UINT32, UINT64
+ @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
+**/
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+{
+ UINT32 LocalTokenNumber;
+ UINTN PeiNexTokenNumber;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ STRING_HEAD StringTableIdx;
+ UINTN Offset;
+ VOID *InternalData;
+ UINTN MaxSize;
+ UINT32 LocalTokenCount;
+
+ if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+ PeiPcdDb = GetPcdDatabase ();
+ LocalTokenCount = PeiPcdDb->LocalTokenCount;
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));
+
+ if (PtrType) {
+ //
+ // Get MaxSize first, then check new size with max buffer size.
+ //
+ GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
+ if (*Size > MaxSize) {
+ *Size = MaxSize;
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (*Size != PeiPcdGetSize (TokenNumber + 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // We only invoke the callback function for Dynamic Type PCD Entry.
+ // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
+ // type PCD entry in ExSetWorker.
+ //
+ PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;
+ if (TokenNumber + 1 < PeiNexTokenNumber + 1) {
+ InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);
+ }
+
+ LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+ InternalData = (VOID *) ((UINT8 *) PeiPcdDb + Offset);
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ case PCD_TYPE_HII:
+ case PCD_TYPE_HII|PCD_TYPE_STRING:
+ {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ case PCD_TYPE_STRING:
+ if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {
+ StringTableIdx = *((STRING_HEAD *)InternalData);
+ CopyMem ((UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset + StringTableIdx, Data, *Size);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ case PCD_TYPE_DATA:
+ {
+ if (PtrType) {
+ if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {
+ CopyMem (InternalData, Data, *Size);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ switch (*Size) {
+ case sizeof(UINT8):
+ *((UINT8 *) InternalData) = *((UINT8 *) Data);
+ return EFI_SUCCESS;
+
+ case sizeof(UINT16):
+ *((UINT16 *) InternalData) = *((UINT16 *) Data);
+ return EFI_SUCCESS;
+
+ case sizeof(UINT32):
+ *((UINT32 *) InternalData) = *((UINT32 *) Data);
+ return EFI_SUCCESS;
+
+ case sizeof(UINT64):
+ *((UINT64 *) InternalData) = *((UINT64 *) Data);
+ return EFI_SUCCESS;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ }
+
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+
+}
+
+/**
+ Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
+
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data Value want to be set.
+ @param SetSize The size of value.
+
+ @return status of ExSetWorker().
+
+**/
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);
+}
+
+/**
+ Set value for a dynamic-ex PCD entry.
+
+ This routine find the local token number according to dynamic-ex PCD's token
+ space guid and token number firstly, and invoke callback function if this PCD
+ entry registered callback function. Finally, invoken general SetWorker to set
+ PCD value.
+
+ @param ExTokenNumber Dynamic-ex PCD token number.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data PCD value want to be set
+ @param SetSize Size of value.
+ @param PtrType If TRUE, this PCD entry is pointer type.
+ If FALSE, this PCD entry is not pointer type.
+
+ @return status of SetWorker().
+
+**/
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ )
+{
+ UINTN TokenNumber;
+
+ if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
+ if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+ return EFI_NOT_FOUND;
+ }
+
+ InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);
+
+ return SetWorker (TokenNumber, Data, Size, PtrType);
+
+}
+
+/**
+ Wrapper function for get PCD value for dynamic-ex PCD.
+
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param ExTokenNumber Token number for dyanmic-ex PCD.
+ @param GetSize The size of dynamic-ex PCD value.
+
+ @return PCD entry in PCD database.
+
+**/
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ )
+{
+ return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);
+}
+
+/**
+ Get the PCD entry pointer in PCD database.
+
+ This routine will visit PCD database to find the PCD entry according to given
+ token number. The given token number is autogened by build tools and it will be
+ translated to local token number. Local token number contains PCD's type and
+ offset of PCD entry in PCD database.
+
+ @param TokenNumber Token's number, it is autogened by build tools
+ @param GetSize The size of token's value
+
+ @return PCD entry pointer in PCD database
+
+**/
+VOID *
+GetWorker (
+ IN UINTN TokenNumber,
+ IN UINTN GetSize
+ )
+{
+ UINT32 Offset;
+ EFI_GUID *Guid;
+ UINT16 *Name;
+ VARIABLE_HEAD *VariableHead;
+ EFI_STATUS Status;
+ UINTN DataSize;
+ VOID *Data;
+ UINT8 *StringTable;
+ STRING_HEAD StringTableIdx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+ UINT32 LocalTokenNumber;
+ UINT32 LocalTokenCount;
+ UINT8 *VaraiableDefaultBuffer;
+
+ //
+ // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+ // We have to decrement TokenNumber by 1 to make it usable
+ // as the array index.
+ //
+ TokenNumber--;
+
+ PeiPcdDb = GetPcdDatabase ();
+ LocalTokenCount = PeiPcdDb->LocalTokenCount;
+
+ // EBC compiler is very choosy. It may report warning about comparison
+ // between UINTN and 0 . So we add 1 in each size of the
+ // comparison.
+ ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));
+
+ ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));
+
+ LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);
+
+ Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
+ StringTable = (UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset;
+
+ switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
+ case PCD_TYPE_VPD:
+ {
+ VPD_HEAD *VpdHead;
+ VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
+ return (VOID *) ((UINTN) PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);
+ }
+
+ case PCD_TYPE_HII|PCD_TYPE_STRING:
+ case PCD_TYPE_HII:
+ {
+ VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
+
+ Guid = (EFI_GUID *) ((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + VariableHead->GuidTableIndex;
+ Name = (UINT16*)&StringTable[VariableHead->StringIndex];
+
+ if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {
+ //
+ // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
+ // string array in string table.
+ //
+ VaraiableDefaultBuffer = (UINT8 *) &StringTable[*(STRING_HEAD*)((UINT8*) PeiPcdDb + VariableHead->DefaultValueOffset)];
+ } else {
+ VaraiableDefaultBuffer = (UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset;
+ }
+ Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
+ if ((Status == EFI_SUCCESS) && (DataSize >= (VariableHead->Offset + GetSize))) {
+ if (GetSize == 0) {
+ //
+ // It is a pointer type. So get the MaxSize reserved for
+ // this PCD entry.
+ //
+ GetPtrTypeSize (TokenNumber, &GetSize, PeiPcdDb);
+ if (GetSize > (DataSize - VariableHead->Offset)) {
+ //
+ // Use actual valid size.
+ //
+ GetSize = DataSize - VariableHead->Offset;
+ }
+ }
+ //
+ // If the operation is successful, we copy the data
+ // to the default value buffer in the PCD Database.
+ //
+ CopyMem (VaraiableDefaultBuffer, (UINT8 *) Data + VariableHead->Offset, GetSize);
+ }
+ return (VOID *) VaraiableDefaultBuffer;
+ }
+
+ case PCD_TYPE_DATA:
+ return (VOID *) ((UINT8 *)PeiPcdDb + Offset);
+
+ case PCD_TYPE_STRING:
+ StringTableIdx = * (STRING_HEAD*) ((UINT8 *) PeiPcdDb + Offset);
+ return (VOID *) (&StringTable[StringTableIdx]);
+
+ default:
+ ASSERT (FALSE);
+ break;
+
+ }
+
+ ASSERT (FALSE);
+
+ return NULL;
+
+}
+
+/**
+ Get Token Number according to dynamic-ex PCD's {token space guid:token number}
+
+ A dynamic-ex type PCD, developer must provide pair of token space guid: token number
+ in DEC file. PCD database maintain a mapping table that translate pair of {token
+ space guid: token number} to Token Number.
+
+ @param Guid Token space guid for dynamic-ex PCD entry.
+ @param ExTokenNumber Dynamic-ex PCD token number.
+
+ @return Token Number for dynamic-ex PCD.
+
+**/
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ )
+{
+ UINT32 Index;
+ DYNAMICEX_MAPPING *ExMap;
+ EFI_GUID *GuidTable;
+ EFI_GUID *MatchGuid;
+ UINTN MatchGuidIdx;
+ PEI_PCD_DATABASE *PeiPcdDb;
+
+ PeiPcdDb = GetPcdDatabase();
+
+ ExMap = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
+ GuidTable = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
+
+ MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof(EFI_GUID), Guid);
+ //
+ // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
+ // error in the BUILD system.
+ //
+ ASSERT (MatchGuid != NULL);
+
+ MatchGuidIdx = MatchGuid - GuidTable;
+
+ for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
+ if ((ExTokenNumber == ExMap[Index].ExTokenNumber) &&
+ (MatchGuidIdx == ExMap[Index].ExGuidIndex)) {
+ return ExMap[Index].TokenNumber;
+ }
+ }
+
+ return PCD_INVALID_TOKEN_NUMBER;
+}
+
+/**
+ Get PCD database from GUID HOB in PEI phase.
+
+ @return Pointer to PCD database.
+
+**/
+PEI_PCD_DATABASE *
+GetPcdDatabase (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
+ ASSERT (GuidHob != NULL);
+
+ return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
+}
+
+/**
+ Get SKU ID table from PCD database.
+
+ @param LocalTokenNumberTableIdx Index of local token number in token number table.
+ @param Database PCD database.
+
+ @return Pointer to SKU ID array table
+
+**/
+SKU_ID *
+GetSkuIdArray (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ )
+{
+ SKU_HEAD *SkuHead;
+ UINTN LocalTokenNumber;
+
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+
+ ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);
+
+ SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
+
+ return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);
+
+}
+
+/**
+ Get index of PCD entry in size table.
+
+ @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
+ @param Database Pointer to PCD database in PEI phase.
+
+ @return index of PCD entry in size table.
+
+**/
+UINTN
+GetSizeTableIndex (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ )
+{
+ UINTN Index;
+ UINTN SizeTableIdx;
+ UINTN LocalTokenNumber;
+ SKU_ID *SkuIdTable;
+
+ SizeTableIdx = 0;
+
+ for (Index = 0; Index < LocalTokenNumberTableIdx; Index++) {
+ LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + Index);
+
+ if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {
+ //
+ // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+ // PCD entry.
+ //
+ if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+ //
+ // We have only two entry for VPD enabled PCD entry:
+ // 1) MAX Size.
+ // 2) Current Size
+ // Current size is equal to MAX size.
+ //
+ SizeTableIdx += 2;
+ } else {
+ if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
+ //
+ // We have only two entry for Non-Sku enabled PCD entry:
+ // 1) MAX SIZE
+ // 2) Current Size
+ //
+ SizeTableIdx += 2;
+ } else {
+ //
+ // We have these entry for SKU enabled PCD entry
+ // 1) MAX SIZE
+ // 2) Current Size for each SKU_ID (It is equal to MaxSku).
+ //
+ SkuIdTable = GetSkuIdArray (Index, Database);
+ SizeTableIdx += (UINTN)*SkuIdTable + 1;
+ }
+ }
+ }
+
+ }
+
+ return SizeTableIdx;
+}
diff --git a/Core/MdeModulePkg/Universal/PCD/Pei/Service.h b/Core/MdeModulePkg/Universal/PCD/Pei/Service.h
new file mode 100644
index 0000000000..fa14abeaa3
--- /dev/null
+++ b/Core/MdeModulePkg/Universal/PCD/Pei/Service.h
@@ -0,0 +1,1117 @@
+/** @file
+ The internal header file declares the private functions used by PeiPcd driver.
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_PCD_SERVICE_H_
+#define _PEI_PCD_SERVICE_H_
+
+#include <PiPei.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/Pcd.h>
+#include <Ppi/PiPcd.h>
+#include <Ppi/PcdInfo.h>
+#include <Ppi/PiPcdInfo.h>
+#include <Guid/PcdDataBaseHobGuid.h>
+#include <Guid/PcdDataBaseSignatureGuid.h>
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+//
+// Please make sure the PCD Serivce PEIM Version is consistent with
+// the version of the generated PEIM PCD Database by build tool.
+//
+#define PCD_SERVICE_PEIM_VERSION 6
+
+//
+// PCD_PEI_SERVICE_DRIVER_VERSION is defined in Autogen.h.
+//
+#if (PCD_SERVICE_PEIM_VERSION != PCD_PEI_SERVICE_DRIVER_VERSION)
+ #error "Please make sure the version of PCD PEIM Service and the generated PCD PEI Database match."
+#endif
+
+/**
+ Retrieve additional information associated with a PCD token in the default token space.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetPcdInfoGetInfo (
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ );
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetPcdInfoGetInfoEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ );
+
+/**
+ Retrieve the currently set SKU Id.
+
+ @return The currently set SKU Id. If the platform has not set at a SKU Id, then the
+ default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
+ Id is returned.
+**/
+UINTN
+EFIAPI
+PeiGetPcdInfoGetSku (
+ VOID
+ );
+
+//
+// PPI Interface Implementation Declaration.
+//
+
+/**
+ Sets the SKU value for subsequent calls to set or get PCD token values.
+
+ SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
+ SetSku() is normally called only once by the system.
+
+ For each item (token), the database can hold a single value that applies to all SKUs,
+ or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
+ SKU-specific values are called SKU enabled.
+
+ The SKU Id of zero is reserved as a default. The valid SkuId range is 1 to 255.
+ For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
+ single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
+ last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
+ the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
+ set for that Id, the results are unpredictable.
+
+ @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and
+ set values associated with a PCD token.
+
+**/
+VOID
+EFIAPI
+PeiPcdSetSku (
+ IN UINTN SkuId
+ );
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the current byte-sized value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT8 value.
+
+**/
+UINT8
+EFIAPI
+PeiPcdGet8 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the current 16-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT16 value.
+
+**/
+UINT16
+EFIAPI
+PeiPcdGet16 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the current 32-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT32 value.
+
+**/
+UINT32
+EFIAPI
+PeiPcdGet32 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the current 64-bits value for a PCD token number.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The UINT64 value.
+
+**/
+UINT64
+EFIAPI
+PeiPcdGet64 (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrived.
+
+**/
+VOID *
+EFIAPI
+PeiPcdGetPtr (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves a Boolean value for a given PCD token.
+
+ Retrieves the current boolean value for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The Boolean value.
+
+**/
+BOOLEAN
+EFIAPI
+PeiPcdGetBool (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+PeiPcdGetSize (
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 8-bit value for a given PCD token.
+
+ Retrieves the 8-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 8-bit value for the PCD token.
+
+**/
+UINT8
+EFIAPI
+PeiPcdGet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 16-bit value for a given PCD token.
+
+ Retrieves the 16-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 16-bit value for the PCD token.
+
+**/
+UINT16
+EFIAPI
+PeiPcdGet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 32-bit value for a given PCD token.
+
+ Retrieves the 32-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 32-bit value for the PCD token.
+
+**/
+UINT32
+EFIAPI
+PeiPcdGet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an 64-bit value for a given PCD token.
+
+ Retrieves the 64-bit value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size 64-bit value for the PCD token.
+
+**/
+UINT64
+EFIAPI
+PeiPcdGet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves a pointer to a value for a given PCD token.
+
+ Retrieves the current pointer to the buffer for a PCD token number.
+ Do not make any assumptions about the alignment of the pointer that
+ is returned by this function call. If the TokenNumber is invalid,
+ the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The pointer to the buffer to be retrived.
+
+**/
+VOID *
+EFIAPI
+PeiPcdGetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves an Boolean value for a given PCD token.
+
+ Retrieves the Boolean value of a particular PCD token.
+ If the TokenNumber is invalid or the token space
+ specified by Guid does not exist, the results are
+ unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size Boolean value for the PCD token.
+
+**/
+BOOLEAN
+EFIAPI
+PeiPcdGetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Retrieves the size of the value for a given PCD token.
+
+ Retrieves the current size of a particular PCD token.
+ If the TokenNumber is invalid, the results are unpredictable.
+
+ @param[in] Guid The token space for the token number.
+ @param[in] TokenNumber The PCD token number.
+
+ @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+PeiPcdGetSizeEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber
+ );
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet8 (
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ );
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet16 (
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ );
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet32 (
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ );
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet64 (
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ );
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtr (
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ );
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetBool (
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ );
+
+/**
+ Sets an 8-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet8Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT8 Value
+ );
+
+/**
+ Sets an 16-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet16Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT16 Value
+ );
+
+/**
+ Sets an 32-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet32Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT32 Value
+ );
+
+/**
+ Sets an 64-bit value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet64Ex (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN UINT64 Value
+ );
+
+/**
+ Sets a value of a specified size for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+ On input, if the SizeOfValue is greater than the maximum size supported
+ for this TokenNumber then the output value of SizeOfValue will reflect
+ the maximum size supported for this TokenNumber.
+ @param[in] Buffer The buffer to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtrEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN OUT UINTN *SizeOfBuffer,
+ IN VOID *Buffer
+ );
+
+/**
+ Sets an Boolean value for a given PCD token.
+
+ When the PCD service sets a value, it will check to ensure that the
+ size of the value being set is compatible with the Token's existing definition.
+ If it is not, an error will be returned.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] Value The value to set for the PCD token.
+
+ @retval EFI_SUCCESS Procedure returned successfully.
+ @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+ being set was incompatible with a call to this function.
+ Use GetSize() to retrieve the size of the target data.
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetBoolEx (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ IN BOOLEAN Value
+ );
+
+/**
+ Specifies a function to be called anytime the value of a designated token is changed.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PPI_CALLBACK CallBackFunction
+ );
+
+/**
+ Cancels a previously set callback function for a particular PCD token number.
+
+ @param [in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param [in] TokenNumber The PCD token number.
+ @param [in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+ @retval EFI_SUCCESS The PCD service has successfully established a call event
+ for the CallBackToken requested.
+ @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PcdUnRegisterCallBackOnSet (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN UINTN TokenNumber,
+ IN PCD_PPI_CALLBACK CallBackFunction
+ );
+
+/**
+ Retrieves the next valid token number in a given namespace.
+
+ This is useful since the PCD infrastructure contains a sparse list of token numbers,
+ and one cannot a priori know what token numbers are valid in the database.
+
+ If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
+ If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
+ If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
+ If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
+ The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
+ If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
+ If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+ If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ This is an optional parameter that may be NULL. If this parameter is NULL, then a request
+ is being made to retrieve tokens from the default token space.
+ @param[in, out] TokenNumber A pointer to the PCD token number to use to find the subsequent token number.
+
+ @retval EFI_SUCCESS The PCD service has retrieved the next valid token number.
+ Or the input token number is already the last valid token number in the PCD database.
+ In the later case, *TokenNumber is updated with the value of 0.
+ @retval EFI_NOT_FOUND If this input token number and token namespace does not exist on the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextToken (
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN OUT UINTN *TokenNumber
+ );
+
+/**
+ Retrieves the next valid PCD token namespace for a given namespace.
+
+ @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates
+ a known token namespace from which the search will start. On output,
+ it designates the next valid token namespace on the platform. If the input
+ token namespace does not exist on the platform, an error is returned and
+ the value of *Guid is undefined. If *Guid is NULL, then the GUID of the
+ first token space of the current platform is assigned to *Guid the function
+ return EFI_SUCCESS. If *Guid is NULL and there is no namespace exist in
+ the platform other than the default (NULL) tokennamespace, *Guid is unchanged
+ and the function return EFI_SUCCESS. If this input token namespace is the last
+ namespace on the platform, *Guid will be assigned to NULL and the function return
+ EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The PCD service retrieved the next valid token space Guid.
+ Or the input token space Guid is already the last valid token space Guid
+ in the PCD database. In the later case, *Guid is updated with the value of NULL.
+ @retval EFI_NOT_FOUND If the input token namespace does not exist on the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextTokenSpace (
+ IN OUT CONST EFI_GUID **Guid
+ );
+
+/**
+ Retrieve additional information associated with a PCD token.
+
+ This includes information such as the type of value the TokenNumber is associated with as well as possible
+ human readable name that is associated with the token.
+
+ @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
+ @param[in] TokenNumber The PCD token number.
+ @param[out] PcdInfo The returned information associated with the requested TokenNumber.
+ The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+ @retval EFI_SUCCESS The PCD information was returned successfully
+ @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+PeiGetPcdInfo (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN TokenNumber,
+ OUT EFI_PCD_INFO *PcdInfo
+ );
+
+/* Internal Function definitions */
+/**
+ Get PCD database from GUID HOB in PEI phase.
+
+ @return Pointer to PCD database.
+
+**/
+PEI_PCD_DATABASE *
+GetPcdDatabase (
+ VOID
+ );
+
+/**
+ Wrapper function for setting non-pointer type value for a PCD entry.
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+
+ @return status of SetWorker.
+
+**/
+EFI_STATUS
+SetValueWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN UINTN Size
+ );
+
+/**
+ Set value for an PCD entry
+
+ @param TokenNumber Pcd token number autogenerated by build tools.
+ @param Data Value want to be set for PCD entry
+ @param Size Size of value.
+ @param PtrType If TRUE, the type of PCD entry's value is Pointer.
+ If False, the type of PCD entry's value is not Pointer.
+
+ @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
+ @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
+ @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
+ @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
+ range of UINT8, UINT16, UINT32, UINT64
+ @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
+**/
+EFI_STATUS
+SetWorker (
+ IN UINTN TokenNumber,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ );
+
+/**
+ Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
+
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data Value want to be set.
+ @param SetSize The size of value.
+
+ @return status of ExSetWorker().
+
+**/
+EFI_STATUS
+ExSetValueWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN Size
+ );
+
+/**
+ Set value for a dynamic PCD entry.
+
+ This routine find the local token number according to dynamic-ex PCD's token
+ space guid and token number firstly, and invoke callback function if this PCD
+ entry registered callback function. Finally, invoken general SetWorker to set
+ PCD value.
+
+ @param ExTokenNumber Dynamic-ex PCD token number.
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param Data PCD value want to be set
+ @param SetSize Size of value.
+ @param PtrType If TRUE, this PCD entry is pointer type.
+ If FALSE, this PCD entry is not pointer type.
+
+ @return status of SetWorker().
+
+**/
+EFI_STATUS
+ExSetWorker (
+ IN UINTN ExTokenNumber,
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN OUT UINTN *Size,
+ IN BOOLEAN PtrType
+ );
+
+/**
+ Get the PCD entry pointer in PCD database.
+
+ This routine will visit PCD database to find the PCD entry according to given
+ token number. The given token number is autogened by build tools and it will be
+ translated to local token number. Local token number contains PCD's type and
+ offset of PCD entry in PCD database.
+
+ @param TokenNumber Token's number, it is autogened by build tools
+ @param GetSize The size of token's value
+
+ @return PCD entry pointer in PCD database
+
+**/
+VOID *
+GetWorker (
+ IN UINTN TokenNumber,
+ IN UINTN GetSize
+ );
+
+/**
+ Wrapper function for get PCD value for dynamic-ex PCD.
+
+ @param Guid Token space guid for dynamic-ex PCD.
+ @param ExTokenNumber Token number for dyanmic-ex PCD.
+ @param GetSize The size of dynamic-ex PCD value.
+
+ @return PCD entry in PCD database.
+
+**/
+VOID *
+ExGetWorker (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber,
+ IN UINTN GetSize
+ );
+
+typedef struct {
+ UINTN TokenNumber;
+ UINTN Size;
+ UINT32 LocalTokenNumberAlias;
+} EX_PCD_ENTRY_ATTRIBUTE;
+
+/**
+ Get Token Number according to dynamic-ex PCD's {token space guid:token number}
+
+ A dynamic-ex type PCD, developer must provide pair of token space guid: token number
+ in DEC file. PCD database maintain a mapping table that translate pair of {token
+ space guid: token number} to Token Number.
+
+ @param Guid Token space guid for dynamic-ex PCD entry.
+ @param ExTokenNumber Token number for dynamic-ex PCD.
+
+ @return Token Number for dynamic-ex PCD.
+
+**/
+UINTN
+GetExPcdTokenNumber (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN ExTokenNumber
+ );
+
+/**
+ Find the local token number according to system SKU ID.
+
+ @param LocalTokenNumber PCD token number
+ @param Size The size of PCD entry.
+
+ @return Token number according to system SKU ID.
+
+**/
+UINT32
+GetSkuEnabledTokenNumber (
+ UINT32 LocalTokenNumber,
+ UINTN Size
+ );
+
+/**
+ The function registers the CallBackOnSet fucntion
+ according to TokenNumber and EFI_GUID space.
+
+ @param TokenNumber The token number.
+ @param Guid The GUID space.
+ @param CallBackFunction The Callback function to be registered.
+ @param Register To register or unregister the callback function.
+
+ @retval EFI_SUCCESS If the Callback function is registered.
+ @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
+ @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
+ slot left in the CallbackFnTable.
+**/
+EFI_STATUS
+PeiRegisterCallBackWorker (
+ IN UINTN TokenNumber,
+ IN CONST EFI_GUID *Guid, OPTIONAL
+ IN PCD_PPI_CALLBACK CallBackFunction,
+ IN BOOLEAN Register
+ );
+
+/**
+ The function builds the PCD database.
+
+ @param FileHandle Handle of the file the external PCD database binary located.
+
+ @return Pointer to PCD database.
+
+**/
+PEI_PCD_DATABASE *
+BuildPcdDatabase (
+ IN EFI_PEI_FILE_HANDLE FileHandle
+ );
+
+/**
+ Get SKU ID tabble from PCD database.
+
+ @param LocalTokenNumberTableIdx Index of local token number in token number table.
+ @param Database PCD Database in PEI phase
+
+ @return Pointer to SKU ID array table
+
+**/
+SKU_ID *
+GetSkuIdArray (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ );
+
+/**
+ Get index of PCD entry in size table.
+
+ @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
+ @param Database Pointer to PCD database.
+
+ @return index of PCD entry in size table.
+
+**/
+UINTN
+GetSizeTableIndex (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN PEI_PCD_DATABASE *Database
+ );
+
+/**
+ Get PCD value's size for POINTER type PCD.
+
+ The POINTER type PCD's value will be stored into a buffer in specificed size.
+ The max size of this PCD's value is described in PCD's definition in DEC file.
+
+ @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
+ @param MaxSize Maxmium size of PCD's value
+ @param Database Pcd database in PEI phase.
+
+ @return PCD value's size for POINTER type PCD.
+
+**/
+UINTN
+GetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ OUT UINTN *MaxSize,
+ IN PEI_PCD_DATABASE *Database
+ );
+
+/**
+ Set PCD value's size for POINTER type PCD.
+
+ The POINTER type PCD's value will be stored into a buffer in specificed size.
+ The max size of this PCD's value is described in PCD's definition in DEC file.
+
+ @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
+ @param CurrentSize Maxmium size of PCD's value
+ @param Database Pcd database in PEI phase.
+
+ @retval TRUE Success to set PCD's value size, which is not exceed maxmium size
+ @retval FALSE Fail to set PCD's value size, which maybe exceed maxmium size
+
+**/
+BOOLEAN
+SetPtrTypeSize (
+ IN UINTN LocalTokenNumberTableIdx,
+ IN OUT UINTN *CurrentSize,
+ IN PEI_PCD_DATABASE *Database
+ );
+
+#endif
+