diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe')
6 files changed, 5128 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Pcd.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Pcd.c new file mode 100644 index 00000000..ee3ec2b5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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.<BR> +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/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf new file mode 100644 index 00000000..c4112296 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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.<BR> +# +# 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/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/PcdDxe.uni new file mode 100644 index 00000000..6a3b3db4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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.<BR>
+//
+// 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/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/PcdDxeExtra.uni new file mode 100644 index 00000000..b9d12be6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Platform Configuration Database DXE Driver"
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Service.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Service.c new file mode 100644 index 00000000..4d7a9505 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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.<BR> +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Service.h" +#include <Library/DxeServicesLib.h> + +PCD_DATABASE mPcdDatabase; + +UINT32 mPcdTotalTokenCount; +UINT32 mPeiLocalTokenCount; +UINT32 mDxeLocalTokenCount; +UINT32 mPeiNexTokenCount; +UINT32 mDxeNexTokenCount; +UINT32 mPeiExMapppingTableSize; +UINT32 mDxeExMapppingTableSize; +UINT32 mPeiGuidTableSize; +UINT32 mDxeGuidTableSize; + +BOOLEAN mPeiExMapTableEmpty; +BOOLEAN mDxeExMapTableEmpty; +BOOLEAN mPeiDatabaseEmpty; + +LIST_ENTRY *mCallbackFnTable; +EFI_GUID **TmpTokenSpaceBuffer; +UINTN TmpTokenSpaceBufferCount; + +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/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Service.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PCD/Dxe/Service.h new file mode 100644 index 00000000..dda26e4d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCD_DXE_SERVICE_H_ +#define _PCD_DXE_SERVICE_H_ + +#include <PiDxe.h> +#include <Guid/PcdDataBaseHobGuid.h> +#include <Guid/PcdDataBaseSignatureGuid.h> +#include <Protocol/Pcd.h> +#include <Protocol/PiPcd.h> +#include <Protocol/PcdInfo.h> +#include <Protocol/PiPcdInfo.h> +#include <Protocol/VarCheck.h> +#include <Protocol/VariableLock.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/PcdLib.h> +#include <Library/HobLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> + +// +// Please make sure the PCD Serivce DXE Version is consistent with +// the version of the generated DXE PCD Database by build tool. +// +#define PCD_SERVICE_DXE_VERSION 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 + |