2 Help functions used by PCD DXE driver.
4 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2015, 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 // Return NULL when PCD name table is absent.
154 if (mPcdDatabase
.PeiDb
->PcdNameTableOffset
== 0) {
158 if (mPcdDatabase
.DxeDb
->PcdNameTableOffset
== 0) {
164 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
165 // We have to decrement TokenNumber by 1 to make it usable
166 // as the array index.
170 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
171 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
173 StringTable
= (UINT8
*) Database
+ Database
->StringTableOffset
;
176 // Get the PCD name index.
178 PcdNameIndex
= (PCD_NAME_INDEX
*)((UINT8
*) Database
+ Database
->PcdNameTableOffset
) + TokenNumber
;
179 TokenSpaceName
= (CHAR8
*)&StringTable
[PcdNameIndex
->TokenSpaceCNameIndex
];
180 PcdName
= (CHAR8
*)&StringTable
[PcdNameIndex
->PcdCNameIndex
];
182 if (OnlyTokenSpaceName
) {
184 // Only need to get the TokenSpaceCName.
186 Name
= AllocateCopyPool (AsciiStrSize (TokenSpaceName
), TokenSpaceName
);
189 // Need to get the full PCD name.
191 Name
= AllocateZeroPool (AsciiStrSize (TokenSpaceName
) + AsciiStrSize (PcdName
));
192 ASSERT (Name
!= NULL
);
194 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
196 AsciiStrCat (Name
, TokenSpaceName
);
197 Name
[AsciiStrSize (TokenSpaceName
) - sizeof (CHAR8
)] = '.';
198 AsciiStrCat (Name
, PcdName
);
205 Retrieve additional information associated with a PCD token.
207 This includes information such as the type of value the TokenNumber is associated with as well as possible
208 human readable name that is associated with the token.
210 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
211 If FALSE, the pcd entry is initialized in DXE phase.
212 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
213 @param[in] TokenNumber The PCD token number.
214 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
215 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
217 @retval EFI_SUCCESS The PCD information was returned successfully
218 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
223 IN CONST EFI_GUID
*Guid
,
224 IN UINTN TokenNumber
,
225 OUT EFI_PCD_INFO
*PcdInfo
228 PCD_DATABASE_INIT
*Database
;
232 DYNAMICEX_MAPPING
*ExMapTable
;
234 UINT32 LocalTokenNumber
;
236 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
238 GuidTable
= (EFI_GUID
*)((UINT8
*)Database
+ Database
->GuidTableOffset
);
239 MatchGuid
= ScanGuid (GuidTable
, Database
->GuidTableCount
* sizeof(EFI_GUID
), Guid
);
241 if (MatchGuid
== NULL
) {
242 return EFI_NOT_FOUND
;
245 GuidTableIdx
= MatchGuid
- GuidTable
;
247 ExMapTable
= (DYNAMICEX_MAPPING
*)((UINT8
*)Database
+ Database
->ExMapTableOffset
);
250 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
252 for (Index
= 0; Index
< Database
->ExTokenCount
; Index
++) {
253 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
254 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
256 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
257 // PcdSize to 0 and PcdName to the null-terminated ASCII string
258 // associated with the token's namespace Guid.
260 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
261 PcdInfo
->PcdSize
= 0;
263 // Here use one representative in the token space to get the TokenSpaceCName.
265 PcdInfo
->PcdName
= GetPcdName (TRUE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
267 } else if (ExMapTable
[Index
].ExTokenNumber
== TokenNumber
) {
268 PcdInfo
->PcdSize
= DxePcdGetSize (ExMapTable
[Index
].TokenNumber
);
269 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
270 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
271 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
277 return EFI_NOT_FOUND
;
281 Retrieve additional information associated with a PCD token.
283 This includes information such as the type of value the TokenNumber is associated with as well as possible
284 human readable name that is associated with the token.
286 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
287 @param[in] TokenNumber The PCD token number.
288 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
289 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
291 @retval EFI_SUCCESS The PCD information was returned successfully.
292 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
296 IN CONST EFI_GUID
*Guid
,
297 IN UINTN TokenNumber
,
298 OUT EFI_PCD_INFO
*PcdInfo
302 BOOLEAN PeiExMapTableEmpty
;
303 BOOLEAN DxeExMapTableEmpty
;
304 UINT32 LocalTokenNumber
;
307 ASSERT (PcdInfo
!= NULL
);
309 Status
= EFI_NOT_FOUND
;
310 PeiExMapTableEmpty
= mPeiExMapTableEmpty
;
311 DxeExMapTableEmpty
= mDxeExMapTableEmpty
;
314 if (((TokenNumber
+ 1 > mPeiNexTokenCount
+ 1) && (TokenNumber
+ 1 <= mPeiLocalTokenCount
+ 1)) ||
315 ((TokenNumber
+ 1 > (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1)))) {
316 return EFI_NOT_FOUND
;
317 } else if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
319 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
320 // PcdSize to 0 and PcdName to NULL for default Token Space.
322 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
323 PcdInfo
->PcdSize
= 0;
324 PcdInfo
->PcdName
= NULL
;
326 PcdInfo
->PcdSize
= DxePcdGetSize (TokenNumber
);
328 if ((TokenNumber
+ 1 <= mPeiNexTokenCount
+ 1)) {
331 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
);
332 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
333 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, TokenNumber
);
338 if (PeiExMapTableEmpty
&& DxeExMapTableEmpty
) {
339 return EFI_NOT_FOUND
;
342 if (!PeiExMapTableEmpty
) {
343 Status
= ExGetPcdInfo (
351 if (Status
== EFI_SUCCESS
) {
355 if (!DxeExMapTableEmpty
) {
356 Status
= ExGetPcdInfo (
368 Get the PCD entry pointer in PCD database.
370 This routine will visit PCD database to find the PCD entry according to given
371 token number. The given token number is autogened by build tools and it will be
372 translated to local token number. Local token number contains PCD's type and
373 offset of PCD entry in PCD database.
375 @param TokenNumber Token's number, it is autogened by build tools
376 @param GetSize The size of token's value
378 @return PCD entry pointer in PCD database
383 IN UINTN TokenNumber
,
391 VARIABLE_HEAD
*VariableHead
;
392 UINT8
*VaraiableDefaultBuffer
;
397 UINTN TmpTokenNumber
;
400 UINT32 LocalTokenNumber
;
402 STRING_HEAD StringTableIdx
;
406 // Aquire lock to prevent reentrance from TPL_CALLBACK level
408 EfiAcquireLock (&mPcdDatabaseLock
);
412 ASSERT (TokenNumber
> 0);
414 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
415 // We have to decrement TokenNumber by 1 to make it usable
416 // as the array index.
420 TmpTokenNumber
= TokenNumber
;
423 // EBC compiler is very choosy. It may report warning about comparison
424 // between UINTN and 0 . So we add 1 in each size of the
427 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
429 ASSERT ((GetSize
== DxePcdGetSize (TokenNumber
+ 1)) || (GetSize
== 0));
431 // EBC compiler is very choosy. It may report warning about comparison
432 // between UINTN and 0 . So we add 1 in each size of the
434 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
436 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
438 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
441 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
443 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
447 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
449 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
451 VpdHead
= (VPD_HEAD
*) ((UINT8
*) PcdDb
+ Offset
);
452 RetPtr
= (VOID
*) (UINTN
) (PcdGet32 (PcdVpdBaseAddress
) + VpdHead
->Offset
);
456 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
459 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
461 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
464 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
465 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
466 Name
= (UINT16
*)(StringTable
+ VariableHead
->StringIndex
);
468 if ((LocalTokenNumber
& PCD_TYPE_ALL_SET
) == (PCD_TYPE_HII
|PCD_TYPE_STRING
)) {
470 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
471 // string array in string table.
473 StringTableIdx
= *(STRING_HEAD
*)((UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
);
474 VaraiableDefaultBuffer
= (UINT8
*) (StringTable
+ StringTableIdx
);
476 VaraiableDefaultBuffer
= (UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
;
478 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
479 if (Status
== EFI_SUCCESS
) {
480 if (DataSize
>= (VariableHead
->Offset
+ GetSize
)) {
483 // It is a pointer type. So get the MaxSize reserved for
486 GetPtrTypeSize (TmpTokenNumber
, &GetSize
);
487 if (GetSize
> (DataSize
- VariableHead
->Offset
)) {
489 // Use actual valid size.
491 GetSize
= DataSize
- VariableHead
->Offset
;
495 // If the operation is successful, we copy the data
496 // to the default value buffer in the PCD Database.
497 // So that we can free the Data allocated in GetHiiVariable.
499 CopyMem (VaraiableDefaultBuffer
, Data
+ VariableHead
->Offset
, GetSize
);
503 RetPtr
= (VOID
*) VaraiableDefaultBuffer
;
506 case PCD_TYPE_STRING
:
507 StringTableIdx
= *(STRING_HEAD
*)((UINT8
*) PcdDb
+ Offset
);
508 RetPtr
= (VOID
*) (StringTable
+ StringTableIdx
);
512 RetPtr
= (VOID
*) ((UINT8
*) PcdDb
+ Offset
);
521 EfiReleaseLock (&mPcdDatabaseLock
);
528 Register the callback function for a PCD entry.
530 This routine will register a callback function to a PCD entry by given token number
531 and token space guid.
533 @param TokenNumber PCD token's number, it is autogened by build tools.
534 @param Guid PCD token space's guid,
535 if not NULL, this PCD is dynamicEx type PCD.
536 @param CallBackFunction Callback function pointer
538 @return EFI_SUCCESS Always success for registering callback function.
542 DxeRegisterCallBackWorker (
543 IN UINTN TokenNumber
,
544 IN CONST EFI_GUID
*Guid
, OPTIONAL
545 IN PCD_PROTOCOL_CALLBACK CallBackFunction
548 CALLBACK_FN_ENTRY
*FnTableEntry
;
549 LIST_ENTRY
*ListHead
;
550 LIST_ENTRY
*ListNode
;
553 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
557 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
558 // We have to decrement TokenNumber by 1 to make it usable
559 // as the array index of mCallbackFnTable[].
561 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
562 ListNode
= GetFirstNode (ListHead
);
564 while (ListNode
!= ListHead
) {
565 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
567 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
569 // We only allow a Callback function to be register once
570 // for a TokenNumber. So just return EFI_SUCCESS
574 ListNode
= GetNextNode (ListHead
, ListNode
);
577 FnTableEntry
= AllocatePool (sizeof(CALLBACK_FN_ENTRY
));
578 ASSERT (FnTableEntry
!= NULL
);
580 FnTableEntry
->CallbackFn
= CallBackFunction
;
581 InsertTailList (ListHead
, &FnTableEntry
->Node
);
587 UnRegister the callback function for a PCD entry.
589 This routine will unregister a callback function to a PCD entry by given token number
590 and token space guid.
592 @param TokenNumber PCD token's number, it is autogened by build tools.
593 @param Guid PCD token space's guid.
594 if not NULL, this PCD is dynamicEx type PCD.
595 @param CallBackFunction Callback function pointer
597 @retval EFI_SUCCESS Callback function is success to be unregister.
598 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.
601 DxeUnRegisterCallBackWorker (
602 IN UINTN TokenNumber
,
603 IN CONST EFI_GUID
*Guid
, OPTIONAL
604 IN PCD_PROTOCOL_CALLBACK CallBackFunction
607 CALLBACK_FN_ENTRY
*FnTableEntry
;
608 LIST_ENTRY
*ListHead
;
609 LIST_ENTRY
*ListNode
;
612 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
616 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
617 // We have to decrement TokenNumber by 1 to make it usable
618 // as the array index of mCallbackFnTable[].
620 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
621 ListNode
= GetFirstNode (ListHead
);
623 while (ListNode
!= ListHead
) {
624 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
626 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
628 // We only allow a Callback function to be register once
629 // for a TokenNumber. So we can safely remove the Node from
630 // the Link List and return EFI_SUCCESS.
632 RemoveEntryList (ListNode
);
633 FreePool (FnTableEntry
);
637 ListNode
= GetNextNode (ListHead
, ListNode
);
640 return EFI_INVALID_PARAMETER
;
644 Get next token number in given token space.
646 This routine is used for dynamicEx type PCD. It will firstly scan token space
647 table to get token space according to given token space guid. Then scan given
648 token number in found token space, if found, then return next token number in
651 @param Guid Token space guid. Next token number will be scaned in
653 @param TokenNumber Token number.
654 If PCD_INVALID_TOKEN_NUMBER, return first token number in
656 If not PCD_INVALID_TOKEN_NUMBER, return next token number
657 in token space table.
658 @param GuidTable Token space guid table. It will be used for scan token space
659 by given token space guid.
660 @param SizeOfGuidTable The size of guid table.
661 @param ExMapTable DynamicEx token number mapping table.
662 @param SizeOfExMapTable The size of dynamicEx token number mapping table.
664 @retval EFI_NOT_FOUND Can not given token space or token number.
665 @retval EFI_SUCCESS Success to get next token number.
669 ExGetNextTokeNumber (
670 IN CONST EFI_GUID
*Guid
,
671 IN OUT UINTN
*TokenNumber
,
672 IN EFI_GUID
*GuidTable
,
673 IN UINTN SizeOfGuidTable
,
674 IN DYNAMICEX_MAPPING
*ExMapTable
,
675 IN UINTN SizeOfExMapTable
682 UINTN ExMapTableCount
;
685 // Scan token space guid
687 MatchGuid
= ScanGuid (GuidTable
, SizeOfGuidTable
, Guid
);
688 if (MatchGuid
== NULL
) {
689 return EFI_NOT_FOUND
;
693 // Find the token space table in dynamicEx mapping table.
696 GuidTableIdx
= MatchGuid
- GuidTable
;
697 ExMapTableCount
= SizeOfExMapTable
/ sizeof(ExMapTable
[0]);
698 for (Index
= 0; Index
< ExMapTableCount
; Index
++) {
699 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
707 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
708 // token number in found token space.
710 if (*TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
711 *TokenNumber
= ExMapTable
[Index
].ExTokenNumber
;
715 for ( ; Index
< ExMapTableCount
; Index
++) {
716 if (ExMapTable
[Index
].ExTokenNumber
== *TokenNumber
) {
721 while (Index
< ExMapTableCount
) {
723 if (Index
== ExMapTableCount
) {
725 // Exceed the length of ExMap Table
727 *TokenNumber
= PCD_INVALID_TOKEN_NUMBER
;
728 return EFI_NOT_FOUND
;
729 } else if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
731 // Found the next match
733 *TokenNumber
= ExMapTable
[Index
].ExTokenNumber
;
739 return EFI_NOT_FOUND
;
743 Find the PCD database.
745 @retval The base address of external PCD database binary.
746 @retval NULL Return NULL if not find.
753 DXE_PCD_DATABASE
*DxePcdDbBinary
;
757 DxePcdDbBinary
= NULL
;
759 // Search the External Pcd database from one section of current FFS,
760 // and read it to memory
762 Status
= GetSectionFromFfs (
765 (VOID
**) &DxePcdDbBinary
,
768 ASSERT_EFI_ERROR (Status
);
771 // Check the first bytes (Header Signature Guid) and build version.
773 if (!CompareGuid ((VOID
*)DxePcdDbBinary
, &gPcdDataBaseSignatureGuid
) ||
774 (DxePcdDbBinary
->BuildVersion
!= PCD_SERVICE_DXE_VERSION
)) {
778 return DxePcdDbBinary
;
782 Initialize the PCD database in DXE phase.
784 PCD database in DXE phase also contains PCD database in PEI phase which is copied
789 BuildPcdDxeDataBase (
793 PEI_PCD_DATABASE
*PeiDatabase
;
794 EFI_HOB_GUID_TYPE
*GuidHob
;
800 // Assign PCD Entries with default value to PCD DATABASE
802 mPcdDatabase
.DxeDb
= LocateExPcdBinary ();
803 ASSERT(mPcdDatabase
.DxeDb
!= NULL
);
804 PcdDxeDbLen
= mPcdDatabase
.DxeDb
->Length
+ mPcdDatabase
.DxeDb
->UninitDataBaseSize
;
805 PcdDxeDb
= AllocateZeroPool (PcdDxeDbLen
);
806 ASSERT (PcdDxeDb
!= NULL
);
807 CopyMem (PcdDxeDb
, mPcdDatabase
.DxeDb
, mPcdDatabase
.DxeDb
->Length
);
808 FreePool (mPcdDatabase
.DxeDb
);
809 mPcdDatabase
.DxeDb
= PcdDxeDb
;
811 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
812 if (GuidHob
!= NULL
) {
815 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
816 // should not be included at all. So the GuidHob could
817 // be NULL. If it is NULL, we just copy over the DXE Default
818 // Value to PCD Database.
821 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
823 // Assign PCD Entries refereneced in PEI phase to PCD DATABASE
825 mPcdDatabase
.PeiDb
= PeiDatabase
;
827 // Inherit the SystemSkuId from PEI phase.
829 mPcdDatabase
.DxeDb
->SystemSkuId
= mPcdDatabase
.PeiDb
->SystemSkuId
;
831 mPcdDatabase
.PeiDb
= AllocateZeroPool (sizeof (PEI_PCD_DATABASE
));
832 ASSERT(mPcdDatabase
.PeiDb
!= NULL
);
836 // Initialized the external PCD database local variables
838 mPeiLocalTokenCount
= mPcdDatabase
.PeiDb
->LocalTokenCount
;
839 mDxeLocalTokenCount
= mPcdDatabase
.DxeDb
->LocalTokenCount
;
841 mPeiExMapppingTableSize
= mPcdDatabase
.PeiDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
842 mDxeExMapppingTableSize
= mPcdDatabase
.DxeDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
843 mPeiGuidTableSize
= mPcdDatabase
.PeiDb
->GuidTableCount
* sizeof(GUID
);
844 mDxeGuidTableSize
= mPcdDatabase
.DxeDb
->GuidTableCount
* sizeof (GUID
);
846 mPcdTotalTokenCount
= mPeiLocalTokenCount
+ mDxeLocalTokenCount
;
847 mPeiNexTokenCount
= mPeiLocalTokenCount
- mPcdDatabase
.PeiDb
->ExTokenCount
;
848 mDxeNexTokenCount
= mDxeLocalTokenCount
- mPcdDatabase
.DxeDb
->ExTokenCount
;
850 mPeiExMapTableEmpty
= (mPcdDatabase
.PeiDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
851 mDxeExMapTableEmpty
= (mPcdDatabase
.DxeDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
852 mPeiDatabaseEmpty
= (mPeiLocalTokenCount
== 0) ? TRUE
: FALSE
;
854 TmpTokenSpaceBufferCount
= mPcdDatabase
.PeiDb
->ExTokenCount
+ mPcdDatabase
.DxeDb
->ExTokenCount
;
855 TmpTokenSpaceBuffer
= (EFI_GUID
**)AllocateZeroPool(TmpTokenSpaceBufferCount
* sizeof (EFI_GUID
*));
858 // Initialized the Callback Function Table
860 mCallbackFnTable
= AllocateZeroPool (mPcdTotalTokenCount
* sizeof (LIST_ENTRY
));
861 ASSERT(mCallbackFnTable
!= NULL
);
864 // EBC compiler is very choosy. It may report warning about comparison
865 // between UINTN and 0 . So we add 1 in each size of the
868 for (Index
= 0; Index
+ 1 < mPcdTotalTokenCount
+ 1; Index
++) {
869 InitializeListHead (&mCallbackFnTable
[Index
]);
874 Get Variable which contains HII type PCD entry.
876 @param VariableGuid Variable's guid
877 @param VariableName Variable's unicode name string
878 @param VariableData Variable's data pointer,
879 @param VariableSize Variable's size.
881 @return the status of gRT->GetVariable
885 IN EFI_GUID
*VariableGuid
,
886 IN UINT16
*VariableName
,
887 OUT UINT8
**VariableData
,
888 OUT UINTN
*VariableSize
899 // Firstly get the real size of HII variable
901 Status
= gRT
->GetVariable (
902 (UINT16
*)VariableName
,
910 // Allocate buffer to hold whole variable data according to variable size.
912 if (Status
== EFI_BUFFER_TOO_SMALL
) {
913 Buffer
= (UINT8
*) AllocatePool (Size
);
915 ASSERT (Buffer
!= NULL
);
917 Status
= gRT
->GetVariable (
925 ASSERT (Status
== EFI_SUCCESS
);
926 *VariableData
= Buffer
;
927 *VariableSize
= Size
;
930 // Use Default Data only when variable is not found.
931 // For other error status, correct data can't be got, and trig ASSERT().
933 ASSERT (Status
== EFI_NOT_FOUND
);
940 Find the local token number according to system SKU ID.
942 @param LocalTokenNumber PCD token number
943 @param Size The size of PCD entry.
944 @param IsPeiDb If TRUE, the PCD entry is initialized in PEI phase.
945 If False, the PCD entry is initialized in DXE phase.
947 @return Token number according to system SKU ID.
951 GetSkuEnabledTokenNumber (
952 UINT32 LocalTokenNumber
,
964 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
966 PcdDb
= IsPeiDb
? (UINT8
*) mPcdDatabase
.PeiDb
: (UINT8
*) mPcdDatabase
.DxeDb
;
968 SkuHead
= (SKU_HEAD
*) (PcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
969 Value
= (UINT8
*) (PcdDb
+ SkuHead
->SkuDataStartOffset
);
971 SkuIdTable
= (SKU_ID
*)(PcdDb
+ SkuHead
->SkuIdTableOffset
);
973 // Find the current system's SKU ID entry in SKU ID table.
976 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
977 if (mPcdDatabase
.DxeDb
->SystemSkuId
== SkuIdTable
[Index
+ 1]) {
984 // Find the default SKU ID entry in SKU ID table.
988 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
989 if (0 == SkuIdTable
[Index
+ 1]) {
994 ASSERT (Index
< SkuIdTable
[0]);
996 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
998 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[Index
]);
999 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_VPD
);
1002 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[Index
]);
1003 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_HII
);
1005 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
1006 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[Index
]);
1007 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_HII
| PCD_TYPE_STRING
);
1009 case PCD_TYPE_STRING
:
1010 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[Index
]);
1011 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_STRING
);
1014 Value
+= Size
* Index
;
1015 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_DATA
);
1028 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
1029 has registered callback function.
1031 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
1033 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
1035 @param TokenNumber PCD token number generated by build tools.
1036 @param Data Value want to be set for this PCD entry
1037 @param Size The size of value
1041 InvokeCallbackOnSet (
1042 UINT32 ExTokenNumber
,
1043 CONST EFI_GUID
*Guid
, OPTIONAL
1049 CALLBACK_FN_ENTRY
*FnTableEntry
;
1050 LIST_ENTRY
*ListHead
;
1051 LIST_ENTRY
*ListNode
;
1054 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1055 // We have to decrement TokenNumber by 1 to make it usable
1056 // as the array index of mCallbackFnTable[].
1058 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
1059 ListNode
= GetFirstNode (ListHead
);
1061 while (ListNode
!= ListHead
) {
1062 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE (ListNode
, CALLBACK_FN_ENTRY
, Node
);
1064 FnTableEntry
->CallbackFn(Guid
,
1065 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
1069 ListNode
= GetNextNode (ListHead
, ListNode
);
1077 Wrapper function for setting non-pointer type value for a PCD entry.
1079 @param TokenNumber Pcd token number autogenerated by build tools.
1080 @param Data Value want to be set for PCD entry
1081 @param Size Size of value.
1083 @return status of SetWorker.
1088 IN UINTN TokenNumber
,
1093 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
1098 Set value for an PCD entry
1100 @param TokenNumber Pcd token number autogenerated by build tools.
1101 @param Data Value want to be set for PCD entry
1102 @param Size Size of value.
1103 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
1104 If False, the type of PCD entry's value is not Pointer.
1106 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
1107 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
1108 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
1109 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
1110 range of UINT8, UINT16, UINT32, UINT64
1111 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
1115 IN UINTN TokenNumber
,
1122 UINT32 LocalTokenNumber
;
1123 EFI_GUID
*GuidTable
;
1127 UINTN VariableOffset
;
1130 VARIABLE_HEAD
*VariableHead
;
1135 UINTN TmpTokenNumber
;
1138 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1139 // We have to decrement TokenNumber by 1 to make it usable
1140 // as the array index.
1144 TmpTokenNumber
= TokenNumber
;
1147 // EBC compiler is very choosy. It may report warning about comparison
1148 // between UINTN and 0 . So we add 1 in each size of the
1151 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
1155 // Get MaxSize first, then check new size with max buffer size.
1157 GetPtrTypeSize (TokenNumber
, &MaxSize
);
1158 if (*Size
> MaxSize
) {
1160 return EFI_INVALID_PARAMETER
;
1163 if (*Size
!= DxePcdGetSize (TokenNumber
+ 1)) {
1164 return EFI_INVALID_PARAMETER
;
1169 // EBC compiler is very choosy. It may report warning about comparison
1170 // between UINTN and 0 . So we add 1 in each size of the
1173 if ((TokenNumber
+ 1 < mPeiNexTokenCount
+ 1) ||
1174 (TokenNumber
+ 1 >= mPeiLocalTokenCount
+ 1 && TokenNumber
+ 1 < (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1))) {
1175 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
1179 // Aquire lock to prevent reentrance from TPL_CALLBACK level
1181 EfiAcquireLock (&mPcdDatabaseLock
);
1184 // EBC compiler is very choosy. It may report warning about comparison
1185 // between UINTN and 0 . So we add 1 in each size of the
1188 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
1190 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
1192 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1194 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
1197 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
1199 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
1203 InternalData
= PcdDb
+ Offset
;
1205 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
1208 Status
= EFI_INVALID_PARAMETER
;
1211 case PCD_TYPE_STRING
:
1212 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1213 CopyMem (StringTable
+ *((STRING_HEAD
*)InternalData
), Data
, *Size
);
1214 Status
= EFI_SUCCESS
;
1216 Status
= EFI_INVALID_PARAMETER
;
1220 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
1223 if (!SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1224 Status
= EFI_INVALID_PARAMETER
;
1230 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1232 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1235 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
1237 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1238 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1239 VariableOffset
= VariableHead
->Offset
;
1240 Attributes
= VariableHead
->Attributes
;
1241 Status
= SetHiiVariable (Guid
, Name
, Attributes
, Data
, *Size
, VariableOffset
);
1246 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1247 CopyMem (InternalData
, Data
, *Size
);
1248 Status
= EFI_SUCCESS
;
1250 Status
= EFI_INVALID_PARAMETER
;
1255 Status
= EFI_SUCCESS
;
1258 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
1261 case sizeof(UINT16
):
1262 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
1265 case sizeof(UINT32
):
1266 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
1269 case sizeof(UINT64
):
1270 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
1275 Status
= EFI_NOT_FOUND
;
1282 Status
= EFI_NOT_FOUND
;
1286 EfiReleaseLock (&mPcdDatabaseLock
);
1292 Wrapper function for get PCD value for dynamic-ex PCD.
1294 @param Guid Token space guid for dynamic-ex PCD.
1295 @param ExTokenNumber Token number for dynamic-ex PCD.
1296 @param GetSize The size of dynamic-ex PCD value.
1298 @return PCD entry in PCD database.
1303 IN CONST EFI_GUID
*Guid
,
1304 IN UINTN ExTokenNumber
,
1308 return GetWorker(GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
), GetSize
);
1312 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
1314 @param ExTokenNumber Token number for dynamic-ex PCD.
1315 @param Guid Token space guid for dynamic-ex PCD.
1316 @param Data Value want to be set.
1317 @param SetSize The size of value.
1319 @return status of ExSetWorker().
1324 IN UINTN ExTokenNumber
,
1325 IN CONST EFI_GUID
*Guid
,
1330 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &SetSize
, FALSE
);
1334 Set value for a dynamic-ex PCD entry.
1336 This routine find the local token number according to dynamic-ex PCD's token
1337 space guid and token number firstly, and invoke callback function if this PCD
1338 entry registered callback function. Finally, invoken general SetWorker to set
1341 @param ExTokenNumber Dynamic-ex PCD token number.
1342 @param Guid Token space guid for dynamic-ex PCD.
1343 @param Data PCD value want to be set
1344 @param SetSize Size of value.
1345 @param PtrType If TRUE, this PCD entry is pointer type.
1346 If FALSE, this PCD entry is not pointer type.
1348 @return status of SetWorker().
1353 IN UINTN ExTokenNumber
,
1354 IN CONST EFI_GUID
*Guid
,
1356 IN OUT UINTN
*SetSize
,
1362 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
);
1364 InvokeCallbackOnSet ((UINT32
) ExTokenNumber
, Guid
, TokenNumber
, Data
, *SetSize
);
1366 return SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
1371 Set value for HII-type PCD.
1373 A HII-type PCD's value is stored in a variable. Setting/Getting the value of
1374 HII-type PCD is to visit this variable.
1376 @param VariableGuid Guid of variable which stored value of a HII-type PCD.
1377 @param VariableName Unicode name of variable which stored value of a HII-type PCD.
1378 @param SetAttributes Attributes bitmask to set for the variable.
1379 @param Data Value want to be set.
1380 @param DataSize Size of value
1381 @param Offset Value offset of HII-type PCD in variable.
1383 @return status of GetVariable()/SetVariable().
1388 IN EFI_GUID
*VariableGuid
,
1389 IN UINT16
*VariableName
,
1390 IN UINT32 SetAttributes
,
1391 IN CONST VOID
*Data
,
1406 // Try to get original variable size information.
1408 Status
= gRT
->GetVariable (
1409 (UINT16
*)VariableName
,
1416 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1418 // Patch new PCD's value to offset in given HII variable.
1420 if (Size
>= (DataSize
+ Offset
)) {
1423 SetSize
= DataSize
+ Offset
;
1425 Buffer
= AllocatePool (SetSize
);
1426 ASSERT (Buffer
!= NULL
);
1428 Status
= gRT
->GetVariable (
1436 ASSERT_EFI_ERROR (Status
);
1438 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1440 if (SetAttributes
== 0) {
1441 SetAttributes
= Attribute
;
1444 Status
= gRT
->SetVariable (
1454 } else if (Status
== EFI_NOT_FOUND
) {
1456 // If variable does not exist, a new variable need to be created.
1459 Size
= Offset
+ DataSize
;
1461 Buffer
= AllocateZeroPool (Size
);
1462 ASSERT (Buffer
!= NULL
);
1464 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1466 if (SetAttributes
== 0) {
1467 SetAttributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1470 Status
= gRT
->SetVariable (
1483 // If we drop to here, the value is failed to be written in to variable area.
1489 Get Token Number according to dynamic-ex PCD's {token space guid:token number}
1491 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
1492 in DEC file. PCD database maintain a mapping table that translate pair of {token
1493 space guid: token number} to Token Number.
1495 @param Guid Token space guid for dynamic-ex PCD entry.
1496 @param ExTokenNumber Dynamic-ex PCD token number.
1498 @return Token Number for dynamic-ex PCD.
1502 GetExPcdTokenNumber (
1503 IN CONST EFI_GUID
*Guid
,
1504 IN UINT32 ExTokenNumber
1508 DYNAMICEX_MAPPING
*ExMap
;
1509 EFI_GUID
*GuidTable
;
1510 EFI_GUID
*MatchGuid
;
1513 if (!mPeiDatabaseEmpty
) {
1514 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->ExMapTableOffset
);
1515 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1517 MatchGuid
= ScanGuid (GuidTable
, mPeiGuidTableSize
, Guid
);
1519 if (MatchGuid
!= NULL
) {
1521 MatchGuidIdx
= MatchGuid
- GuidTable
;
1523 for (Index
= 0; Index
< mPcdDatabase
.PeiDb
->ExTokenCount
; Index
++) {
1524 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1525 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1526 return ExMap
[Index
].TokenNumber
;
1532 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->ExMapTableOffset
);
1533 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1535 MatchGuid
= ScanGuid (GuidTable
, mDxeGuidTableSize
, Guid
);
1537 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
1538 // error in the BUILD system.
1540 ASSERT (MatchGuid
!= NULL
);
1542 MatchGuidIdx
= MatchGuid
- GuidTable
;
1544 for (Index
= 0; Index
< mPcdDatabase
.DxeDb
->ExTokenCount
; Index
++) {
1545 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1546 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1547 return ExMap
[Index
].TokenNumber
;
1557 Get SKU ID table from PCD database.
1559 @param LocalTokenNumberTableIdx Index of local token number in token number table.
1560 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1561 If FALSE, the pcd entry is initialized in DXE phase.
1562 @return Pointer to SKU ID array table
1567 IN UINTN LocalTokenNumberTableIdx
,
1572 UINTN LocalTokenNumber
;
1576 LocalTokenNumber
= *((UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
) + LocalTokenNumberTableIdx
);
1577 Database
= (UINT8
*) mPcdDatabase
.PeiDb
;
1579 LocalTokenNumber
= *((UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
) + LocalTokenNumberTableIdx
);
1580 Database
= (UINT8
*) mPcdDatabase
.DxeDb
;
1583 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
1585 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
1587 return (SKU_ID
*) (Database
+ SkuHead
->SkuIdTableOffset
);
1592 Wrapper function of getting index of PCD entry in size table.
1594 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1595 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1596 If FALSE, the pcd entry is initialized in DXE phase.
1598 @return index of PCD entry in size table.
1602 IN UINTN LocalTokenNumberTableIdx
,
1606 UINT32
*LocalTokenNumberTable
;
1607 UINTN LocalTokenNumber
;
1613 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1615 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1620 for (Index
= 0; Index
< LocalTokenNumberTableIdx
; Index
++) {
1621 LocalTokenNumber
= LocalTokenNumberTable
[Index
];
1623 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
1625 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1628 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1630 // We have only two entry for VPD enabled PCD entry:
1633 // Current size is equal to MAX size.
1637 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1639 // We have only two entry for Non-Sku enabled PCD entry:
1646 // We have these entry for SKU enabled PCD entry
1648 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1650 SkuIdTable
= GetSkuIdArray (Index
, IsPeiDb
);
1651 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
1658 return SizeTableIdx
;
1662 Get size of POINTER type PCD value.
1664 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1665 @param MaxSize Maxmium size of POINTER type PCD value.
1667 @return size of POINTER type PCD value.
1672 IN UINTN LocalTokenNumberTableIdx
,
1677 UINTN LocalTokenNumber
;
1679 SIZE_INFO
*SizeTable
;
1682 UINT32
*LocalTokenNumberTable
;
1684 // EBC compiler is very choosy. It may report warning about comparison
1685 // between UINTN and 0 . So we add 1 in each size of the
1687 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1691 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1692 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1694 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1695 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1696 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1699 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1701 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1703 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1705 *MaxSize
= SizeTable
[SizeTableIdx
];
1707 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1710 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1712 // We have only two entry for VPD enabled PCD entry:
1715 // We consider current size is equal to MAX size.
1719 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1721 // We have only two entry for Non-Sku enabled PCD entry:
1725 return SizeTable
[SizeTableIdx
+ 1];
1728 // We have these entry for SKU enabled PCD entry
1730 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1732 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, IsPeiDb
);
1733 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
1734 if (SkuIdTable
[1 + Index
] == mPcdDatabase
.DxeDb
->SystemSkuId
) {
1735 return SizeTable
[SizeTableIdx
+ 1 + Index
];
1738 return SizeTable
[SizeTableIdx
+ 1];
1744 Set size of POINTER type PCD value. The size should not exceed the maximum size
1747 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1748 @param CurrentSize Size of POINTER type PCD value.
1750 @retval TRUE Success to set size of PCD value.
1751 @retval FALSE Fail to set size of PCD value.
1755 IN UINTN LocalTokenNumberTableIdx
,
1756 IN OUT UINTN
*CurrentSize
1760 UINTN LocalTokenNumber
;
1762 SIZE_INFO
*SizeTable
;
1766 UINT32
*LocalTokenNumberTable
;
1769 // EBC compiler is very choosy. It may report warning about comparison
1770 // between UINTN and 0 . So we add 1 in each size of the
1773 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1776 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1777 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1779 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1780 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1781 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1784 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1786 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1788 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1790 MaxSize
= SizeTable
[SizeTableIdx
];
1792 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1795 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1797 // We shouldn't come here as we don't support SET for VPD
1802 if ((*CurrentSize
> MaxSize
) ||
1803 (*CurrentSize
== MAX_ADDRESS
)) {
1804 *CurrentSize
= MaxSize
;
1808 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1810 // We have only two entry for Non-Sku enabled PCD entry:
1814 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
1818 // We have these entry for SKU enabled PCD entry
1820 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1822 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, IsPeiDb
);
1823 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
1824 if (SkuIdTable
[1 + Index
] == mPcdDatabase
.DxeDb
->SystemSkuId
) {
1825 SizeTable
[SizeTableIdx
+ 1 + Index
] = (SIZE_INFO
) *CurrentSize
;
1829 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
1836 VariableLock DynamicHiiPcd.
1838 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1839 If FALSE, the pcd entry is initialized in DXE phase.
1840 @param[in] VariableLock Pointer to VariableLockProtocol.
1844 VariableLockDynamicHiiPcd (
1846 IN EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
1850 PCD_DATABASE_INIT
*Database
;
1851 UINT32 LocalTokenCount
;
1853 UINT32 LocalTokenNumber
;
1855 EFI_GUID
*GuidTable
;
1857 VARIABLE_HEAD
*VariableHead
;
1861 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
1862 LocalTokenCount
= IsPeiDb
? mPeiLocalTokenCount
: mDxeLocalTokenCount
;
1865 // Go through PCD database to find out DynamicHii PCDs.
1867 for (TokenNumber
= 1; TokenNumber
<= LocalTokenCount
; TokenNumber
++) {
1869 LocalTokenNumber
= GetLocalTokenNumber (TRUE
, TokenNumber
);
1871 LocalTokenNumber
= GetLocalTokenNumber (FALSE
, TokenNumber
+ mPeiLocalTokenCount
);
1873 if ((LocalTokenNumber
& PCD_TYPE_HII
) != 0) {
1874 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1875 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*) Database
+ Offset
);
1877 // Why not to set property by VarCheckProtocol with Attributes and Property directly here?
1878 // It is because that set property by VarCheckProtocol will indicate the variable to
1879 // be a system variable, but the unknown max size of the variable is dangerous to
1880 // the system variable region.
1882 if ((VariableHead
->Property
& VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY
) != 0) {
1884 // DynamicHii PCD with RO property set in *.dsc.
1886 StringTable
= (UINT8
*) ((UINT8
*) Database
+ Database
->StringTableOffset
);
1887 GuidTable
= (EFI_GUID
*) ((UINT8
*) Database
+ Database
->GuidTableOffset
);
1888 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1889 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1890 Status
= VariableLock
->RequestToLock (VariableLock
, Name
, Guid
);
1891 ASSERT_EFI_ERROR (Status
);
1898 VariableLockProtocol callback
1899 to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
1901 @param[in] Event Event whose notification function is being invoked.
1902 @param[in] Context Pointer to the notification function's context.
1907 VariableLockCallBack (
1913 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
1915 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
1916 if (!EFI_ERROR (Status
)) {
1917 VariableLockDynamicHiiPcd (TRUE
, VariableLock
);
1918 VariableLockDynamicHiiPcd (FALSE
, VariableLock
);