2 Help functions used by PCD DXE driver.
4 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/DxeServicesLib.h>
20 PCD_DATABASE mPcdDatabase
;
22 UINT32 mPcdTotalTokenCount
;
23 UINT32 mPeiLocalTokenCount
;
24 UINT32 mDxeLocalTokenCount
;
25 UINT32 mPeiNexTokenCount
;
26 UINT32 mDxeNexTokenCount
;
27 UINT32 mPeiExMapppingTableSize
;
28 UINT32 mDxeExMapppingTableSize
;
29 UINT32 mPeiGuidTableSize
;
30 UINT32 mDxeGuidTableSize
;
32 BOOLEAN mPeiExMapTableEmpty
;
33 BOOLEAN mDxeExMapTableEmpty
;
34 BOOLEAN mPeiDatabaseEmpty
;
36 LIST_ENTRY
*mCallbackFnTable
;
37 EFI_GUID
**TmpTokenSpaceBuffer
;
38 UINTN TmpTokenSpaceBufferCount
;
40 UINTN mPeiPcdDbSize
= 0;
41 PEI_PCD_DATABASE
*mPeiPcdDbBinary
= NULL
;
42 UINTN mDxePcdDbSize
= 0;
43 DXE_PCD_DATABASE
*mDxePcdDbBinary
= NULL
;
46 Get Local Token Number by Token Number.
48 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
49 If FALSE, the pcd entry is initialized in DXE phase.
50 @param[in] TokenNumber The PCD token number.
52 @return Local Token Number.
60 UINT32
*LocalTokenNumberTable
;
63 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
64 // We have to decrement TokenNumber by 1 to make it usable
65 // as the array index.
69 LocalTokenNumberTable
= IsPeiDb
? (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
) :
70 (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
71 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
73 return LocalTokenNumberTable
[TokenNumber
];
77 Get PCD type by Local Token Number.
79 @param[in] LocalTokenNumber The PCD local token number.
85 IN UINT32 LocalTokenNumber
88 switch (LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) {
89 case PCD_DATUM_TYPE_POINTER
:
90 return EFI_PCD_TYPE_PTR
;
91 case PCD_DATUM_TYPE_UINT8
:
92 if ((LocalTokenNumber
& PCD_DATUM_TYPE_UINT8_BOOLEAN
) == PCD_DATUM_TYPE_UINT8_BOOLEAN
) {
93 return EFI_PCD_TYPE_BOOL
;
95 return EFI_PCD_TYPE_8
;
97 case PCD_DATUM_TYPE_UINT16
:
98 return EFI_PCD_TYPE_16
;
99 case PCD_DATUM_TYPE_UINT32
:
100 return EFI_PCD_TYPE_32
;
101 case PCD_DATUM_TYPE_UINT64
:
102 return EFI_PCD_TYPE_64
;
105 return EFI_PCD_TYPE_8
;
112 @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.
113 If FALSE, need to get the full PCD name.
114 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
115 If FALSE, the pcd entry is initialized in DXE phase.
116 @param[in] TokenNumber The PCD token number.
118 @return The TokenSpaceCName or full PCD name.
122 IN BOOLEAN OnlyTokenSpaceName
,
127 PCD_DATABASE_INIT
*Database
;
130 PCD_NAME_INDEX
*PcdNameIndex
;
131 CHAR8
*TokenSpaceName
;
136 // Return NULL when PCD name table is absent.
139 if (mPcdDatabase
.PeiDb
->PcdNameTableOffset
== 0) {
143 if (mPcdDatabase
.DxeDb
->PcdNameTableOffset
== 0) {
149 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
150 // We have to decrement TokenNumber by 1 to make it usable
151 // as the array index.
155 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
156 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
158 StringTable
= (UINT8
*) Database
+ Database
->StringTableOffset
;
161 // Get the PCD name index.
163 PcdNameIndex
= (PCD_NAME_INDEX
*)((UINT8
*) Database
+ Database
->PcdNameTableOffset
) + TokenNumber
;
164 TokenSpaceName
= (CHAR8
*)&StringTable
[PcdNameIndex
->TokenSpaceCNameIndex
];
165 PcdName
= (CHAR8
*)&StringTable
[PcdNameIndex
->PcdCNameIndex
];
167 if (OnlyTokenSpaceName
) {
169 // Only need to get the TokenSpaceCName.
171 Name
= AllocateCopyPool (AsciiStrSize (TokenSpaceName
), TokenSpaceName
);
174 // Need to get the full PCD name.
176 NameSize
= AsciiStrSize (TokenSpaceName
) + AsciiStrSize (PcdName
);
177 Name
= AllocateZeroPool (NameSize
);
178 ASSERT (Name
!= NULL
);
180 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
182 AsciiStrCatS (Name
, NameSize
, TokenSpaceName
);
183 Name
[AsciiStrSize (TokenSpaceName
) - sizeof (CHAR8
)] = '.';
184 AsciiStrCatS (Name
, NameSize
, PcdName
);
191 Retrieve additional information associated with a PCD token.
193 This includes information such as the type of value the TokenNumber is associated with as well as possible
194 human readable name that is associated with the token.
196 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
197 If FALSE, the pcd entry is initialized in DXE phase.
198 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
199 @param[in] TokenNumber The PCD token number.
200 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
201 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
203 @retval EFI_SUCCESS The PCD information was returned successfully
204 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
209 IN CONST EFI_GUID
*Guid
,
210 IN UINTN TokenNumber
,
211 OUT EFI_PCD_INFO
*PcdInfo
214 PCD_DATABASE_INIT
*Database
;
218 DYNAMICEX_MAPPING
*ExMapTable
;
220 UINT32 LocalTokenNumber
;
222 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
224 GuidTable
= (EFI_GUID
*)((UINT8
*)Database
+ Database
->GuidTableOffset
);
225 MatchGuid
= ScanGuid (GuidTable
, Database
->GuidTableCount
* sizeof(EFI_GUID
), Guid
);
227 if (MatchGuid
== NULL
) {
228 return EFI_NOT_FOUND
;
231 GuidTableIdx
= MatchGuid
- GuidTable
;
233 ExMapTable
= (DYNAMICEX_MAPPING
*)((UINT8
*)Database
+ Database
->ExMapTableOffset
);
236 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
238 for (Index
= 0; Index
< Database
->ExTokenCount
; Index
++) {
239 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
240 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
242 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
243 // PcdSize to 0 and PcdName to the null-terminated ASCII string
244 // associated with the token's namespace Guid.
246 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
247 PcdInfo
->PcdSize
= 0;
249 // Here use one representative in the token space to get the TokenSpaceCName.
251 PcdInfo
->PcdName
= GetPcdName (TRUE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
253 } else if (ExMapTable
[Index
].ExTokenNumber
== TokenNumber
) {
254 PcdInfo
->PcdSize
= DxePcdGetSize (ExMapTable
[Index
].TokenNumber
);
255 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
256 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
257 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
263 return EFI_NOT_FOUND
;
267 Retrieve additional information associated with a PCD token.
269 This includes information such as the type of value the TokenNumber is associated with as well as possible
270 human readable name that is associated with the token.
272 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
273 @param[in] TokenNumber The PCD token number.
274 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
275 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
277 @retval EFI_SUCCESS The PCD information was returned successfully.
278 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
282 IN CONST EFI_GUID
*Guid
,
283 IN UINTN TokenNumber
,
284 OUT EFI_PCD_INFO
*PcdInfo
288 BOOLEAN PeiExMapTableEmpty
;
289 BOOLEAN DxeExMapTableEmpty
;
290 UINT32 LocalTokenNumber
;
293 ASSERT (PcdInfo
!= NULL
);
295 Status
= EFI_NOT_FOUND
;
296 PeiExMapTableEmpty
= mPeiExMapTableEmpty
;
297 DxeExMapTableEmpty
= mDxeExMapTableEmpty
;
300 if (((TokenNumber
+ 1 > mPeiNexTokenCount
+ 1) && (TokenNumber
+ 1 <= mPeiLocalTokenCount
+ 1)) ||
301 ((TokenNumber
+ 1 > (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1)))) {
302 return EFI_NOT_FOUND
;
303 } else if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
305 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
306 // PcdSize to 0 and PcdName to NULL for default Token Space.
308 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
309 PcdInfo
->PcdSize
= 0;
310 PcdInfo
->PcdName
= NULL
;
312 PcdInfo
->PcdSize
= DxePcdGetSize (TokenNumber
);
314 if ((TokenNumber
+ 1 <= mPeiNexTokenCount
+ 1)) {
317 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
);
318 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
319 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, TokenNumber
);
324 if (PeiExMapTableEmpty
&& DxeExMapTableEmpty
) {
325 return EFI_NOT_FOUND
;
328 if (!PeiExMapTableEmpty
) {
329 Status
= ExGetPcdInfo (
337 if (Status
== EFI_SUCCESS
) {
341 if (!DxeExMapTableEmpty
) {
342 Status
= ExGetPcdInfo (
354 Get the PCD entry pointer in PCD database.
356 This routine will visit PCD database to find the PCD entry according to given
357 token number. The given token number is autogened by build tools and it will be
358 translated to local token number. Local token number contains PCD's type and
359 offset of PCD entry in PCD database.
361 @param TokenNumber Token's number, it is autogened by build tools
362 @param GetSize The size of token's value
364 @return PCD entry pointer in PCD database
369 IN UINTN TokenNumber
,
377 VARIABLE_HEAD
*VariableHead
;
378 UINT8
*VaraiableDefaultBuffer
;
383 UINTN TmpTokenNumber
;
386 UINT32 LocalTokenNumber
;
388 STRING_HEAD StringTableIdx
;
392 // Aquire lock to prevent reentrance from TPL_CALLBACK level
394 EfiAcquireLock (&mPcdDatabaseLock
);
398 ASSERT (TokenNumber
> 0);
400 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
401 // We have to decrement TokenNumber by 1 to make it usable
402 // as the array index.
406 TmpTokenNumber
= TokenNumber
;
409 // EBC compiler is very choosy. It may report warning about comparison
410 // between UINTN and 0 . So we add 1 in each size of the
413 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
415 ASSERT ((GetSize
== DxePcdGetSize (TokenNumber
+ 1)) || (GetSize
== 0));
417 // EBC compiler is very choosy. It may report warning about comparison
418 // between UINTN and 0 . So we add 1 in each size of the
420 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
422 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
424 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
427 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
429 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
433 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
435 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
437 VpdHead
= (VPD_HEAD
*) ((UINT8
*) PcdDb
+ Offset
);
438 ASSERT (mVpdBaseAddress
!= 0);
439 RetPtr
= (VOID
*) (mVpdBaseAddress
+ 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
) && (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
)) {
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.
743 // Search the External Pcd database from one section of current FFS,
744 // and read it to memory
746 Status
= GetSectionFromFfs (
749 (VOID
**) &mDxePcdDbBinary
,
752 ASSERT_EFI_ERROR (Status
);
755 // Check the first bytes (Header Signature Guid) and build version.
757 if (!CompareGuid ((VOID
*)mDxePcdDbBinary
, &gPcdDataBaseSignatureGuid
) ||
758 (mDxePcdDbBinary
->BuildVersion
!= PCD_SERVICE_DXE_VERSION
)) {
762 return mDxePcdDbBinary
;
766 Update PCD database base on current SkuId
768 @param SkuId Current SkuId
769 @param IsPeiDb Whether to update PEI PCD database.
771 @retval EFI_SUCCESS Update PCD database successfully.
772 @retval EFI_NOT_FOUND Not found PCD database for current SkuId.
781 PCD_DATABASE_SKU_DELTA
*SkuDelta
;
782 PCD_DATA_DELTA
*SkuDeltaData
;
784 if (IsPeiDb
&& mPeiPcdDbBinary
!= NULL
) {
786 // Find the delta data for PEI DB
788 Index
= (mPcdDatabase
.PeiDb
->Length
+ 7) & (~7);
790 while (Index
< mPeiPcdDbSize
) {
791 SkuDelta
= (PCD_DATABASE_SKU_DELTA
*) ((UINT8
*) mPeiPcdDbBinary
+ Index
);
792 if (SkuDelta
->SkuId
== SkuId
&& SkuDelta
->SkuIdCompared
== 0) {
795 Index
= (Index
+ SkuDelta
->Length
+ 7) & (~7);
799 // Patch the delta data into current PCD database
801 if (Index
< mPeiPcdDbSize
&& SkuDelta
!= NULL
) {
802 SkuDeltaData
= (PCD_DATA_DELTA
*) (SkuDelta
+ 1);
803 while ((UINT8
*) SkuDeltaData
< (UINT8
*) SkuDelta
+ SkuDelta
->Length
) {
804 *((UINT8
*) mPcdDatabase
.PeiDb
+ SkuDeltaData
->Offset
) = (UINT8
) SkuDeltaData
->Value
;
808 return EFI_NOT_FOUND
;
813 // Find the delta data for DXE DB
815 Index
= (mPcdDatabase
.DxeDb
->Length
+ 7) & (~7);
817 while (Index
< mDxePcdDbSize
) {
818 SkuDelta
= (PCD_DATABASE_SKU_DELTA
*) ((UINT8
*) mDxePcdDbBinary
+ Index
);
819 if (SkuDelta
->SkuId
== SkuId
&& SkuDelta
->SkuIdCompared
== 0) {
822 Index
= (Index
+ SkuDelta
->Length
+ 7) & (~7);
826 // Patch the delta data into current PCD database
828 if (Index
< mDxePcdDbSize
&& SkuDelta
!= NULL
) {
829 SkuDeltaData
= (PCD_DATA_DELTA
*) (SkuDelta
+ 1);
830 while ((UINT8
*) SkuDeltaData
< (UINT8
*) SkuDelta
+ SkuDelta
->Length
) {
831 *((UINT8
*) mPcdDatabase
.DxeDb
+ SkuDeltaData
->Offset
) = (UINT8
) SkuDeltaData
->Value
;
837 return EFI_NOT_FOUND
;
841 Initialize the PCD database in DXE phase.
843 PCD database in DXE phase also contains PCD database in PEI phase which is copied
848 BuildPcdDxeDataBase (
852 PEI_PCD_DATABASE
*PeiDatabase
;
853 EFI_HOB_GUID_TYPE
*GuidHob
;
860 // Assign PCD Entries with default value to PCD DATABASE
862 mPcdDatabase
.DxeDb
= LocateExPcdBinary ();
863 ASSERT(mPcdDatabase
.DxeDb
!= NULL
);
864 PcdDxeDbLen
= mPcdDatabase
.DxeDb
->Length
+ mPcdDatabase
.DxeDb
->UninitDataBaseSize
;
865 PcdDxeDb
= AllocateZeroPool (PcdDxeDbLen
);
866 ASSERT (PcdDxeDb
!= NULL
);
867 CopyMem (PcdDxeDb
, mPcdDatabase
.DxeDb
, mPcdDatabase
.DxeDb
->Length
);
868 mPcdDatabase
.DxeDb
= PcdDxeDb
;
870 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
871 if (GuidHob
!= NULL
) {
874 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
875 // should not be included at all. So the GuidHob could
876 // be NULL. If it is NULL, we just copy over the DXE Default
877 // Value to PCD Database.
879 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
882 // Get next one that stores full PEI data
884 GuidHob
= GetNextGuidHob (&gPcdDataBaseHobGuid
, GET_NEXT_HOB (GuidHob
));
885 if (GuidHob
!= NULL
) {
886 mPeiPcdDbBinary
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
887 mPeiPcdDbSize
= (UINTN
) GET_GUID_HOB_DATA_SIZE (GuidHob
);
891 // Assign PCD Entries refereneced in PEI phase to PCD DATABASE
893 mPcdDatabase
.PeiDb
= PeiDatabase
;
895 // Inherit the SystemSkuId from PEI phase.
897 if (mPcdDatabase
.PeiDb
->SystemSkuId
!= 0) {
898 Status
= UpdatePcdDatabase (mPcdDatabase
.PeiDb
->SystemSkuId
, FALSE
);
899 ASSERT_EFI_ERROR (Status
);
901 mPcdDatabase
.DxeDb
->SystemSkuId
= mPcdDatabase
.PeiDb
->SystemSkuId
;
903 mPcdDatabase
.PeiDb
= AllocateZeroPool (sizeof (PEI_PCD_DATABASE
));
904 ASSERT(mPcdDatabase
.PeiDb
!= NULL
);
908 // Initialized the external PCD database local variables
910 mPeiLocalTokenCount
= mPcdDatabase
.PeiDb
->LocalTokenCount
;
911 mDxeLocalTokenCount
= mPcdDatabase
.DxeDb
->LocalTokenCount
;
913 mPeiExMapppingTableSize
= mPcdDatabase
.PeiDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
914 mDxeExMapppingTableSize
= mPcdDatabase
.DxeDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
915 mPeiGuidTableSize
= mPcdDatabase
.PeiDb
->GuidTableCount
* sizeof(GUID
);
916 mDxeGuidTableSize
= mPcdDatabase
.DxeDb
->GuidTableCount
* sizeof (GUID
);
918 mPcdTotalTokenCount
= mPeiLocalTokenCount
+ mDxeLocalTokenCount
;
919 mPeiNexTokenCount
= mPeiLocalTokenCount
- mPcdDatabase
.PeiDb
->ExTokenCount
;
920 mDxeNexTokenCount
= mDxeLocalTokenCount
- mPcdDatabase
.DxeDb
->ExTokenCount
;
922 mPeiExMapTableEmpty
= (mPcdDatabase
.PeiDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
923 mDxeExMapTableEmpty
= (mPcdDatabase
.DxeDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
924 mPeiDatabaseEmpty
= (mPeiLocalTokenCount
== 0) ? TRUE
: FALSE
;
926 TmpTokenSpaceBufferCount
= mPcdDatabase
.PeiDb
->ExTokenCount
+ mPcdDatabase
.DxeDb
->ExTokenCount
;
927 TmpTokenSpaceBuffer
= (EFI_GUID
**)AllocateZeroPool(TmpTokenSpaceBufferCount
* sizeof (EFI_GUID
*));
930 // Initialized the Callback Function Table
932 mCallbackFnTable
= AllocateZeroPool (mPcdTotalTokenCount
* sizeof (LIST_ENTRY
));
933 ASSERT(mCallbackFnTable
!= NULL
);
936 // EBC compiler is very choosy. It may report warning about comparison
937 // between UINTN and 0 . So we add 1 in each size of the
940 for (Index
= 0; Index
+ 1 < mPcdTotalTokenCount
+ 1; Index
++) {
941 InitializeListHead (&mCallbackFnTable
[Index
]);
946 Get Variable which contains HII type PCD entry.
948 @param VariableGuid Variable's guid
949 @param VariableName Variable's unicode name string
950 @param VariableData Variable's data pointer,
951 @param VariableSize Variable's size.
953 @return the status of gRT->GetVariable
957 IN EFI_GUID
*VariableGuid
,
958 IN UINT16
*VariableName
,
959 OUT UINT8
**VariableData
,
960 OUT UINTN
*VariableSize
971 // Firstly get the real size of HII variable
973 Status
= gRT
->GetVariable (
974 (UINT16
*)VariableName
,
982 // Allocate buffer to hold whole variable data according to variable size.
984 if (Status
== EFI_BUFFER_TOO_SMALL
) {
985 Buffer
= (UINT8
*) AllocatePool (Size
);
987 ASSERT (Buffer
!= NULL
);
989 Status
= gRT
->GetVariable (
997 ASSERT (Status
== EFI_SUCCESS
);
998 *VariableData
= Buffer
;
999 *VariableSize
= Size
;
1002 // Use Default Data only when variable is not found.
1003 // For other error status, correct data can't be got, and trig ASSERT().
1005 ASSERT (Status
== EFI_NOT_FOUND
);
1012 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
1013 has registered callback function.
1015 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
1017 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
1019 @param TokenNumber PCD token number generated by build tools.
1020 @param Data Value want to be set for this PCD entry
1021 @param Size The size of value
1025 InvokeCallbackOnSet (
1026 UINT32 ExTokenNumber
,
1027 CONST EFI_GUID
*Guid
, OPTIONAL
1033 CALLBACK_FN_ENTRY
*FnTableEntry
;
1034 LIST_ENTRY
*ListHead
;
1035 LIST_ENTRY
*ListNode
;
1038 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1039 // We have to decrement TokenNumber by 1 to make it usable
1040 // as the array index of mCallbackFnTable[].
1042 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
1043 ListNode
= GetFirstNode (ListHead
);
1045 while (ListNode
!= ListHead
) {
1046 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE (ListNode
, CALLBACK_FN_ENTRY
, Node
);
1048 FnTableEntry
->CallbackFn(Guid
,
1049 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
1053 ListNode
= GetNextNode (ListHead
, ListNode
);
1061 Wrapper function for setting non-pointer type value for a PCD entry.
1063 @param TokenNumber Pcd token number autogenerated by build tools.
1064 @param Data Value want to be set for PCD entry
1065 @param Size Size of value.
1067 @return status of SetWorker.
1072 IN UINTN TokenNumber
,
1077 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
1082 Set value for an PCD entry
1084 @param TokenNumber Pcd token number autogenerated by build tools.
1085 @param Data Value want to be set for PCD entry
1086 @param Size Size of value.
1087 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
1088 If False, the type of PCD entry's value is not Pointer.
1090 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
1091 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
1092 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
1093 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
1094 range of UINT8, UINT16, UINT32, UINT64
1095 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
1099 IN UINTN TokenNumber
,
1106 UINT32 LocalTokenNumber
;
1107 EFI_GUID
*GuidTable
;
1111 UINTN VariableOffset
;
1114 VARIABLE_HEAD
*VariableHead
;
1119 UINTN TmpTokenNumber
;
1122 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1123 // We have to decrement TokenNumber by 1 to make it usable
1124 // as the array index.
1128 TmpTokenNumber
= TokenNumber
;
1131 // EBC compiler is very choosy. It may report warning about comparison
1132 // between UINTN and 0 . So we add 1 in each size of the
1135 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
1139 // Get MaxSize first, then check new size with max buffer size.
1141 GetPtrTypeSize (TokenNumber
, &MaxSize
);
1142 if (*Size
> MaxSize
) {
1144 return EFI_INVALID_PARAMETER
;
1147 if (*Size
!= DxePcdGetSize (TokenNumber
+ 1)) {
1148 return EFI_INVALID_PARAMETER
;
1153 // EBC compiler is very choosy. It may report warning about comparison
1154 // between UINTN and 0 . So we add 1 in each size of the
1157 if ((TokenNumber
+ 1 < mPeiNexTokenCount
+ 1) ||
1158 (TokenNumber
+ 1 >= mPeiLocalTokenCount
+ 1 && TokenNumber
+ 1 < (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1))) {
1159 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
1163 // Aquire lock to prevent reentrance from TPL_CALLBACK level
1165 EfiAcquireLock (&mPcdDatabaseLock
);
1168 // EBC compiler is very choosy. It may report warning about comparison
1169 // between UINTN and 0 . So we add 1 in each size of the
1172 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
1174 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
1176 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1178 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
1181 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
1183 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
1187 InternalData
= PcdDb
+ Offset
;
1189 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
1192 Status
= EFI_INVALID_PARAMETER
;
1195 case PCD_TYPE_STRING
:
1196 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1197 CopyMem (StringTable
+ *((STRING_HEAD
*)InternalData
), Data
, *Size
);
1198 Status
= EFI_SUCCESS
;
1200 Status
= EFI_INVALID_PARAMETER
;
1204 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
1207 if (!SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1208 Status
= EFI_INVALID_PARAMETER
;
1214 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1216 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1219 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
1221 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1222 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1223 VariableOffset
= VariableHead
->Offset
;
1224 Attributes
= VariableHead
->Attributes
;
1225 Status
= SetHiiVariable (Guid
, Name
, Attributes
, Data
, *Size
, VariableOffset
);
1230 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1231 CopyMem (InternalData
, Data
, *Size
);
1232 Status
= EFI_SUCCESS
;
1234 Status
= EFI_INVALID_PARAMETER
;
1239 Status
= EFI_SUCCESS
;
1242 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
1245 case sizeof(UINT16
):
1246 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
1249 case sizeof(UINT32
):
1250 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
1253 case sizeof(UINT64
):
1254 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
1259 Status
= EFI_NOT_FOUND
;
1266 Status
= EFI_NOT_FOUND
;
1270 EfiReleaseLock (&mPcdDatabaseLock
);
1276 Wrapper function for get PCD value for dynamic-ex PCD.
1278 @param Guid Token space guid for dynamic-ex PCD.
1279 @param ExTokenNumber Token number for dynamic-ex PCD.
1280 @param GetSize The size of dynamic-ex PCD value.
1282 @return PCD entry in PCD database.
1287 IN CONST EFI_GUID
*Guid
,
1288 IN UINTN ExTokenNumber
,
1292 return GetWorker(GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
), GetSize
);
1296 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
1298 @param ExTokenNumber Token number for dynamic-ex PCD.
1299 @param Guid Token space guid for dynamic-ex PCD.
1300 @param Data Value want to be set.
1301 @param SetSize The size of value.
1303 @return status of ExSetWorker().
1308 IN UINTN ExTokenNumber
,
1309 IN CONST EFI_GUID
*Guid
,
1314 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &SetSize
, FALSE
);
1318 Set value for a dynamic-ex PCD entry.
1320 This routine find the local token number according to dynamic-ex PCD's token
1321 space guid and token number firstly, and invoke callback function if this PCD
1322 entry registered callback function. Finally, invoken general SetWorker to set
1325 @param ExTokenNumber Dynamic-ex PCD token number.
1326 @param Guid Token space guid for dynamic-ex PCD.
1327 @param Data PCD value want to be set
1328 @param SetSize Size of value.
1329 @param PtrType If TRUE, this PCD entry is pointer type.
1330 If FALSE, this PCD entry is not pointer type.
1332 @return status of SetWorker().
1337 IN UINTN ExTokenNumber
,
1338 IN CONST EFI_GUID
*Guid
,
1340 IN OUT UINTN
*SetSize
,
1346 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
);
1348 InvokeCallbackOnSet ((UINT32
) ExTokenNumber
, Guid
, TokenNumber
, Data
, *SetSize
);
1350 return SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
1355 Get variable size and data from HII-type PCDs.
1357 @param[in] VariableGuid Guid of variable which stored value of a HII-type PCD.
1358 @param[in] VariableName Unicode name of variable which stored value of a HII-type PCD.
1359 @param[out] VariableSize Pointer to variable size got from HII-type PCDs.
1360 @param[out] VariableData Pointer to variable data got from HII-type PCDs.
1364 GetVariableSizeAndDataFromHiiPcd (
1365 IN EFI_GUID
*VariableGuid
,
1366 IN UINT16
*VariableName
,
1367 OUT UINTN
*VariableSize
,
1368 OUT VOID
*VariableData OPTIONAL
1372 PCD_DATABASE_INIT
*Database
;
1374 UINT32 LocalTokenNumber
;
1376 EFI_GUID
*GuidTable
;
1378 VARIABLE_HEAD
*VariableHead
;
1383 UINT8
*VaraiableDefaultBuffer
;
1384 STRING_HEAD StringTableIdx
;
1389 // Go through PCD database to find out DynamicHii PCDs.
1391 for (TokenNumber
= 1; TokenNumber
<= mPcdTotalTokenCount
; TokenNumber
++) {
1392 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
1393 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
1394 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
);
1395 if ((LocalTokenNumber
& PCD_TYPE_HII
) != 0) {
1397 // Get the Variable Guid and Name pointer.
1399 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1400 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*) Database
+ Offset
);
1401 StringTable
= (UINT8
*) ((UINT8
*) Database
+ Database
->StringTableOffset
);
1402 GuidTable
= (EFI_GUID
*) ((UINT8
*) Database
+ Database
->GuidTableOffset
);
1403 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1404 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1405 if (CompareGuid (VariableGuid
, Guid
) && (StrCmp (VariableName
, Name
) == 0)) {
1407 // It is the matched DynamicHii PCD.
1409 PcdDataSize
= DxePcdGetSize (TokenNumber
);
1410 Size
= VariableHead
->Offset
+ PcdDataSize
;
1411 if (Size
> *VariableSize
) {
1412 *VariableSize
= Size
;
1414 if (VariableData
!= NULL
) {
1415 if ((LocalTokenNumber
& PCD_TYPE_ALL_SET
) == (PCD_TYPE_HII
|PCD_TYPE_STRING
)) {
1417 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
1418 // string array in string table.
1420 StringTableIdx
= *(STRING_HEAD
*) ((UINT8
*) Database
+ VariableHead
->DefaultValueOffset
);
1421 VaraiableDefaultBuffer
= (UINT8
*) (StringTable
+ StringTableIdx
);
1423 VaraiableDefaultBuffer
= (UINT8
*) Database
+ VariableHead
->DefaultValueOffset
;
1425 CopyMem ((UINT8
*) VariableData
+ VariableHead
->Offset
, VaraiableDefaultBuffer
, PcdDataSize
);
1433 Set value for HII-type PCD.
1435 A HII-type PCD's value is stored in a variable. Setting/Getting the value of
1436 HII-type PCD is to visit this variable.
1438 @param VariableGuid Guid of variable which stored value of a HII-type PCD.
1439 @param VariableName Unicode name of variable which stored value of a HII-type PCD.
1440 @param SetAttributes Attributes bitmask to set for the variable.
1441 @param Data Value want to be set.
1442 @param DataSize Size of value
1443 @param Offset Value offset of HII-type PCD in variable.
1445 @return status of GetVariable()/SetVariable().
1450 IN EFI_GUID
*VariableGuid
,
1451 IN UINT16
*VariableName
,
1452 IN UINT32 SetAttributes
,
1453 IN CONST VOID
*Data
,
1468 // Try to get original variable size information.
1470 Status
= gRT
->GetVariable (
1471 (UINT16
*)VariableName
,
1478 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1480 // Patch new PCD's value to offset in given HII variable.
1482 if (Size
>= (DataSize
+ Offset
)) {
1485 SetSize
= DataSize
+ Offset
;
1487 Buffer
= AllocatePool (SetSize
);
1488 ASSERT (Buffer
!= NULL
);
1490 Status
= gRT
->GetVariable (
1498 ASSERT_EFI_ERROR (Status
);
1500 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1502 if (SetAttributes
== 0) {
1503 SetAttributes
= Attribute
;
1506 Status
= gRT
->SetVariable (
1516 } else if (Status
== EFI_NOT_FOUND
) {
1518 // If variable does not exist, a new variable need to be created.
1522 // Get size, allocate buffer and get data.
1524 GetVariableSizeAndDataFromHiiPcd (VariableGuid
, VariableName
, &Size
, NULL
);
1525 Buffer
= AllocateZeroPool (Size
);
1526 ASSERT (Buffer
!= NULL
);
1527 GetVariableSizeAndDataFromHiiPcd (VariableGuid
, VariableName
, &Size
, Buffer
);
1532 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1534 if (SetAttributes
== 0) {
1535 SetAttributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1538 Status
= gRT
->SetVariable (
1551 // If we drop to here, the value is failed to be written in to variable area.
1557 Get Token Number according to dynamic-ex PCD's {token space guid:token number}
1559 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
1560 in DEC file. PCD database maintain a mapping table that translate pair of {token
1561 space guid: token number} to Token Number.
1563 @param Guid Token space guid for dynamic-ex PCD entry.
1564 @param ExTokenNumber Dynamic-ex PCD token number.
1566 @return Token Number for dynamic-ex PCD.
1570 GetExPcdTokenNumber (
1571 IN CONST EFI_GUID
*Guid
,
1572 IN UINT32 ExTokenNumber
1576 DYNAMICEX_MAPPING
*ExMap
;
1577 EFI_GUID
*GuidTable
;
1578 EFI_GUID
*MatchGuid
;
1581 if (!mPeiDatabaseEmpty
) {
1582 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->ExMapTableOffset
);
1583 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1585 MatchGuid
= ScanGuid (GuidTable
, mPeiGuidTableSize
, Guid
);
1587 if (MatchGuid
!= NULL
) {
1589 MatchGuidIdx
= MatchGuid
- GuidTable
;
1591 for (Index
= 0; Index
< mPcdDatabase
.PeiDb
->ExTokenCount
; Index
++) {
1592 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1593 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1594 return ExMap
[Index
].TokenNumber
;
1600 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->ExMapTableOffset
);
1601 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1603 MatchGuid
= ScanGuid (GuidTable
, mDxeGuidTableSize
, Guid
);
1605 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
1606 // error in the BUILD system.
1608 ASSERT (MatchGuid
!= NULL
);
1610 MatchGuidIdx
= MatchGuid
- GuidTable
;
1612 for (Index
= 0; Index
< mPcdDatabase
.DxeDb
->ExTokenCount
; Index
++) {
1613 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1614 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1615 return ExMap
[Index
].TokenNumber
;
1625 Wrapper function of getting index of PCD entry in size table.
1627 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1628 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1629 If FALSE, the pcd entry is initialized in DXE phase.
1631 @return index of PCD entry in size table.
1635 IN UINTN LocalTokenNumberTableIdx
,
1639 UINT32
*LocalTokenNumberTable
;
1640 UINTN LocalTokenNumber
;
1645 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1647 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1652 for (Index
= 0; Index
< LocalTokenNumberTableIdx
; Index
++) {
1653 LocalTokenNumber
= LocalTokenNumberTable
[Index
];
1655 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
1657 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1660 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1662 // We have only two entry for VPD enabled PCD entry:
1665 // Current size is equal to MAX size.
1670 // We have only two entry for Non-Sku enabled PCD entry:
1680 return SizeTableIdx
;
1684 Get size of POINTER type PCD value.
1686 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1687 @param MaxSize Maxmium size of POINTER type PCD value.
1689 @return size of POINTER type PCD value.
1694 IN UINTN LocalTokenNumberTableIdx
,
1699 UINTN LocalTokenNumber
;
1700 SIZE_INFO
*SizeTable
;
1702 UINT32
*LocalTokenNumberTable
;
1704 // EBC compiler is very choosy. It may report warning about comparison
1705 // between UINTN and 0 . So we add 1 in each size of the
1707 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1711 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1712 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1714 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1715 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1716 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1719 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1721 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1723 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1725 *MaxSize
= SizeTable
[SizeTableIdx
];
1727 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1730 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1732 // We have only two entry for VPD enabled PCD entry:
1735 // We consider current size is equal to MAX size.
1740 // We have only two entry for Non-Sku enabled PCD entry:
1744 return SizeTable
[SizeTableIdx
+ 1];
1749 Set size of POINTER type PCD value. The size should not exceed the maximum size
1752 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1753 @param CurrentSize Size of POINTER type PCD value.
1755 @retval TRUE Success to set size of PCD value.
1756 @retval FALSE Fail to set size of PCD value.
1760 IN UINTN LocalTokenNumberTableIdx
,
1761 IN OUT UINTN
*CurrentSize
1765 UINTN LocalTokenNumber
;
1766 SIZE_INFO
*SizeTable
;
1769 UINT32
*LocalTokenNumberTable
;
1772 // EBC compiler is very choosy. It may report warning about comparison
1773 // between UINTN and 0 . So we add 1 in each size of the
1776 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1779 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1780 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1782 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1783 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1784 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1787 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1789 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1791 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1793 MaxSize
= SizeTable
[SizeTableIdx
];
1795 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1798 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1800 // We shouldn't come here as we don't support SET for VPD
1805 if ((*CurrentSize
> MaxSize
) ||
1806 (*CurrentSize
== MAX_ADDRESS
)) {
1807 *CurrentSize
= MaxSize
;
1812 // We have only two entry for Non-Sku enabled PCD entry:
1816 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
1822 VariableLock DynamicHiiPcd.
1824 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1825 If FALSE, the pcd entry is initialized in DXE phase.
1826 @param[in] VariableLock Pointer to VariableLockProtocol.
1830 VariableLockDynamicHiiPcd (
1832 IN EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
1836 PCD_DATABASE_INIT
*Database
;
1837 UINT32 LocalTokenCount
;
1839 UINT32 LocalTokenNumber
;
1841 EFI_GUID
*GuidTable
;
1843 VARIABLE_HEAD
*VariableHead
;
1847 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
1848 LocalTokenCount
= IsPeiDb
? mPeiLocalTokenCount
: mDxeLocalTokenCount
;
1851 // Go through PCD database to find out DynamicHii PCDs.
1853 for (TokenNumber
= 1; TokenNumber
<= LocalTokenCount
; TokenNumber
++) {
1855 LocalTokenNumber
= GetLocalTokenNumber (TRUE
, TokenNumber
);
1857 LocalTokenNumber
= GetLocalTokenNumber (FALSE
, TokenNumber
+ mPeiLocalTokenCount
);
1859 if ((LocalTokenNumber
& PCD_TYPE_HII
) != 0) {
1860 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1861 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*) Database
+ Offset
);
1863 // Why not to set property by VarCheckProtocol with Attributes and Property directly here?
1864 // It is because that set property by VarCheckProtocol will indicate the variable to
1865 // be a system variable, but the unknown max size of the variable is dangerous to
1866 // the system variable region.
1868 if ((VariableHead
->Property
& VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY
) != 0) {
1870 // DynamicHii PCD with RO property set in *.dsc.
1872 StringTable
= (UINT8
*) ((UINT8
*) Database
+ Database
->StringTableOffset
);
1873 GuidTable
= (EFI_GUID
*) ((UINT8
*) Database
+ Database
->GuidTableOffset
);
1874 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1875 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1876 Status
= VariableLock
->RequestToLock (VariableLock
, Name
, Guid
);
1877 ASSERT_EFI_ERROR (Status
);
1884 VariableLockProtocol callback
1885 to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
1887 @param[in] Event Event whose notification function is being invoked.
1888 @param[in] Context Pointer to the notification function's context.
1893 VariableLockCallBack (
1899 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
1901 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
1902 if (!EFI_ERROR (Status
)) {
1903 VariableLockDynamicHiiPcd (TRUE
, VariableLock
);
1904 VariableLockDynamicHiiPcd (FALSE
, VariableLock
);