diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c')
-rw-r--r-- | roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c | 1901 |
1 files changed, 1901 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c new file mode 100644 index 000000000..ea7edc3cb --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/PCD/Dxe/Service.c @@ -0,0 +1,1901 @@ +/** @file
+ Help functions used by PCD DXE driver.
+
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<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);
+ }
+}
+
|