2 Help functions used by PCD DXE driver.
4 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/DxeServicesLib.h>
19 PCD_DATABASE mPcdDatabase
;
21 UINT32 mPcdTotalTokenCount
;
22 UINT32 mPeiLocalTokenCount
;
23 UINT32 mDxeLocalTokenCount
;
24 UINT32 mPeiNexTokenCount
;
25 UINT32 mDxeNexTokenCount
;
26 UINT32 mPeiExMapppingTableSize
;
27 UINT32 mDxeExMapppingTableSize
;
28 UINT32 mPeiGuidTableSize
;
29 UINT32 mDxeGuidTableSize
;
31 BOOLEAN mPeiExMapTableEmpty
;
32 BOOLEAN mDxeExMapTableEmpty
;
33 BOOLEAN mPeiDatabaseEmpty
;
35 LIST_ENTRY
*mCallbackFnTable
;
36 EFI_GUID
**TmpTokenSpaceBuffer
;
37 UINTN TmpTokenSpaceBufferCount
;
40 Get Local Token Number by Token Number.
42 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
43 If FALSE, the pcd entry is initialized in DXE phase.
44 @param[in] TokenNumber The PCD token number.
46 @return Local Token Number.
55 UINT32
*LocalTokenNumberTable
;
56 UINT32 LocalTokenNumber
;
61 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
62 // We have to decrement TokenNumber by 1 to make it usable
63 // as the array index.
68 // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
70 TmpTokenNumber
= TokenNumber
;
72 LocalTokenNumberTable
= IsPeiDb
? (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
) :
73 (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
74 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
76 LocalTokenNumber
= LocalTokenNumberTable
[TokenNumber
];
78 Size
= (LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) >> PCD_DATUM_TYPE_SHIFT
;
80 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
82 GetPtrTypeSize (TmpTokenNumber
, &MaxSize
);
86 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
, IsPeiDb
);
89 return LocalTokenNumber
;
93 Get PCD type by Local Token Number.
95 @param[in] LocalTokenNumber The PCD local token number.
101 IN UINT32 LocalTokenNumber
104 switch (LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) {
105 case PCD_DATUM_TYPE_POINTER
:
106 return EFI_PCD_TYPE_PTR
;
107 case PCD_DATUM_TYPE_UINT8
:
108 if ((LocalTokenNumber
& PCD_DATUM_TYPE_UINT8_BOOLEAN
) == PCD_DATUM_TYPE_UINT8_BOOLEAN
) {
109 return EFI_PCD_TYPE_BOOL
;
111 return EFI_PCD_TYPE_8
;
113 case PCD_DATUM_TYPE_UINT16
:
114 return EFI_PCD_TYPE_16
;
115 case PCD_DATUM_TYPE_UINT32
:
116 return EFI_PCD_TYPE_32
;
117 case PCD_DATUM_TYPE_UINT64
:
118 return EFI_PCD_TYPE_64
;
121 return EFI_PCD_TYPE_8
;
128 @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.
129 If FALSE, need to get the full PCD name.
130 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
131 If FALSE, the pcd entry is initialized in DXE phase.
132 @param[in] TokenNumber The PCD token number.
134 @return The TokenSpaceCName or full PCD name.
138 IN BOOLEAN OnlyTokenSpaceName
,
143 PCD_DATABASE_INIT
*Database
;
145 PCD_NAME_INDEX
*PcdNameIndex
;
146 CHAR8
*TokenSpaceName
;
151 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
152 // We have to decrement TokenNumber by 1 to make it usable
153 // as the array index.
157 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
158 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
160 StringTable
= (UINT8
*) Database
+ Database
->StringTableOffset
;
163 // Get the PCD name index.
165 PcdNameIndex
= (PCD_NAME_INDEX
*)((UINT8
*) Database
+ Database
->PcdNameTableOffset
) + TokenNumber
;
166 TokenSpaceName
= (CHAR8
*)&StringTable
[PcdNameIndex
->TokenSpaceCNameIndex
];
167 PcdName
= (CHAR8
*)&StringTable
[PcdNameIndex
->PcdCNameIndex
];
169 if (OnlyTokenSpaceName
) {
171 // Only need to get the TokenSpaceCName.
173 Name
= AllocateCopyPool (AsciiStrSize (TokenSpaceName
), TokenSpaceName
);
176 // Need to get the full PCD name.
178 Name
= AllocateZeroPool (AsciiStrSize (TokenSpaceName
) + AsciiStrSize (PcdName
));
179 ASSERT (Name
!= NULL
);
181 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
183 AsciiStrCat (Name
, TokenSpaceName
);
184 Name
[AsciiStrSize (TokenSpaceName
) - sizeof (CHAR8
)] = '.';
185 AsciiStrCat (Name
, PcdName
);
192 Retrieve additional information associated with a PCD token.
194 This includes information such as the type of value the TokenNumber is associated with as well as possible
195 human readable name that is associated with the token.
197 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
198 If FALSE, the pcd entry is initialized in DXE phase.
199 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
200 @param[in] TokenNumber The PCD token number.
201 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
202 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
204 @retval EFI_SUCCESS The PCD information was returned successfully
205 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
210 IN CONST EFI_GUID
*Guid
,
211 IN UINTN TokenNumber
,
212 OUT EFI_PCD_INFO
*PcdInfo
215 PCD_DATABASE_INIT
*Database
;
219 DYNAMICEX_MAPPING
*ExMapTable
;
221 UINT32 LocalTokenNumber
;
223 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
225 GuidTable
= (EFI_GUID
*)((UINT8
*)Database
+ Database
->GuidTableOffset
);
226 MatchGuid
= ScanGuid (GuidTable
, Database
->GuidTableCount
* sizeof(EFI_GUID
), Guid
);
228 if (MatchGuid
== NULL
) {
229 return EFI_NOT_FOUND
;
232 GuidTableIdx
= MatchGuid
- GuidTable
;
234 ExMapTable
= (DYNAMICEX_MAPPING
*)((UINT8
*)Database
+ Database
->ExMapTableOffset
);
237 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
239 for (Index
= 0; Index
< Database
->ExTokenCount
; Index
++) {
240 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
241 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
243 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
244 // PcdSize to 0 and PcdName to the null-terminated ASCII string
245 // associated with the token's namespace Guid.
247 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
248 PcdInfo
->PcdSize
= 0;
250 // Here use one representative in the token space to get the TokenSpaceCName.
252 PcdInfo
->PcdName
= GetPcdName (TRUE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
254 } else if (ExMapTable
[Index
].ExTokenNumber
== TokenNumber
) {
255 PcdInfo
->PcdSize
= DxePcdGetSize (ExMapTable
[Index
].TokenNumber
);
256 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
257 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
258 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
264 return EFI_NOT_FOUND
;
268 Retrieve additional information associated with a PCD token.
270 This includes information such as the type of value the TokenNumber is associated with as well as possible
271 human readable name that is associated with the token.
273 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
274 @param[in] TokenNumber The PCD token number.
275 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
276 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
278 @retval EFI_SUCCESS The PCD information was returned successfully.
279 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
283 IN CONST EFI_GUID
*Guid
,
284 IN UINTN TokenNumber
,
285 OUT EFI_PCD_INFO
*PcdInfo
289 BOOLEAN PeiExMapTableEmpty
;
290 BOOLEAN DxeExMapTableEmpty
;
291 UINT32 LocalTokenNumber
;
294 ASSERT (PcdInfo
!= NULL
);
296 Status
= EFI_NOT_FOUND
;
297 PeiExMapTableEmpty
= mPeiExMapTableEmpty
;
298 DxeExMapTableEmpty
= mDxeExMapTableEmpty
;
301 if (((TokenNumber
+ 1 > mPeiNexTokenCount
+ 1) && (TokenNumber
+ 1 <= mPeiLocalTokenCount
+ 1)) ||
302 ((TokenNumber
+ 1 > (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1)))) {
303 return EFI_NOT_FOUND
;
304 } else if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
306 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
307 // PcdSize to 0 and PcdName to NULL for default Token Space.
309 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
310 PcdInfo
->PcdSize
= 0;
311 PcdInfo
->PcdName
= NULL
;
313 PcdInfo
->PcdSize
= DxePcdGetSize (TokenNumber
);
315 if ((TokenNumber
+ 1 <= mPeiNexTokenCount
+ 1)) {
318 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
);
319 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
320 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, TokenNumber
);
325 if (PeiExMapTableEmpty
&& DxeExMapTableEmpty
) {
326 return EFI_NOT_FOUND
;
329 if (!PeiExMapTableEmpty
) {
330 Status
= ExGetPcdInfo (
338 if (Status
== EFI_SUCCESS
) {
342 if (!DxeExMapTableEmpty
) {
343 Status
= ExGetPcdInfo (
355 Get the PCD entry pointer in PCD database.
357 This routine will visit PCD database to find the PCD entry according to given
358 token number. The given token number is autogened by build tools and it will be
359 translated to local token number. Local token number contains PCD's type and
360 offset of PCD entry in PCD database.
362 @param TokenNumber Token's number, it is autogened by build tools
363 @param GetSize The size of token's value
365 @return PCD entry pointer in PCD database
370 IN UINTN TokenNumber
,
378 VARIABLE_HEAD
*VariableHead
;
379 UINT8
*VaraiableDefaultBuffer
;
384 UINTN TmpTokenNumber
;
387 UINT32 LocalTokenNumber
;
389 STRING_HEAD StringTableIdx
;
393 // Aquire lock to prevent reentrance from TPL_CALLBACK level
395 EfiAcquireLock (&mPcdDatabaseLock
);
399 ASSERT (TokenNumber
> 0);
401 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
402 // We have to decrement TokenNumber by 1 to make it usable
403 // as the array index.
407 TmpTokenNumber
= TokenNumber
;
410 // EBC compiler is very choosy. It may report warning about comparison
411 // between UINTN and 0 . So we add 1 in each size of the
414 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
416 ASSERT ((GetSize
== DxePcdGetSize (TokenNumber
+ 1)) || (GetSize
== 0));
418 // EBC compiler is very choosy. It may report warning about comparison
419 // between UINTN and 0 . So we add 1 in each size of the
421 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
423 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
425 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
428 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
430 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
434 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
436 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
438 VpdHead
= (VPD_HEAD
*) ((UINT8
*) PcdDb
+ Offset
);
439 RetPtr
= (VOID
*) (UINTN
) (PcdGet32 (PcdVpdBaseAddress
) + VpdHead
->Offset
);
443 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
446 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
448 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
451 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
452 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
453 Name
= (UINT16
*)(StringTable
+ VariableHead
->StringIndex
);
455 if ((LocalTokenNumber
& PCD_TYPE_ALL_SET
) == (PCD_TYPE_HII
|PCD_TYPE_STRING
)) {
457 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
458 // string array in string table.
460 StringTableIdx
= *(STRING_HEAD
*)((UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
);
461 VaraiableDefaultBuffer
= (UINT8
*) (StringTable
+ StringTableIdx
);
463 VaraiableDefaultBuffer
= (UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
;
465 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
466 if (Status
== EFI_SUCCESS
) {
467 if (DataSize
>= (VariableHead
->Offset
+ GetSize
)) {
470 // It is a pointer type. So get the MaxSize reserved for
473 GetPtrTypeSize (TmpTokenNumber
, &GetSize
);
474 if (GetSize
> (DataSize
- VariableHead
->Offset
)) {
476 // Use actual valid size.
478 GetSize
= DataSize
- VariableHead
->Offset
;
482 // If the operation is successful, we copy the data
483 // to the default value buffer in the PCD Database.
484 // So that we can free the Data allocated in GetHiiVariable.
486 CopyMem (VaraiableDefaultBuffer
, Data
+ VariableHead
->Offset
, GetSize
);
490 RetPtr
= (VOID
*) VaraiableDefaultBuffer
;
493 case PCD_TYPE_STRING
:
494 StringTableIdx
= *(STRING_HEAD
*)((UINT8
*) PcdDb
+ Offset
);
495 RetPtr
= (VOID
*) (StringTable
+ StringTableIdx
);
499 RetPtr
= (VOID
*) ((UINT8
*) PcdDb
+ Offset
);
508 EfiReleaseLock (&mPcdDatabaseLock
);
515 Register the callback function for a PCD entry.
517 This routine will register a callback function to a PCD entry by given token number
518 and token space guid.
520 @param TokenNumber PCD token's number, it is autogened by build tools.
521 @param Guid PCD token space's guid,
522 if not NULL, this PCD is dynamicEx type PCD.
523 @param CallBackFunction Callback function pointer
525 @return EFI_SUCCESS Always success for registering callback function.
529 DxeRegisterCallBackWorker (
530 IN UINTN TokenNumber
,
531 IN CONST EFI_GUID
*Guid
, OPTIONAL
532 IN PCD_PROTOCOL_CALLBACK CallBackFunction
535 CALLBACK_FN_ENTRY
*FnTableEntry
;
536 LIST_ENTRY
*ListHead
;
537 LIST_ENTRY
*ListNode
;
540 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
544 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
545 // We have to decrement TokenNumber by 1 to make it usable
546 // as the array index of mCallbackFnTable[].
548 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
549 ListNode
= GetFirstNode (ListHead
);
551 while (ListNode
!= ListHead
) {
552 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
554 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
556 // We only allow a Callback function to be register once
557 // for a TokenNumber. So just return EFI_SUCCESS
561 ListNode
= GetNextNode (ListHead
, ListNode
);
564 FnTableEntry
= AllocatePool (sizeof(CALLBACK_FN_ENTRY
));
565 ASSERT (FnTableEntry
!= NULL
);
567 FnTableEntry
->CallbackFn
= CallBackFunction
;
568 InsertTailList (ListHead
, &FnTableEntry
->Node
);
574 UnRegister the callback function for a PCD entry.
576 This routine will unregister a callback function to a PCD entry by given token number
577 and token space guid.
579 @param TokenNumber PCD token's number, it is autogened by build tools.
580 @param Guid PCD token space's guid.
581 if not NULL, this PCD is dynamicEx type PCD.
582 @param CallBackFunction Callback function pointer
584 @retval EFI_SUCCESS Callback function is success to be unregister.
585 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.
588 DxeUnRegisterCallBackWorker (
589 IN UINTN TokenNumber
,
590 IN CONST EFI_GUID
*Guid
, OPTIONAL
591 IN PCD_PROTOCOL_CALLBACK CallBackFunction
594 CALLBACK_FN_ENTRY
*FnTableEntry
;
595 LIST_ENTRY
*ListHead
;
596 LIST_ENTRY
*ListNode
;
599 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
603 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
604 // We have to decrement TokenNumber by 1 to make it usable
605 // as the array index of mCallbackFnTable[].
607 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
608 ListNode
= GetFirstNode (ListHead
);
610 while (ListNode
!= ListHead
) {
611 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
613 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
615 // We only allow a Callback function to be register once
616 // for a TokenNumber. So we can safely remove the Node from
617 // the Link List and return EFI_SUCCESS.
619 RemoveEntryList (ListNode
);
620 FreePool (FnTableEntry
);
624 ListNode
= GetNextNode (ListHead
, ListNode
);
627 return EFI_INVALID_PARAMETER
;
631 Get next token number in given token space.
633 This routine is used for dynamicEx type PCD. It will firstly scan token space
634 table to get token space according to given token space guid. Then scan given
635 token number in found token space, if found, then return next token number in
638 @param Guid Token space guid. Next token number will be scaned in
640 @param TokenNumber Token number.
641 If PCD_INVALID_TOKEN_NUMBER, return first token number in
643 If not PCD_INVALID_TOKEN_NUMBER, return next token number
644 in token space table.
645 @param GuidTable Token space guid table. It will be used for scan token space
646 by given token space guid.
647 @param SizeOfGuidTable The size of guid table.
648 @param ExMapTable DynamicEx token number mapping table.
649 @param SizeOfExMapTable The size of dynamicEx token number mapping table.
651 @retval EFI_NOT_FOUND Can not given token space or token number.
652 @retval EFI_SUCCESS Success to get next token number.
656 ExGetNextTokeNumber (
657 IN CONST EFI_GUID
*Guid
,
658 IN OUT UINTN
*TokenNumber
,
659 IN EFI_GUID
*GuidTable
,
660 IN UINTN SizeOfGuidTable
,
661 IN DYNAMICEX_MAPPING
*ExMapTable
,
662 IN UINTN SizeOfExMapTable
669 UINTN ExMapTableCount
;
672 // Scan token space guid
674 MatchGuid
= ScanGuid (GuidTable
, SizeOfGuidTable
, Guid
);
675 if (MatchGuid
== NULL
) {
676 return EFI_NOT_FOUND
;
680 // Find the token space table in dynamicEx mapping table.
683 GuidTableIdx
= MatchGuid
- GuidTable
;
684 ExMapTableCount
= SizeOfExMapTable
/ sizeof(ExMapTable
[0]);
685 for (Index
= 0; Index
< ExMapTableCount
; Index
++) {
686 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
694 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
695 // token number in found token space.
697 if (*TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
698 *TokenNumber
= ExMapTable
[Index
].ExTokenNumber
;
702 for ( ; Index
< ExMapTableCount
; Index
++) {
703 if (ExMapTable
[Index
].ExTokenNumber
== *TokenNumber
) {
708 while (Index
< ExMapTableCount
) {
710 if (Index
== ExMapTableCount
) {
712 // Exceed the length of ExMap Table
714 *TokenNumber
= PCD_INVALID_TOKEN_NUMBER
;
715 return EFI_NOT_FOUND
;
716 } else if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
718 // Found the next match
720 *TokenNumber
= ExMapTable
[Index
].ExTokenNumber
;
726 return EFI_NOT_FOUND
;
730 Find the PCD database.
732 @retval The base address of external PCD database binary.
733 @retval NULL Return NULL if not find.
740 DXE_PCD_DATABASE
*DxePcdDbBinary
;
744 DxePcdDbBinary
= NULL
;
746 // Search the External Pcd database from one section of current FFS,
747 // and read it to memory
749 Status
= GetSectionFromFfs (
752 (VOID
**) &DxePcdDbBinary
,
755 ASSERT_EFI_ERROR (Status
);
758 // Check the first bytes (Header Signature Guid) and build version.
760 if (!CompareGuid ((VOID
*)DxePcdDbBinary
, &gPcdDataBaseSignatureGuid
) ||
761 (DxePcdDbBinary
->BuildVersion
!= PCD_SERVICE_DXE_VERSION
)) {
765 return DxePcdDbBinary
;
769 Initialize the PCD database in DXE phase.
771 PCD database in DXE phase also contains PCD database in PEI phase which is copied
776 BuildPcdDxeDataBase (
780 PEI_PCD_DATABASE
*PeiDatabase
;
781 EFI_HOB_GUID_TYPE
*GuidHob
;
787 // Assign PCD Entries with default value to PCD DATABASE
789 mPcdDatabase
.DxeDb
= LocateExPcdBinary ();
790 ASSERT(mPcdDatabase
.DxeDb
!= NULL
);
791 PcdDxeDbLen
= mPcdDatabase
.DxeDb
->Length
+ mPcdDatabase
.DxeDb
->UninitDataBaseSize
;
792 PcdDxeDb
= AllocateZeroPool (PcdDxeDbLen
);
793 ASSERT (PcdDxeDb
!= NULL
);
794 CopyMem (PcdDxeDb
, mPcdDatabase
.DxeDb
, mPcdDatabase
.DxeDb
->Length
);
795 FreePool (mPcdDatabase
.DxeDb
);
796 mPcdDatabase
.DxeDb
= PcdDxeDb
;
798 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
799 if (GuidHob
!= NULL
) {
802 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
803 // should not be included at all. So the GuidHob could
804 // be NULL. If it is NULL, we just copy over the DXE Default
805 // Value to PCD Database.
808 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
810 // Assign PCD Entries refereneced in PEI phase to PCD DATABASE
812 mPcdDatabase
.PeiDb
= PeiDatabase
;
814 // Inherit the SystemSkuId from PEI phase.
816 mPcdDatabase
.DxeDb
->SystemSkuId
= mPcdDatabase
.PeiDb
->SystemSkuId
;
818 mPcdDatabase
.PeiDb
= AllocateZeroPool (sizeof (PEI_PCD_DATABASE
));
819 ASSERT(mPcdDatabase
.PeiDb
!= NULL
);
823 // Initialized the external PCD database local variables
825 mPeiLocalTokenCount
= mPcdDatabase
.PeiDb
->LocalTokenCount
;
826 mDxeLocalTokenCount
= mPcdDatabase
.DxeDb
->LocalTokenCount
;
828 mPeiExMapppingTableSize
= mPcdDatabase
.PeiDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
829 mDxeExMapppingTableSize
= mPcdDatabase
.DxeDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
830 mPeiGuidTableSize
= mPcdDatabase
.PeiDb
->GuidTableCount
* sizeof(GUID
);
831 mDxeGuidTableSize
= mPcdDatabase
.DxeDb
->GuidTableCount
* sizeof (GUID
);
833 mPcdTotalTokenCount
= mPeiLocalTokenCount
+ mDxeLocalTokenCount
;
834 mPeiNexTokenCount
= mPeiLocalTokenCount
- mPcdDatabase
.PeiDb
->ExTokenCount
;
835 mDxeNexTokenCount
= mDxeLocalTokenCount
- mPcdDatabase
.DxeDb
->ExTokenCount
;
837 mPeiExMapTableEmpty
= (mPcdDatabase
.PeiDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
838 mDxeExMapTableEmpty
= (mPcdDatabase
.DxeDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
839 mPeiDatabaseEmpty
= (mPeiLocalTokenCount
== 0) ? TRUE
: FALSE
;
841 TmpTokenSpaceBufferCount
= mPcdDatabase
.PeiDb
->ExTokenCount
+ mPcdDatabase
.DxeDb
->ExTokenCount
;
842 TmpTokenSpaceBuffer
= (EFI_GUID
**)AllocateZeroPool(TmpTokenSpaceBufferCount
* sizeof (EFI_GUID
*));
845 // Initialized the Callback Function Table
847 mCallbackFnTable
= AllocateZeroPool (mPcdTotalTokenCount
* sizeof (LIST_ENTRY
));
848 ASSERT(mCallbackFnTable
!= NULL
);
851 // EBC compiler is very choosy. It may report warning about comparison
852 // between UINTN and 0 . So we add 1 in each size of the
855 for (Index
= 0; Index
+ 1 < mPcdTotalTokenCount
+ 1; Index
++) {
856 InitializeListHead (&mCallbackFnTable
[Index
]);
861 Get Variable which contains HII type PCD entry.
863 @param VariableGuid Variable's guid
864 @param VariableName Variable's unicode name string
865 @param VariableData Variable's data pointer,
866 @param VariableSize Variable's size.
868 @return the status of gRT->GetVariable
872 IN EFI_GUID
*VariableGuid
,
873 IN UINT16
*VariableName
,
874 OUT UINT8
**VariableData
,
875 OUT UINTN
*VariableSize
886 // Firstly get the real size of HII variable
888 Status
= gRT
->GetVariable (
889 (UINT16
*)VariableName
,
897 // Allocate buffer to hold whole variable data according to variable size.
899 if (Status
== EFI_BUFFER_TOO_SMALL
) {
900 Buffer
= (UINT8
*) AllocatePool (Size
);
902 ASSERT (Buffer
!= NULL
);
904 Status
= gRT
->GetVariable (
912 ASSERT (Status
== EFI_SUCCESS
);
913 *VariableData
= Buffer
;
914 *VariableSize
= Size
;
917 // Use Default Data only when variable is not found.
918 // For other error status, correct data can't be got, and trig ASSERT().
920 ASSERT (Status
== EFI_NOT_FOUND
);
927 Find the local token number according to system SKU ID.
929 @param LocalTokenNumber PCD token number
930 @param Size The size of PCD entry.
931 @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.
932 If False, the PCD entry is initialized in DXE phase.
934 @return Token number according to system SKU ID.
938 GetSkuEnabledTokenNumber (
939 UINT32 LocalTokenNumber
,
951 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
953 PcdDb
= IsPeiDb
? (UINT8
*) mPcdDatabase
.PeiDb
: (UINT8
*) mPcdDatabase
.DxeDb
;
955 SkuHead
= (SKU_HEAD
*) (PcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
956 Value
= (UINT8
*) (PcdDb
+ SkuHead
->SkuDataStartOffset
);
958 SkuIdTable
= (SKU_ID
*)(PcdDb
+ SkuHead
->SkuIdTableOffset
);
960 // Find the current system's SKU ID entry in SKU ID table.
963 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
964 if (mPcdDatabase
.DxeDb
->SystemSkuId
== SkuIdTable
[Index
+ 1]) {
971 // Find the default SKU ID entry in SKU ID table.
975 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
976 if (0 == SkuIdTable
[Index
+ 1]) {
981 ASSERT (Index
< SkuIdTable
[0]);
983 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
985 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[Index
]);
986 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_VPD
);
989 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[Index
]);
990 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_HII
);
992 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
993 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[Index
]);
994 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_HII
| PCD_TYPE_STRING
);
996 case PCD_TYPE_STRING
:
997 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[Index
]);
998 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_STRING
);
1001 Value
+= Size
* Index
;
1002 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_DATA
);
1015 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
1016 has registered callback function.
1018 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
1020 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
1022 @param TokenNumber PCD token number generated by build tools.
1023 @param Data Value want to be set for this PCD entry
1024 @param Size The size of value
1028 InvokeCallbackOnSet (
1029 UINT32 ExTokenNumber
,
1030 CONST EFI_GUID
*Guid
, OPTIONAL
1036 CALLBACK_FN_ENTRY
*FnTableEntry
;
1037 LIST_ENTRY
*ListHead
;
1038 LIST_ENTRY
*ListNode
;
1041 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1042 // We have to decrement TokenNumber by 1 to make it usable
1043 // as the array index of mCallbackFnTable[].
1045 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
1046 ListNode
= GetFirstNode (ListHead
);
1048 while (ListNode
!= ListHead
) {
1049 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE (ListNode
, CALLBACK_FN_ENTRY
, Node
);
1051 FnTableEntry
->CallbackFn(Guid
,
1052 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
1056 ListNode
= GetNextNode (ListHead
, ListNode
);
1064 Wrapper function for setting non-pointer type value for a PCD entry.
1066 @param TokenNumber Pcd token number autogenerated by build tools.
1067 @param Data Value want to be set for PCD entry
1068 @param Size Size of value.
1070 @return status of SetWorker.
1075 IN UINTN TokenNumber
,
1080 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
1085 Set value for an PCD entry
1087 @param TokenNumber Pcd token number autogenerated by build tools.
1088 @param Data Value want to be set for PCD entry
1089 @param Size Size of value.
1090 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
1091 If False, the type of PCD entry's value is not Pointer.
1093 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
1094 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
1095 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
1096 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
1097 range of UINT8, UINT16, UINT32, UINT64
1098 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
1102 IN UINTN TokenNumber
,
1109 UINT32 LocalTokenNumber
;
1110 EFI_GUID
*GuidTable
;
1114 UINTN VariableOffset
;
1117 VARIABLE_HEAD
*VariableHead
;
1122 UINTN TmpTokenNumber
;
1125 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1126 // We have to decrement TokenNumber by 1 to make it usable
1127 // as the array index.
1131 TmpTokenNumber
= TokenNumber
;
1134 // EBC compiler is very choosy. It may report warning about comparison
1135 // between UINTN and 0 . So we add 1 in each size of the
1138 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
1142 // Get MaxSize first, then check new size with max buffer size.
1144 GetPtrTypeSize (TokenNumber
, &MaxSize
);
1145 if (*Size
> MaxSize
) {
1147 return EFI_INVALID_PARAMETER
;
1150 if (*Size
!= DxePcdGetSize (TokenNumber
+ 1)) {
1151 return EFI_INVALID_PARAMETER
;
1156 // EBC compiler is very choosy. It may report warning about comparison
1157 // between UINTN and 0 . So we add 1 in each size of the
1160 if ((TokenNumber
+ 1 < mPeiNexTokenCount
+ 1) ||
1161 (TokenNumber
+ 1 >= mPeiLocalTokenCount
+ 1 && TokenNumber
+ 1 < (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1))) {
1162 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
1166 // Aquire lock to prevent reentrance from TPL_CALLBACK level
1168 EfiAcquireLock (&mPcdDatabaseLock
);
1171 // EBC compiler is very choosy. It may report warning about comparison
1172 // between UINTN and 0 . So we add 1 in each size of the
1175 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
1177 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
1179 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1181 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
1184 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
1186 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
1190 InternalData
= PcdDb
+ Offset
;
1192 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
1195 Status
= EFI_INVALID_PARAMETER
;
1198 case PCD_TYPE_STRING
:
1199 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1200 CopyMem (StringTable
+ *((STRING_HEAD
*)InternalData
), Data
, *Size
);
1201 Status
= EFI_SUCCESS
;
1203 Status
= EFI_INVALID_PARAMETER
;
1207 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
1210 if (!SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1211 Status
= EFI_INVALID_PARAMETER
;
1217 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1219 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1222 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
1224 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1225 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1226 VariableOffset
= VariableHead
->Offset
;
1227 Attributes
= VariableHead
->Attributes
;
1228 Status
= SetHiiVariable (Guid
, Name
, Attributes
, Data
, *Size
, VariableOffset
);
1233 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1234 CopyMem (InternalData
, Data
, *Size
);
1235 Status
= EFI_SUCCESS
;
1237 Status
= EFI_INVALID_PARAMETER
;
1242 Status
= EFI_SUCCESS
;
1245 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
1248 case sizeof(UINT16
):
1249 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
1252 case sizeof(UINT32
):
1253 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
1256 case sizeof(UINT64
):
1257 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
1262 Status
= EFI_NOT_FOUND
;
1269 Status
= EFI_NOT_FOUND
;
1273 EfiReleaseLock (&mPcdDatabaseLock
);
1279 Wrapper function for get PCD value for dynamic-ex PCD.
1281 @param Guid Token space guid for dynamic-ex PCD.
1282 @param ExTokenNumber Token number for dynamic-ex PCD.
1283 @param GetSize The size of dynamic-ex PCD value.
1285 @return PCD entry in PCD database.
1290 IN CONST EFI_GUID
*Guid
,
1291 IN UINTN ExTokenNumber
,
1295 return GetWorker(GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
), GetSize
);
1299 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
1301 @param ExTokenNumber Token number for dynamic-ex PCD.
1302 @param Guid Token space guid for dynamic-ex PCD.
1303 @param Data Value want to be set.
1304 @param SetSize The size of value.
1306 @return status of ExSetWorker().
1311 IN UINTN ExTokenNumber
,
1312 IN CONST EFI_GUID
*Guid
,
1317 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &SetSize
, FALSE
);
1321 Set value for a dynamic-ex PCD entry.
1323 This routine find the local token number according to dynamic-ex PCD's token
1324 space guid and token number firstly, and invoke callback function if this PCD
1325 entry registered callback function. Finally, invoken general SetWorker to set
1328 @param ExTokenNumber Dynamic-ex PCD token number.
1329 @param Guid Token space guid for dynamic-ex PCD.
1330 @param Data PCD value want to be set
1331 @param SetSize Size of value.
1332 @param PtrType If TRUE, this PCD entry is pointer type.
1333 If FALSE, this PCD entry is not pointer type.
1335 @return status of SetWorker().
1340 IN UINTN ExTokenNumber
,
1341 IN CONST EFI_GUID
*Guid
,
1343 IN OUT UINTN
*SetSize
,
1349 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
);
1351 InvokeCallbackOnSet ((UINT32
) ExTokenNumber
, Guid
, TokenNumber
, Data
, *SetSize
);
1353 return SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
1358 Set value for HII-type PCD.
1360 A HII-type PCD's value is stored in a variable. Setting/Getting the value of
1361 HII-type PCD is to visit this variable.
1363 @param VariableGuid Guid of variable which stored value of a HII-type PCD.
1364 @param VariableName Unicode name of variable which stored value of a HII-type PCD.
1365 @param SetAttributes Attributes bitmask to set for the variable.
1366 @param Data Value want to be set.
1367 @param DataSize Size of value
1368 @param Offset Value offset of HII-type PCD in variable.
1370 @return status of GetVariable()/SetVariable().
1375 IN EFI_GUID
*VariableGuid
,
1376 IN UINT16
*VariableName
,
1377 IN UINT32 SetAttributes
,
1378 IN CONST VOID
*Data
,
1393 // Try to get original variable size information.
1395 Status
= gRT
->GetVariable (
1396 (UINT16
*)VariableName
,
1403 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1405 // Patch new PCD's value to offset in given HII variable.
1407 if (Size
>= (DataSize
+ Offset
)) {
1410 SetSize
= DataSize
+ Offset
;
1412 Buffer
= AllocatePool (SetSize
);
1413 ASSERT (Buffer
!= NULL
);
1415 Status
= gRT
->GetVariable (
1423 ASSERT_EFI_ERROR (Status
);
1425 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1427 if (SetAttributes
== 0) {
1428 SetAttributes
= Attribute
;
1431 Status
= gRT
->SetVariable (
1441 } else if (Status
== EFI_NOT_FOUND
) {
1443 // If variable does not exist, a new variable need to be created.
1446 Size
= Offset
+ DataSize
;
1448 Buffer
= AllocateZeroPool (Size
);
1449 ASSERT (Buffer
!= NULL
);
1451 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1453 if (SetAttributes
== 0) {
1454 SetAttributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1457 Status
= gRT
->SetVariable (
1470 // If we drop to here, the value is failed to be written in to variable area.
1476 Get Token Number according to dynamic-ex PCD's {token space guid:token number}
1478 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
1479 in DEC file. PCD database maintain a mapping table that translate pair of {token
1480 space guid: token number} to Token Number.
1482 @param Guid Token space guid for dynamic-ex PCD entry.
1483 @param ExTokenNumber Dynamic-ex PCD token number.
1485 @return Token Number for dynamic-ex PCD.
1489 GetExPcdTokenNumber (
1490 IN CONST EFI_GUID
*Guid
,
1491 IN UINT32 ExTokenNumber
1495 DYNAMICEX_MAPPING
*ExMap
;
1496 EFI_GUID
*GuidTable
;
1497 EFI_GUID
*MatchGuid
;
1500 if (!mPeiDatabaseEmpty
) {
1501 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->ExMapTableOffset
);
1502 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1504 MatchGuid
= ScanGuid (GuidTable
, mPeiGuidTableSize
, Guid
);
1506 if (MatchGuid
!= NULL
) {
1508 MatchGuidIdx
= MatchGuid
- GuidTable
;
1510 for (Index
= 0; Index
< mPcdDatabase
.PeiDb
->ExTokenCount
; Index
++) {
1511 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1512 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1513 return ExMap
[Index
].TokenNumber
;
1519 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->ExMapTableOffset
);
1520 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1522 MatchGuid
= ScanGuid (GuidTable
, mDxeGuidTableSize
, Guid
);
1524 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
1525 // error in the BUILD system.
1527 ASSERT (MatchGuid
!= NULL
);
1529 MatchGuidIdx
= MatchGuid
- GuidTable
;
1531 for (Index
= 0; Index
< mPcdDatabase
.DxeDb
->ExTokenCount
; Index
++) {
1532 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1533 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1534 return ExMap
[Index
].TokenNumber
;
1544 Get SKU ID table from PCD database.
1546 @param LocalTokenNumberTableIdx Index of local token number in token number table.
1547 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1548 If FALSE, the pcd entry is initialized in DXE phase.
1549 @return Pointer to SKU ID array table
1554 IN UINTN LocalTokenNumberTableIdx
,
1559 UINTN LocalTokenNumber
;
1563 LocalTokenNumber
= *((UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
) + LocalTokenNumberTableIdx
);
1564 Database
= (UINT8
*) mPcdDatabase
.PeiDb
;
1566 LocalTokenNumber
= *((UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
) + LocalTokenNumberTableIdx
);
1567 Database
= (UINT8
*) mPcdDatabase
.DxeDb
;
1570 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
1572 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
1574 return (SKU_ID
*) (Database
+ SkuHead
->SkuIdTableOffset
);
1579 Wrapper function of getting index of PCD entry in size table.
1581 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1582 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1583 If FALSE, the pcd entry is initialized in DXE phase.
1585 @return index of PCD entry in size table.
1589 IN UINTN LocalTokenNumberTableIdx
,
1593 UINT32
*LocalTokenNumberTable
;
1594 UINTN LocalTokenNumber
;
1600 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1602 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1607 for (Index
= 0; Index
< LocalTokenNumberTableIdx
; Index
++) {
1608 LocalTokenNumber
= LocalTokenNumberTable
[Index
];
1610 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
1612 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1615 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1617 // We have only two entry for VPD enabled PCD entry:
1620 // Current size is equal to MAX size.
1624 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1626 // We have only two entry for Non-Sku enabled PCD entry:
1633 // We have these entry for SKU enabled PCD entry
1635 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1637 SkuIdTable
= GetSkuIdArray (Index
, IsPeiDb
);
1638 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
1645 return SizeTableIdx
;
1649 Get size of POINTER type PCD value.
1651 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1652 @param MaxSize Maxmium size of POINTER type PCD value.
1654 @return size of POINTER type PCD value.
1659 IN UINTN LocalTokenNumberTableIdx
,
1664 UINTN LocalTokenNumber
;
1666 SIZE_INFO
*SizeTable
;
1669 UINT32
*LocalTokenNumberTable
;
1671 // EBC compiler is very choosy. It may report warning about comparison
1672 // between UINTN and 0 . So we add 1 in each size of the
1674 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1678 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1679 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1681 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1682 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1683 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1686 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1688 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1690 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1692 *MaxSize
= SizeTable
[SizeTableIdx
];
1694 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1697 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1699 // We have only two entry for VPD enabled PCD entry:
1702 // We consider current size is equal to MAX size.
1706 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1708 // We have only two entry for Non-Sku enabled PCD entry:
1712 return SizeTable
[SizeTableIdx
+ 1];
1715 // We have these entry for SKU enabled PCD entry
1717 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1719 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, IsPeiDb
);
1720 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
1721 if (SkuIdTable
[1 + Index
] == mPcdDatabase
.DxeDb
->SystemSkuId
) {
1722 return SizeTable
[SizeTableIdx
+ 1 + Index
];
1725 return SizeTable
[SizeTableIdx
+ 1];
1731 Set size of POINTER type PCD value. The size should not exceed the maximum size
1734 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1735 @param CurrentSize Size of POINTER type PCD value.
1737 @retval TRUE Success to set size of PCD value.
1738 @retval FALSE Fail to set size of PCD value.
1742 IN UINTN LocalTokenNumberTableIdx
,
1743 IN OUT UINTN
*CurrentSize
1747 UINTN LocalTokenNumber
;
1749 SIZE_INFO
*SizeTable
;
1753 UINT32
*LocalTokenNumberTable
;
1756 // EBC compiler is very choosy. It may report warning about comparison
1757 // between UINTN and 0 . So we add 1 in each size of the
1760 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1763 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1764 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1766 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1767 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1768 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1771 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1773 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1775 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1777 MaxSize
= SizeTable
[SizeTableIdx
];
1779 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1782 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1784 // We shouldn't come here as we don't support SET for VPD
1789 if ((*CurrentSize
> MaxSize
) ||
1790 (*CurrentSize
== MAX_ADDRESS
)) {
1791 *CurrentSize
= MaxSize
;
1795 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1797 // We have only two entry for Non-Sku enabled PCD entry:
1801 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
1805 // We have these entry for SKU enabled PCD entry
1807 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1809 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, IsPeiDb
);
1810 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
1811 if (SkuIdTable
[1 + Index
] == mPcdDatabase
.DxeDb
->SystemSkuId
) {
1812 SizeTable
[SizeTableIdx
+ 1 + Index
] = (SIZE_INFO
) *CurrentSize
;
1816 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
1823 VariableLock DynamicHiiPcd.
1825 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1826 If FALSE, the pcd entry is initialized in DXE phase.
1827 @param[in] VariableLock Pointer to VariableLockProtocol.
1831 VariableLockDynamicHiiPcd (
1833 IN EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
1837 PCD_DATABASE_INIT
*Database
;
1838 UINT32 LocalTokenCount
;
1840 UINT32 LocalTokenNumber
;
1842 EFI_GUID
*GuidTable
;
1844 VARIABLE_HEAD
*VariableHead
;
1848 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
1849 LocalTokenCount
= IsPeiDb
? mPeiLocalTokenCount
: mDxeLocalTokenCount
;
1852 // Go through PCD database to find out DynamicHii PCDs.
1854 for (TokenNumber
= 0; TokenNumber
< LocalTokenCount
; TokenNumber
++) {
1856 LocalTokenNumber
= GetLocalTokenNumber (TRUE
, TokenNumber
);
1858 LocalTokenNumber
= GetLocalTokenNumber (FALSE
, TokenNumber
+ mPeiLocalTokenCount
);
1860 if ((LocalTokenNumber
& PCD_TYPE_HII
) != 0) {
1861 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1862 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*) Database
+ Offset
);
1864 // Why not to set property by VarCheckProtocol with Attributes and Property directly here?
1865 // It is because that set property by VarCheckProtocol will indicate the variable to
1866 // be a system variable, but the unknown max size of the variable is dangerous to
1867 // the system variable region.
1869 if ((VariableHead
->Property
& VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY
) != 0) {
1871 // DynamicHii PCD with RO property set in *.dsc.
1873 StringTable
= (UINT8
*) ((UINT8
*) Database
+ Database
->StringTableOffset
);
1874 GuidTable
= (EFI_GUID
*) ((UINT8
*) Database
+ Database
->GuidTableOffset
);
1875 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1876 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1877 Status
= VariableLock
->RequestToLock (VariableLock
, Name
, Guid
);
1878 ASSERT_EFI_ERROR (Status
);
1885 VariableLockProtocol callback
1886 to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
1888 @param[in] Event Event whose notification function is being invoked.
1889 @param[in] Context Pointer to the notification function's context.
1894 VariableLockCallBack (
1900 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
1902 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
1903 if (!EFI_ERROR (Status
)) {
1904 VariableLockDynamicHiiPcd (TRUE
, VariableLock
);
1905 VariableLockDynamicHiiPcd (FALSE
, VariableLock
);