From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c | 1378 ++++++++++++++ roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf | 349 ++++ .../edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni | 291 +++ .../MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni | 14 + roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c | 1901 ++++++++++++++++++++ roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.h | 1195 ++++++++++++ roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c | 1672 +++++++++++++++++ roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf | 351 ++++ .../MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni | 290 +++ .../Universal/PCD/Pei/PcdPeimExtra.uni | 14 + roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.c | 1081 +++++++++++ roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.h | 1082 +++++++++++ 12 files changed, 9618 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.h create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.c create mode 100644 roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.h (limited to 'roms/edk2/MdeModulePkg/Universal/PCD') diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c new file mode 100644 index 000000000..cdb9b4fac --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c @@ -0,0 +1,1378 @@ +/** @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 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#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; +UINTN mVpdBaseAddress = 0; + +/** + 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 + ); + + // + // Cache VpdBaseAddress in entry point for the following usage. + // + + // + // PcdVpdBaseAddress64 is DynamicEx PCD only. So, DxePcdGet64Ex() is used to get its value. + // + mVpdBaseAddress = (UINTN) DxePcdGet64Ex (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdVpdBaseAddress64)); + if (mVpdBaseAddress == 0) { + // + // PcdVpdBaseAddress64 is not set, get value from PcdVpdBaseAddress. + // + mVpdBaseAddress = (UINTN) PcdGet32 (PcdVpdBaseAddress); + } + + 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; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "PcdDxe - SkuId 0x%lx is to be set.\n", (SKU_ID) SkuId)); + + if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) { + // + // The input SKU Id is equal to current SKU Id, return directly. + // + DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is same to current system Sku.\n")); + 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 ((DEBUG_INFO, "PcdDxe - SkuId is found in SkuId table.\n")); + Status = UpdatePcdDatabase (SkuId, TRUE); + if (!EFI_ERROR (Status)) { + mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID) SkuId; + DEBUG ((DEBUG_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId)); + return; + } + } + } + + // + // Invalid input SkuId, the default SKU Id will be still used for the system. + // + DEBUG ((DEBUG_ERROR, "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 + ) +{ + // + // PcdSetNvStoreDefaultId should be set in PEI phase to take effect. + // + ASSERT (!(CompareGuid (Guid, &gEfiMdeModulePkgTokenSpaceGuid) && + (ExTokenNumber == PcdToken(PcdSetNvStoreDefaultId)))); + 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); + TmpTokenSpaceBufferCount = 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/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf new file mode 100644 index 000000000..eb9f757f1 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf @@ -0,0 +1,349 @@ +## @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 PCD setting - PcdVpdBaseAddress64 or 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_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 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[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 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. + gEfiMdeModulePkgTokenSpaceGuid ## SOMETIMES_CONSUMES ## GUID + +[Protocols] + gPcdProtocolGuid ## PRODUCES + gEfiPcdProtocolGuid ## PRODUCES + gGetPcdInfoProtocolGuid ## SOMETIMES_PRODUCES + gEfiGetPcdInfoProtocolGuid ## SOMETIMES_PRODUCES + ## NOTIFY + ## SOMETIMES_CONSUMES + gEdkiiVariableLockProtocolGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64 ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId ## SOMETIMES_CONSUMES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + PcdDxeExtra.uni diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni new file mode 100644 index 000000000..6a3b3db4c --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni @@ -0,0 +1,291 @@ +// /** @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_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 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#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/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni new file mode 100644 index 000000000..b9d12be63 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni @@ -0,0 +1,14 @@ +// /** @file +// PcdDxe Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Platform Configuration Database DXE Driver" + + diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c new file mode 100644 index 000000000..ea7edc3cb --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c @@ -0,0 +1,1901 @@ +/** @file + Help functions used by PCD DXE driver. + +Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Service.h" +#include + +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; + +UINTN mPeiPcdDbSize = 0; +PEI_PCD_DATABASE *mPeiPcdDbBinary = NULL; +UINTN mDxePcdDbSize = 0; +DXE_PCD_DATABASE *mDxePcdDbBinary = NULL; + +/** + 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 + ) +{ + UINT32 *LocalTokenNumberTable; + + // + // 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--; + + LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset) : + (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset); + TokenNumber = IsPeiDb ? TokenNumber : TokenNumber - mPeiLocalTokenCount; + + return LocalTokenNumberTable[TokenNumber]; +} + +/** + 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); + ASSERT (mVpdBaseAddress != 0); + RetPtr = (VOID *) (mVpdBaseAddress + 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 +) +{ + EFI_STATUS Status; + + // + // Search the External Pcd database from one section of current FFS, + // and read it to memory + // + Status = GetSectionFromFfs ( + EFI_SECTION_RAW, + 0, + (VOID **) &mDxePcdDbBinary, + &mDxePcdDbSize + ); + ASSERT_EFI_ERROR (Status); + + // + // Check the first bytes (Header Signature Guid) and build version. + // + if (!CompareGuid ((VOID *)mDxePcdDbBinary, &gPcdDataBaseSignatureGuid) || + (mDxePcdDbBinary->BuildVersion != PCD_SERVICE_DXE_VERSION)) { + ASSERT (FALSE); + } + + return mDxePcdDbBinary; +} + +/** + Update PCD database base on current SkuId + + @param SkuId Current SkuId + @param IsPeiDb Whether to update PEI PCD database. + + @retval EFI_SUCCESS Update PCD database successfully. + @retval EFI_NOT_FOUND Not found PCD database for current SkuId. +**/ +EFI_STATUS +UpdatePcdDatabase ( + IN SKU_ID SkuId, + IN BOOLEAN IsPeiDb + ) +{ + UINTN Index; + PCD_DATABASE_SKU_DELTA *SkuDelta; + PCD_DATA_DELTA *SkuDeltaData; + + if (IsPeiDb && mPeiPcdDbBinary != NULL) { + // + // Find the delta data for PEI DB + // + Index = (mPcdDatabase.PeiDb->Length + 7) & (~7); + SkuDelta = NULL; + while (Index < mPeiPcdDbSize) { + SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) mPeiPcdDbBinary + Index); + if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) { + break; + } + Index = (Index + SkuDelta->Length + 7) & (~7); + } + + // + // Patch the delta data into current PCD database + // + if (Index < mPeiPcdDbSize && SkuDelta != NULL) { + SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1); + while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) { + *((UINT8 *) mPcdDatabase.PeiDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value; + SkuDeltaData ++; + } + } else { + return EFI_NOT_FOUND; + } + } + + // + // Find the delta data for DXE DB + // + Index = (mPcdDatabase.DxeDb->Length + 7) & (~7); + SkuDelta = NULL; + while (Index < mDxePcdDbSize) { + SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) mDxePcdDbBinary + Index); + if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) { + break; + } + Index = (Index + SkuDelta->Length + 7) & (~7); + } + + // + // Patch the delta data into current PCD database + // + if (Index < mDxePcdDbSize && SkuDelta != NULL) { + SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1); + while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) { + *((UINT8 *) mPcdDatabase.DxeDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value; + SkuDeltaData ++; + } + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +/** + 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; + EFI_STATUS Status; + + // + // 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); + 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); + + // + // Get next one that stores full PEI data + // + GuidHob = GetNextGuidHob (&gPcdDataBaseHobGuid, GET_NEXT_HOB (GuidHob)); + if (GuidHob != NULL) { + mPeiPcdDbBinary = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob); + mPeiPcdDbSize = (UINTN) GET_GUID_HOB_DATA_SIZE (GuidHob); + } + + // + // Assign PCD Entries refereneced in PEI phase to PCD DATABASE + // + mPcdDatabase.PeiDb = PeiDatabase; + // + // Inherit the SystemSkuId from PEI phase. + // + if (mPcdDatabase.PeiDb->SystemSkuId != 0) { + Status = UpdatePcdDatabase (mPcdDatabase.PeiDb->SystemSkuId, FALSE); + ASSERT_EFI_ERROR (Status); + } + 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; +} + +/** + 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; +} + +/** + 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; + + 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 { + // + // We have only two entry for Non-Sku enabled PCD entry: + // 1) MAX SIZE + // 2) Current Size + // + SizeTableIdx += 2; + } + } + + } + + 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; + SIZE_INFO *SizeTable; + 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 { + // + // We have only two entry for Non-Sku enabled PCD entry: + // 1) MAX SIZE + // 2) Current Size + // + 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; + SIZE_INFO *SizeTable; + 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; + } + + // + // 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; + } +} + +/** + 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/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.h b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.h new file mode 100644 index 000000000..6109458ca --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.h @@ -0,0 +1,1195 @@ +/** @file +Private functions used by PCD DXE driver. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCD_DXE_SERVICE_H_ +#define _PCD_DXE_SERVICE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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 7 + +// +// 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 + +extern UINTN mVpdBaseAddress; + +/** + 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 + ); + +/** + 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 + ); + +/** + Update PCD database base on current SkuId + + @param SkuId Current SkuId + @param IsPeiDb Whether to update PEI PCD database. + + @retval EFI_SUCCESS Update PCD database successfully. + @retval EFI_NOT_FOUND Not found PCD database for current SkuId. +**/ +EFI_STATUS +UpdatePcdDatabase ( + IN SKU_ID SkuId, + IN BOOLEAN IsPeiDb + ); + +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/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c new file mode 100644 index 000000000..9c6346924 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c @@ -0,0 +1,1672 @@ +/** @file + All Pcd Ppi services are implemented here. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#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 + } +}; + +/** + Callback on SET PcdSetNvStoreDefaultId + + Once PcdSetNvStoreDefaultId is set, the default NV storage will be found from + PcdNvStoreDefaultValueBuffer, and built into VariableHob. + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in, out] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + +**/ +VOID +EFIAPI +PcdSetNvStoreDefaultIdCallBack ( + IN CONST EFI_GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN OUT VOID *TokenData, + IN UINTN TokenDataSize + ) +{ + EFI_STATUS Status; + UINT16 DefaultId; + SKU_ID SkuId; + UINTN FullSize; + UINTN Index; + UINT8 *DataBuffer; + UINT8 *VarStoreHobData; + UINT8 *BufferEnd; + BOOLEAN IsFound; + VARIABLE_STORE_HEADER *NvStoreBuffer; + PCD_DEFAULT_DATA *DataHeader; + PCD_DEFAULT_INFO *DefaultInfo; + PCD_DATA_DELTA *DeltaData; + + DefaultId = *(UINT16 *) TokenData; + SkuId = GetPcdDatabase()->SystemSkuId; + IsFound = FALSE; + + if (PeiPcdGetSizeEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer)) > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) { + DataBuffer = (UINT8 *) PeiPcdGetPtrEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer)); + FullSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *) DataBuffer)->Length; + DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)); + // + // The first section data includes NV storage default setting. + // + NvStoreBuffer = (VARIABLE_STORE_HEADER *) ((UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize); + VarStoreHobData = (UINT8 *) BuildGuidHob (&NvStoreBuffer->Signature, NvStoreBuffer->Size); + ASSERT (VarStoreHobData != NULL); + CopyMem (VarStoreHobData, NvStoreBuffer, NvStoreBuffer->Size); + // + // Find the matched SkuId and DefaultId in the first section + // + DefaultInfo = &(DataHeader->DefaultInfo[0]); + BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize; + while ((UINT8 *) DefaultInfo < BufferEnd) { + if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == SkuId) { + IsFound = TRUE; + break; + } + DefaultInfo ++; + } + // + // Find the matched SkuId and DefaultId in the remaining section + // + Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7)); + DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index); + while (!IsFound && Index < FullSize && DataHeader->DataSize != 0xFFFFFFFF) { + DefaultInfo = &(DataHeader->DefaultInfo[0]); + BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize; + while ((UINT8 *) DefaultInfo < BufferEnd) { + if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == SkuId) { + IsFound = TRUE; + break; + } + DefaultInfo ++; + } + if (IsFound) { + DeltaData = (PCD_DATA_DELTA *) BufferEnd; + BufferEnd = (UINT8 *) DataHeader + DataHeader->DataSize; + while ((UINT8 *) DeltaData < BufferEnd) { + *(VarStoreHobData + DeltaData->Offset) = (UINT8) DeltaData->Value; + DeltaData ++; + } + break; + } + Index = (Index + DataHeader->DataSize + 7) & (~7) ; + DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index); + } + } + + Status = PcdUnRegisterCallBackOnSet ( + &gEfiMdeModulePkgTokenSpaceGuid, + PcdToken(PcdSetNvStoreDefaultId), + PcdSetNvStoreDefaultIdCallBack + ); + ASSERT_EFI_ERROR (Status); +} + +/** + Report Pei PCD database of all SKUs as Guid HOB so that DxePcd can access it. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS Successfully update the Boot records. +**/ +EFI_STATUS +EFIAPI +EndOfPeiSignalPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + PEI_PCD_DATABASE *Database; + EFI_BOOT_MODE BootMode; + EFI_STATUS Status; + UINTN Instance; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + VOID *PcdDb; + UINT32 Length; + PEI_PCD_DATABASE *PeiPcdDb; + + Status = PeiServicesGetBootMode(&BootMode); + ASSERT_EFI_ERROR (Status); + + // + // Don't need to report it on S3 boot. + // + if (BootMode == BOOT_ON_S3_RESUME) { + return EFI_SUCCESS; + } + + PeiPcdDb = GetPcdDatabase(); + if (PeiPcdDb->SystemSkuId != (SKU_ID) 0) { + // + // SkuId has been set. Don't need to report it to DXE phase. + // + return EFI_SUCCESS; + } + + // + // Get full PCD database from PcdPeim FileHandle + // + Instance = 0; + FileHandle = NULL; + while (TRUE) { + // + // Traverse all firmware volume instances + // + Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle); + // + // Error should not happen + // + ASSERT_EFI_ERROR (Status); + + // + // Find PcdDb file from the beginning in this firmware volume. + // + FileHandle = NULL; + Status = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle); + if (!EFI_ERROR (Status)) { + // + // Find PcdPeim FileHandle in this volume + // + break; + } + // + // We cannot find PcdPeim in this firmware volume, then search the next volume. + // + Instance++; + } + + // + // Find PEI PcdDb and Build second PcdDB GuidHob + // + Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb); + ASSERT_EFI_ERROR (Status); + Length = PeiPcdDb->LengthForAllSkus; + Database = BuildGuidHob (&gPcdDataBaseHobGuid, Length); + CopyMem (Database, PcdDb, Length); + + return EFI_SUCCESS; +} + +EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + EndOfPeiSignalPpiNotifyCallback + } +}; + +/** + 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); + + Status = PeiServicesNotifyPpi (&mEndOfPeiSignalPpiNotifyList[0]); + ASSERT_EFI_ERROR (Status); + + Status = PeiRegisterCallBackOnSet ( + &gEfiMdeModulePkgTokenSpaceGuid, + PcdToken(PcdSetNvStoreDefaultId), + PcdSetNvStoreDefaultIdCallBack + ); + 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; + EFI_STATUS Status; + UINTN Instance; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + VOID *PcdDb; + UINT32 Length; + PCD_DATABASE_SKU_DELTA *SkuDelta; + PCD_DATA_DELTA *SkuDeltaData; + + DEBUG ((DEBUG_INFO, "PcdPei - SkuId 0x%lx is to be set.\n", (SKU_ID) SkuId)); + + PeiPcdDb = GetPcdDatabase(); + + if (SkuId == PeiPcdDb->SystemSkuId) { + // + // The input SKU Id is equal to current SKU Id, return directly. + // + DEBUG ((DEBUG_INFO, "PcdPei - SkuId is same to current system Sku.\n")); + 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 ((DEBUG_INFO, "PcdPei - SkuId is found in SkuId table.\n")); + break; + } + } + + if (Index < SkuIdTable[0]) { + // + // Get full PCD database from PcdPeim FileHandle + // + Instance = 0; + FileHandle = NULL; + while (TRUE) { + // + // Traverse all firmware volume instances + // + Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle); + // + // Error should not happen + // + ASSERT_EFI_ERROR (Status); + + // + // Find PcdDb file from the beginning in this firmware volume. + // + FileHandle = NULL; + Status = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle); + if (!EFI_ERROR (Status)) { + // + // Find PcdPeim FileHandle in this volume + // + break; + } + // + // We cannot find PcdPeim in this firmware volume, then search the next volume. + // + Instance++; + } + + // + // Find the delta data between the different Skus + // + Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb); + ASSERT_EFI_ERROR (Status); + Length = PeiPcdDb->LengthForAllSkus; + Index = (PeiPcdDb->Length + 7) & (~7); + SkuDelta = NULL; + while (Index < Length) { + SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) PcdDb + Index); + if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) { + break; + } + Index = (Index + SkuDelta->Length + 7) & (~7); + } + + // + // Patch the delta data into current PCD database + // + if (Index < Length && SkuDelta != NULL) { + SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1); + while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) { + *((UINT8 *) PeiPcdDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value; + SkuDeltaData ++; + } + PeiPcdDb->SystemSkuId = (SKU_ID) SkuId; + DEBUG ((DEBUG_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId)); + return; + } + } + + // + // Invalid input SkuId, the default SKU Id will be still used for the system. + // + DEBUG ((DEBUG_ERROR, "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; + SIZE_INFO *SizeTable; + + 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 { + // + // We have only two entry for Non-Sku enabled PCD entry: + // 1) MAX SIZE + // 2) Current Size + // + 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; + SIZE_INFO *SizeTable; + 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; + } + + // + // 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; + } + +} diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf new file mode 100644 index 000000000..7152a7d53 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf @@ -0,0 +1,351 @@ +## @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 PCD setting - PcdVpdBaseAddress64 or 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_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 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[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 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. + gEfiMdeModulePkgTokenSpaceGuid ## SOMETIMES_CONSUMES ## GUID + +[Ppis] + gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES + gPcdPpiGuid ## PRODUCES + gEfiPeiPcdPpiGuid ## PRODUCES + gGetPcdInfoPpiGuid ## SOMETIMES_PRODUCES + gEfiGetPcdInfoPpiGuid ## SOMETIMES_PRODUCES + gEfiEndOfPeiSignalPpiGuid ## NOTIFY + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiFullPcdDatabaseEnable ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64 ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId ## CONSUMES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + PcdPeimExtra.uni diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni new file mode 100644 index 000000000..0a800889a --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeim.uni @@ -0,0 +1,290 @@ +// /** @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_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 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#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/roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni new file mode 100644 index 000000000..1e47f0e79 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/PcdPeimExtra.uni @@ -0,0 +1,14 @@ +// /** @file +// PcdPeim Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Platform Configuration Database PEI Module" + + diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.c b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.c new file mode 100644 index 000000000..5b037353a --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.c @@ -0,0 +1,1081 @@ +/** @file + The driver internal functions are implmented here. + They build Pei PCD database, and provide access service to PCD database. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#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; + + // + // 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); + + 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; +} + +/** + 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; + UINTN VpdBaseAddress; + + // + // 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); + + // + // PcdVpdBaseAddress64 is DynamicEx PCD only. So, PeiPcdGet64Ex() is used to get its value. + // + VpdBaseAddress = (UINTN) PeiPcdGet64Ex (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdVpdBaseAddress64)); + if (VpdBaseAddress == 0) { + // + // PcdVpdBaseAddress64 is not set, get value from PcdVpdBaseAddress. + // + VpdBaseAddress = (UINTN) PcdGet32 (PcdVpdBaseAddress); + } + ASSERT (VpdBaseAddress != 0); + return (VOID *)(VpdBaseAddress + 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 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; + + 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 { + // + // We have only two entry for Non-Sku enabled PCD entry: + // 1) MAX SIZE + // 2) Current Size + // + SizeTableIdx += 2; + } + } + + } + + return SizeTableIdx; +} diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.h b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.h new file mode 100644 index 000000000..547094fe8 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Pei/Service.h @@ -0,0 +1,1082 @@ +/** @file + The internal header file declares the private functions used by PeiPcd driver. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PEI_PCD_SERVICE_H_ +#define _PEI_PCD_SERVICE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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 7 + +// +// 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 + ); + +/** + 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 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 + -- cgit