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 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/DxeServicesLib.h>
14 PCD_DATABASE mPcdDatabase
;
16 UINT32 mPcdTotalTokenCount
;
17 UINT32 mPeiLocalTokenCount
;
18 UINT32 mDxeLocalTokenCount
;
19 UINT32 mPeiNexTokenCount
;
20 UINT32 mDxeNexTokenCount
;
21 UINT32 mPeiExMapppingTableSize
;
22 UINT32 mDxeExMapppingTableSize
;
23 UINT32 mPeiGuidTableSize
;
24 UINT32 mDxeGuidTableSize
;
26 BOOLEAN mPeiExMapTableEmpty
;
27 BOOLEAN mDxeExMapTableEmpty
;
28 BOOLEAN mPeiDatabaseEmpty
;
30 LIST_ENTRY
*mCallbackFnTable
;
31 EFI_GUID
**TmpTokenSpaceBuffer
;
32 UINTN TmpTokenSpaceBufferCount
;
34 UINTN mPeiPcdDbSize
= 0;
35 PEI_PCD_DATABASE
*mPeiPcdDbBinary
= NULL
;
36 UINTN mDxePcdDbSize
= 0;
37 DXE_PCD_DATABASE
*mDxePcdDbBinary
= NULL
;
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.
54 UINT32
*LocalTokenNumberTable
;
57 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
58 // We have to decrement TokenNumber by 1 to make it usable
59 // as the array index.
63 LocalTokenNumberTable
= IsPeiDb
? (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
) :
64 (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
65 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
67 return LocalTokenNumberTable
[TokenNumber
];
71 Get PCD type by Local Token Number.
73 @param[in] LocalTokenNumber The PCD local token number.
79 IN UINT32 LocalTokenNumber
82 switch (LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) {
83 case PCD_DATUM_TYPE_POINTER
:
84 return EFI_PCD_TYPE_PTR
;
85 case PCD_DATUM_TYPE_UINT8
:
86 if ((LocalTokenNumber
& PCD_DATUM_TYPE_UINT8_BOOLEAN
) == PCD_DATUM_TYPE_UINT8_BOOLEAN
) {
87 return EFI_PCD_TYPE_BOOL
;
89 return EFI_PCD_TYPE_8
;
91 case PCD_DATUM_TYPE_UINT16
:
92 return EFI_PCD_TYPE_16
;
93 case PCD_DATUM_TYPE_UINT32
:
94 return EFI_PCD_TYPE_32
;
95 case PCD_DATUM_TYPE_UINT64
:
96 return EFI_PCD_TYPE_64
;
99 return EFI_PCD_TYPE_8
;
106 @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.
107 If FALSE, need to get the full PCD name.
108 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
109 If FALSE, the pcd entry is initialized in DXE phase.
110 @param[in] TokenNumber The PCD token number.
112 @return The TokenSpaceCName or full PCD name.
116 IN BOOLEAN OnlyTokenSpaceName
,
121 PCD_DATABASE_INIT
*Database
;
124 PCD_NAME_INDEX
*PcdNameIndex
;
125 CHAR8
*TokenSpaceName
;
130 // Return NULL when PCD name table is absent.
133 if (mPcdDatabase
.PeiDb
->PcdNameTableOffset
== 0) {
137 if (mPcdDatabase
.DxeDb
->PcdNameTableOffset
== 0) {
143 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
144 // We have to decrement TokenNumber by 1 to make it usable
145 // as the array index.
149 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
150 TokenNumber
= IsPeiDb
? TokenNumber
: TokenNumber
- mPeiLocalTokenCount
;
152 StringTable
= (UINT8
*) Database
+ Database
->StringTableOffset
;
155 // Get the PCD name index.
157 PcdNameIndex
= (PCD_NAME_INDEX
*)((UINT8
*) Database
+ Database
->PcdNameTableOffset
) + TokenNumber
;
158 TokenSpaceName
= (CHAR8
*)&StringTable
[PcdNameIndex
->TokenSpaceCNameIndex
];
159 PcdName
= (CHAR8
*)&StringTable
[PcdNameIndex
->PcdCNameIndex
];
161 if (OnlyTokenSpaceName
) {
163 // Only need to get the TokenSpaceCName.
165 Name
= AllocateCopyPool (AsciiStrSize (TokenSpaceName
), TokenSpaceName
);
168 // Need to get the full PCD name.
170 NameSize
= AsciiStrSize (TokenSpaceName
) + AsciiStrSize (PcdName
);
171 Name
= AllocateZeroPool (NameSize
);
172 ASSERT (Name
!= NULL
);
174 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
176 AsciiStrCatS (Name
, NameSize
, TokenSpaceName
);
177 Name
[AsciiStrSize (TokenSpaceName
) - sizeof (CHAR8
)] = '.';
178 AsciiStrCatS (Name
, NameSize
, PcdName
);
185 Retrieve additional information associated with a PCD token.
187 This includes information such as the type of value the TokenNumber is associated with as well as possible
188 human readable name that is associated with the token.
190 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
191 If FALSE, the pcd entry is initialized in DXE phase.
192 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
193 @param[in] TokenNumber The PCD token number.
194 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
195 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
197 @retval EFI_SUCCESS The PCD information was returned successfully
198 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
203 IN CONST EFI_GUID
*Guid
,
204 IN UINTN TokenNumber
,
205 OUT EFI_PCD_INFO
*PcdInfo
208 PCD_DATABASE_INIT
*Database
;
212 DYNAMICEX_MAPPING
*ExMapTable
;
214 UINT32 LocalTokenNumber
;
216 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
218 GuidTable
= (EFI_GUID
*)((UINT8
*)Database
+ Database
->GuidTableOffset
);
219 MatchGuid
= ScanGuid (GuidTable
, Database
->GuidTableCount
* sizeof(EFI_GUID
), Guid
);
221 if (MatchGuid
== NULL
) {
222 return EFI_NOT_FOUND
;
225 GuidTableIdx
= MatchGuid
- GuidTable
;
227 ExMapTable
= (DYNAMICEX_MAPPING
*)((UINT8
*)Database
+ Database
->ExMapTableOffset
);
230 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
232 for (Index
= 0; Index
< Database
->ExTokenCount
; Index
++) {
233 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
234 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
236 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
237 // PcdSize to 0 and PcdName to the null-terminated ASCII string
238 // associated with the token's namespace Guid.
240 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
241 PcdInfo
->PcdSize
= 0;
243 // Here use one representative in the token space to get the TokenSpaceCName.
245 PcdInfo
->PcdName
= GetPcdName (TRUE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
247 } else if (ExMapTable
[Index
].ExTokenNumber
== TokenNumber
) {
248 PcdInfo
->PcdSize
= DxePcdGetSize (ExMapTable
[Index
].TokenNumber
);
249 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
250 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
251 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, ExMapTable
[Index
].TokenNumber
);
257 return EFI_NOT_FOUND
;
261 Retrieve additional information associated with a PCD token.
263 This includes information such as the type of value the TokenNumber is associated with as well as possible
264 human readable name that is associated with the token.
266 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
267 @param[in] TokenNumber The PCD token number.
268 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
269 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
271 @retval EFI_SUCCESS The PCD information was returned successfully.
272 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
276 IN CONST EFI_GUID
*Guid
,
277 IN UINTN TokenNumber
,
278 OUT EFI_PCD_INFO
*PcdInfo
282 BOOLEAN PeiExMapTableEmpty
;
283 BOOLEAN DxeExMapTableEmpty
;
284 UINT32 LocalTokenNumber
;
287 ASSERT (PcdInfo
!= NULL
);
289 Status
= EFI_NOT_FOUND
;
290 PeiExMapTableEmpty
= mPeiExMapTableEmpty
;
291 DxeExMapTableEmpty
= mDxeExMapTableEmpty
;
294 if (((TokenNumber
+ 1 > mPeiNexTokenCount
+ 1) && (TokenNumber
+ 1 <= mPeiLocalTokenCount
+ 1)) ||
295 ((TokenNumber
+ 1 > (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1)))) {
296 return EFI_NOT_FOUND
;
297 } else if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
299 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
300 // PcdSize to 0 and PcdName to NULL for default Token Space.
302 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
303 PcdInfo
->PcdSize
= 0;
304 PcdInfo
->PcdName
= NULL
;
306 PcdInfo
->PcdSize
= DxePcdGetSize (TokenNumber
);
308 if ((TokenNumber
+ 1 <= mPeiNexTokenCount
+ 1)) {
311 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
);
312 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
313 PcdInfo
->PcdName
= GetPcdName (FALSE
, IsPeiDb
, TokenNumber
);
318 if (PeiExMapTableEmpty
&& DxeExMapTableEmpty
) {
319 return EFI_NOT_FOUND
;
322 if (!PeiExMapTableEmpty
) {
323 Status
= ExGetPcdInfo (
331 if (Status
== EFI_SUCCESS
) {
335 if (!DxeExMapTableEmpty
) {
336 Status
= ExGetPcdInfo (
348 Get the PCD entry pointer in PCD database.
350 This routine will visit PCD database to find the PCD entry according to given
351 token number. The given token number is autogened by build tools and it will be
352 translated to local token number. Local token number contains PCD's type and
353 offset of PCD entry in PCD database.
355 @param TokenNumber Token's number, it is autogened by build tools
356 @param GetSize The size of token's value
358 @return PCD entry pointer in PCD database
363 IN UINTN TokenNumber
,
371 VARIABLE_HEAD
*VariableHead
;
372 UINT8
*VaraiableDefaultBuffer
;
377 UINTN TmpTokenNumber
;
380 UINT32 LocalTokenNumber
;
382 STRING_HEAD StringTableIdx
;
386 // Aquire lock to prevent reentrance from TPL_CALLBACK level
388 EfiAcquireLock (&mPcdDatabaseLock
);
392 ASSERT (TokenNumber
> 0);
394 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
395 // We have to decrement TokenNumber by 1 to make it usable
396 // as the array index.
400 TmpTokenNumber
= TokenNumber
;
403 // EBC compiler is very choosy. It may report warning about comparison
404 // between UINTN and 0 . So we add 1 in each size of the
407 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
409 ASSERT ((GetSize
== DxePcdGetSize (TokenNumber
+ 1)) || (GetSize
== 0));
411 // EBC compiler is very choosy. It may report warning about comparison
412 // between UINTN and 0 . So we add 1 in each size of the
414 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
416 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
418 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
421 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
423 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
427 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
429 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
431 VpdHead
= (VPD_HEAD
*) ((UINT8
*) PcdDb
+ Offset
);
432 ASSERT (mVpdBaseAddress
!= 0);
433 RetPtr
= (VOID
*) (mVpdBaseAddress
+ VpdHead
->Offset
);
437 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
440 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
442 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
445 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
446 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
447 Name
= (UINT16
*)(StringTable
+ VariableHead
->StringIndex
);
449 if ((LocalTokenNumber
& PCD_TYPE_ALL_SET
) == (PCD_TYPE_HII
|PCD_TYPE_STRING
)) {
451 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
452 // string array in string table.
454 StringTableIdx
= *(STRING_HEAD
*)((UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
);
455 VaraiableDefaultBuffer
= (UINT8
*) (StringTable
+ StringTableIdx
);
457 VaraiableDefaultBuffer
= (UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
;
459 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
460 if (Status
== EFI_SUCCESS
) {
461 if (DataSize
>= (VariableHead
->Offset
+ GetSize
)) {
464 // It is a pointer type. So get the MaxSize reserved for
467 GetPtrTypeSize (TmpTokenNumber
, &GetSize
);
468 if (GetSize
> (DataSize
- VariableHead
->Offset
)) {
470 // Use actual valid size.
472 GetSize
= DataSize
- VariableHead
->Offset
;
476 // If the operation is successful, we copy the data
477 // to the default value buffer in the PCD Database.
478 // So that we can free the Data allocated in GetHiiVariable.
480 CopyMem (VaraiableDefaultBuffer
, Data
+ VariableHead
->Offset
, GetSize
);
484 RetPtr
= (VOID
*) VaraiableDefaultBuffer
;
487 case PCD_TYPE_STRING
:
488 StringTableIdx
= *(STRING_HEAD
*)((UINT8
*) PcdDb
+ Offset
);
489 RetPtr
= (VOID
*) (StringTable
+ StringTableIdx
);
493 RetPtr
= (VOID
*) ((UINT8
*) PcdDb
+ Offset
);
502 EfiReleaseLock (&mPcdDatabaseLock
);
509 Register the callback function for a PCD entry.
511 This routine will register a callback function to a PCD entry by given token number
512 and token space guid.
514 @param TokenNumber PCD token's number, it is autogened by build tools.
515 @param Guid PCD token space's guid,
516 if not NULL, this PCD is dynamicEx type PCD.
517 @param CallBackFunction Callback function pointer
519 @return EFI_SUCCESS Always success for registering callback function.
523 DxeRegisterCallBackWorker (
524 IN UINTN TokenNumber
,
525 IN CONST EFI_GUID
*Guid
, OPTIONAL
526 IN PCD_PROTOCOL_CALLBACK CallBackFunction
529 CALLBACK_FN_ENTRY
*FnTableEntry
;
530 LIST_ENTRY
*ListHead
;
531 LIST_ENTRY
*ListNode
;
534 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
538 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
539 // We have to decrement TokenNumber by 1 to make it usable
540 // as the array index of mCallbackFnTable[].
542 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
543 ListNode
= GetFirstNode (ListHead
);
545 while (ListNode
!= ListHead
) {
546 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
548 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
550 // We only allow a Callback function to be register once
551 // for a TokenNumber. So just return EFI_SUCCESS
555 ListNode
= GetNextNode (ListHead
, ListNode
);
558 FnTableEntry
= AllocatePool (sizeof(CALLBACK_FN_ENTRY
));
559 ASSERT (FnTableEntry
!= NULL
);
561 FnTableEntry
->CallbackFn
= CallBackFunction
;
562 InsertTailList (ListHead
, &FnTableEntry
->Node
);
568 UnRegister the callback function for a PCD entry.
570 This routine will unregister a callback function to a PCD entry by given token number
571 and token space guid.
573 @param TokenNumber PCD token's number, it is autogened by build tools.
574 @param Guid PCD token space's guid.
575 if not NULL, this PCD is dynamicEx type PCD.
576 @param CallBackFunction Callback function pointer
578 @retval EFI_SUCCESS Callback function is success to be unregister.
579 @retval EFI_INVALID_PARAMETER Can not find the PCD entry by given token number.
582 DxeUnRegisterCallBackWorker (
583 IN UINTN TokenNumber
,
584 IN CONST EFI_GUID
*Guid
, OPTIONAL
585 IN PCD_PROTOCOL_CALLBACK CallBackFunction
588 CALLBACK_FN_ENTRY
*FnTableEntry
;
589 LIST_ENTRY
*ListHead
;
590 LIST_ENTRY
*ListNode
;
593 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
597 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
598 // We have to decrement TokenNumber by 1 to make it usable
599 // as the array index of mCallbackFnTable[].
601 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
602 ListNode
= GetFirstNode (ListHead
);
604 while (ListNode
!= ListHead
) {
605 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
607 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
609 // We only allow a Callback function to be register once
610 // for a TokenNumber. So we can safely remove the Node from
611 // the Link List and return EFI_SUCCESS.
613 RemoveEntryList (ListNode
);
614 FreePool (FnTableEntry
);
618 ListNode
= GetNextNode (ListHead
, ListNode
);
621 return EFI_INVALID_PARAMETER
;
625 Get next token number in given token space.
627 This routine is used for dynamicEx type PCD. It will firstly scan token space
628 table to get token space according to given token space guid. Then scan given
629 token number in found token space, if found, then return next token number in
632 @param Guid Token space guid. Next token number will be scaned in
634 @param TokenNumber Token number.
635 If PCD_INVALID_TOKEN_NUMBER, return first token number in
637 If not PCD_INVALID_TOKEN_NUMBER, return next token number
638 in token space table.
639 @param GuidTable Token space guid table. It will be used for scan token space
640 by given token space guid.
641 @param SizeOfGuidTable The size of guid table.
642 @param ExMapTable DynamicEx token number mapping table.
643 @param SizeOfExMapTable The size of dynamicEx token number mapping table.
645 @retval EFI_NOT_FOUND Can not given token space or token number.
646 @retval EFI_SUCCESS Success to get next token number.
650 ExGetNextTokeNumber (
651 IN CONST EFI_GUID
*Guid
,
652 IN OUT UINTN
*TokenNumber
,
653 IN EFI_GUID
*GuidTable
,
654 IN UINTN SizeOfGuidTable
,
655 IN DYNAMICEX_MAPPING
*ExMapTable
,
656 IN UINTN SizeOfExMapTable
663 UINTN ExMapTableCount
;
666 // Scan token space guid
668 MatchGuid
= ScanGuid (GuidTable
, SizeOfGuidTable
, Guid
);
669 if (MatchGuid
== NULL
) {
670 return EFI_NOT_FOUND
;
674 // Find the token space table in dynamicEx mapping table.
677 GuidTableIdx
= MatchGuid
- GuidTable
;
678 ExMapTableCount
= SizeOfExMapTable
/ sizeof(ExMapTable
[0]);
679 for (Index
= 0; Index
< ExMapTableCount
; Index
++) {
680 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
688 // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
689 // token number in found token space.
691 if (*TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
692 *TokenNumber
= ExMapTable
[Index
].ExTokenNumber
;
696 for ( ; Index
< ExMapTableCount
; Index
++) {
697 if ((ExMapTable
[Index
].ExTokenNumber
== *TokenNumber
) && (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
)) {
702 while (Index
< ExMapTableCount
) {
704 if (Index
== ExMapTableCount
) {
706 // Exceed the length of ExMap Table
708 *TokenNumber
= PCD_INVALID_TOKEN_NUMBER
;
709 return EFI_NOT_FOUND
;
710 } else if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
712 // Found the next match
714 *TokenNumber
= ExMapTable
[Index
].ExTokenNumber
;
720 return EFI_NOT_FOUND
;
724 Find the PCD database.
726 @retval The base address of external PCD database binary.
727 @retval NULL Return NULL if not find.
737 // Search the External Pcd database from one section of current FFS,
738 // and read it to memory
740 Status
= GetSectionFromFfs (
743 (VOID
**) &mDxePcdDbBinary
,
746 ASSERT_EFI_ERROR (Status
);
749 // Check the first bytes (Header Signature Guid) and build version.
751 if (!CompareGuid ((VOID
*)mDxePcdDbBinary
, &gPcdDataBaseSignatureGuid
) ||
752 (mDxePcdDbBinary
->BuildVersion
!= PCD_SERVICE_DXE_VERSION
)) {
756 return mDxePcdDbBinary
;
760 Update PCD database base on current SkuId
762 @param SkuId Current SkuId
763 @param IsPeiDb Whether to update PEI PCD database.
765 @retval EFI_SUCCESS Update PCD database successfully.
766 @retval EFI_NOT_FOUND Not found PCD database for current SkuId.
775 PCD_DATABASE_SKU_DELTA
*SkuDelta
;
776 PCD_DATA_DELTA
*SkuDeltaData
;
778 if (IsPeiDb
&& mPeiPcdDbBinary
!= NULL
) {
780 // Find the delta data for PEI DB
782 Index
= (mPcdDatabase
.PeiDb
->Length
+ 7) & (~7);
784 while (Index
< mPeiPcdDbSize
) {
785 SkuDelta
= (PCD_DATABASE_SKU_DELTA
*) ((UINT8
*) mPeiPcdDbBinary
+ Index
);
786 if (SkuDelta
->SkuId
== SkuId
&& SkuDelta
->SkuIdCompared
== 0) {
789 Index
= (Index
+ SkuDelta
->Length
+ 7) & (~7);
793 // Patch the delta data into current PCD database
795 if (Index
< mPeiPcdDbSize
&& SkuDelta
!= NULL
) {
796 SkuDeltaData
= (PCD_DATA_DELTA
*) (SkuDelta
+ 1);
797 while ((UINT8
*) SkuDeltaData
< (UINT8
*) SkuDelta
+ SkuDelta
->Length
) {
798 *((UINT8
*) mPcdDatabase
.PeiDb
+ SkuDeltaData
->Offset
) = (UINT8
) SkuDeltaData
->Value
;
802 return EFI_NOT_FOUND
;
807 // Find the delta data for DXE DB
809 Index
= (mPcdDatabase
.DxeDb
->Length
+ 7) & (~7);
811 while (Index
< mDxePcdDbSize
) {
812 SkuDelta
= (PCD_DATABASE_SKU_DELTA
*) ((UINT8
*) mDxePcdDbBinary
+ Index
);
813 if (SkuDelta
->SkuId
== SkuId
&& SkuDelta
->SkuIdCompared
== 0) {
816 Index
= (Index
+ SkuDelta
->Length
+ 7) & (~7);
820 // Patch the delta data into current PCD database
822 if (Index
< mDxePcdDbSize
&& SkuDelta
!= NULL
) {
823 SkuDeltaData
= (PCD_DATA_DELTA
*) (SkuDelta
+ 1);
824 while ((UINT8
*) SkuDeltaData
< (UINT8
*) SkuDelta
+ SkuDelta
->Length
) {
825 *((UINT8
*) mPcdDatabase
.DxeDb
+ SkuDeltaData
->Offset
) = (UINT8
) SkuDeltaData
->Value
;
831 return EFI_NOT_FOUND
;
835 Initialize the PCD database in DXE phase.
837 PCD database in DXE phase also contains PCD database in PEI phase which is copied
842 BuildPcdDxeDataBase (
846 PEI_PCD_DATABASE
*PeiDatabase
;
847 EFI_HOB_GUID_TYPE
*GuidHob
;
854 // Assign PCD Entries with default value to PCD DATABASE
856 mPcdDatabase
.DxeDb
= LocateExPcdBinary ();
857 ASSERT(mPcdDatabase
.DxeDb
!= NULL
);
858 PcdDxeDbLen
= mPcdDatabase
.DxeDb
->Length
+ mPcdDatabase
.DxeDb
->UninitDataBaseSize
;
859 PcdDxeDb
= AllocateZeroPool (PcdDxeDbLen
);
860 ASSERT (PcdDxeDb
!= NULL
);
861 CopyMem (PcdDxeDb
, mPcdDatabase
.DxeDb
, mPcdDatabase
.DxeDb
->Length
);
862 mPcdDatabase
.DxeDb
= PcdDxeDb
;
864 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
865 if (GuidHob
!= NULL
) {
868 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
869 // should not be included at all. So the GuidHob could
870 // be NULL. If it is NULL, we just copy over the DXE Default
871 // Value to PCD Database.
873 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
876 // Get next one that stores full PEI data
878 GuidHob
= GetNextGuidHob (&gPcdDataBaseHobGuid
, GET_NEXT_HOB (GuidHob
));
879 if (GuidHob
!= NULL
) {
880 mPeiPcdDbBinary
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
881 mPeiPcdDbSize
= (UINTN
) GET_GUID_HOB_DATA_SIZE (GuidHob
);
885 // Assign PCD Entries refereneced in PEI phase to PCD DATABASE
887 mPcdDatabase
.PeiDb
= PeiDatabase
;
889 // Inherit the SystemSkuId from PEI phase.
891 if (mPcdDatabase
.PeiDb
->SystemSkuId
!= 0) {
892 Status
= UpdatePcdDatabase (mPcdDatabase
.PeiDb
->SystemSkuId
, FALSE
);
893 ASSERT_EFI_ERROR (Status
);
895 mPcdDatabase
.DxeDb
->SystemSkuId
= mPcdDatabase
.PeiDb
->SystemSkuId
;
897 mPcdDatabase
.PeiDb
= AllocateZeroPool (sizeof (PEI_PCD_DATABASE
));
898 ASSERT(mPcdDatabase
.PeiDb
!= NULL
);
902 // Initialized the external PCD database local variables
904 mPeiLocalTokenCount
= mPcdDatabase
.PeiDb
->LocalTokenCount
;
905 mDxeLocalTokenCount
= mPcdDatabase
.DxeDb
->LocalTokenCount
;
907 mPeiExMapppingTableSize
= mPcdDatabase
.PeiDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
908 mDxeExMapppingTableSize
= mPcdDatabase
.DxeDb
->ExTokenCount
* sizeof (DYNAMICEX_MAPPING
);
909 mPeiGuidTableSize
= mPcdDatabase
.PeiDb
->GuidTableCount
* sizeof(GUID
);
910 mDxeGuidTableSize
= mPcdDatabase
.DxeDb
->GuidTableCount
* sizeof (GUID
);
912 mPcdTotalTokenCount
= mPeiLocalTokenCount
+ mDxeLocalTokenCount
;
913 mPeiNexTokenCount
= mPeiLocalTokenCount
- mPcdDatabase
.PeiDb
->ExTokenCount
;
914 mDxeNexTokenCount
= mDxeLocalTokenCount
- mPcdDatabase
.DxeDb
->ExTokenCount
;
916 mPeiExMapTableEmpty
= (mPcdDatabase
.PeiDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
917 mDxeExMapTableEmpty
= (mPcdDatabase
.DxeDb
->ExTokenCount
== 0) ? TRUE
: FALSE
;
918 mPeiDatabaseEmpty
= (mPeiLocalTokenCount
== 0) ? TRUE
: FALSE
;
920 TmpTokenSpaceBufferCount
= mPcdDatabase
.PeiDb
->ExTokenCount
+ mPcdDatabase
.DxeDb
->ExTokenCount
;
921 TmpTokenSpaceBuffer
= (EFI_GUID
**)AllocateZeroPool(TmpTokenSpaceBufferCount
* sizeof (EFI_GUID
*));
924 // Initialized the Callback Function Table
926 mCallbackFnTable
= AllocateZeroPool (mPcdTotalTokenCount
* sizeof (LIST_ENTRY
));
927 ASSERT(mCallbackFnTable
!= NULL
);
930 // EBC compiler is very choosy. It may report warning about comparison
931 // between UINTN and 0 . So we add 1 in each size of the
934 for (Index
= 0; Index
+ 1 < mPcdTotalTokenCount
+ 1; Index
++) {
935 InitializeListHead (&mCallbackFnTable
[Index
]);
940 Get Variable which contains HII type PCD entry.
942 @param VariableGuid Variable's guid
943 @param VariableName Variable's unicode name string
944 @param VariableData Variable's data pointer,
945 @param VariableSize Variable's size.
947 @return the status of gRT->GetVariable
951 IN EFI_GUID
*VariableGuid
,
952 IN UINT16
*VariableName
,
953 OUT UINT8
**VariableData
,
954 OUT UINTN
*VariableSize
965 // Firstly get the real size of HII variable
967 Status
= gRT
->GetVariable (
968 (UINT16
*)VariableName
,
976 // Allocate buffer to hold whole variable data according to variable size.
978 if (Status
== EFI_BUFFER_TOO_SMALL
) {
979 Buffer
= (UINT8
*) AllocatePool (Size
);
981 ASSERT (Buffer
!= NULL
);
983 Status
= gRT
->GetVariable (
991 ASSERT (Status
== EFI_SUCCESS
);
992 *VariableData
= Buffer
;
993 *VariableSize
= Size
;
996 // Use Default Data only when variable is not found.
997 // For other error status, correct data can't be got, and trig ASSERT().
999 ASSERT (Status
== EFI_NOT_FOUND
);
1006 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
1007 has registered callback function.
1009 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
1011 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
1013 @param TokenNumber PCD token number generated by build tools.
1014 @param Data Value want to be set for this PCD entry
1015 @param Size The size of value
1019 InvokeCallbackOnSet (
1020 UINT32 ExTokenNumber
,
1021 CONST EFI_GUID
*Guid
, OPTIONAL
1027 CALLBACK_FN_ENTRY
*FnTableEntry
;
1028 LIST_ENTRY
*ListHead
;
1029 LIST_ENTRY
*ListNode
;
1032 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1033 // We have to decrement TokenNumber by 1 to make it usable
1034 // as the array index of mCallbackFnTable[].
1036 ListHead
= &mCallbackFnTable
[TokenNumber
- 1];
1037 ListNode
= GetFirstNode (ListHead
);
1039 while (ListNode
!= ListHead
) {
1040 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE (ListNode
, CALLBACK_FN_ENTRY
, Node
);
1042 FnTableEntry
->CallbackFn(Guid
,
1043 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
1047 ListNode
= GetNextNode (ListHead
, ListNode
);
1055 Wrapper function for setting non-pointer type value for a PCD entry.
1057 @param TokenNumber Pcd token number autogenerated by build tools.
1058 @param Data Value want to be set for PCD entry
1059 @param Size Size of value.
1061 @return status of SetWorker.
1066 IN UINTN TokenNumber
,
1071 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
1076 Set value for an PCD entry
1078 @param TokenNumber Pcd token number autogenerated by build tools.
1079 @param Data Value want to be set for PCD entry
1080 @param Size Size of value.
1081 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
1082 If False, the type of PCD entry's value is not Pointer.
1084 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
1085 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
1086 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
1087 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
1088 range of UINT8, UINT16, UINT32, UINT64
1089 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
1093 IN UINTN TokenNumber
,
1100 UINT32 LocalTokenNumber
;
1101 EFI_GUID
*GuidTable
;
1105 UINTN VariableOffset
;
1108 VARIABLE_HEAD
*VariableHead
;
1113 UINTN TmpTokenNumber
;
1116 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
1117 // We have to decrement TokenNumber by 1 to make it usable
1118 // as the array index.
1122 TmpTokenNumber
= TokenNumber
;
1125 // EBC compiler is very choosy. It may report warning about comparison
1126 // between UINTN and 0 . So we add 1 in each size of the
1129 ASSERT (TokenNumber
+ 1 < mPcdTotalTokenCount
+ 1);
1133 // Get MaxSize first, then check new size with max buffer size.
1135 GetPtrTypeSize (TokenNumber
, &MaxSize
);
1136 if (*Size
> MaxSize
) {
1138 return EFI_INVALID_PARAMETER
;
1141 if (*Size
!= DxePcdGetSize (TokenNumber
+ 1)) {
1142 return EFI_INVALID_PARAMETER
;
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 if ((TokenNumber
+ 1 < mPeiNexTokenCount
+ 1) ||
1152 (TokenNumber
+ 1 >= mPeiLocalTokenCount
+ 1 && TokenNumber
+ 1 < (mPeiLocalTokenCount
+ mDxeNexTokenCount
+ 1))) {
1153 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
1157 // Aquire lock to prevent reentrance from TPL_CALLBACK level
1159 EfiAcquireLock (&mPcdDatabaseLock
);
1162 // EBC compiler is very choosy. It may report warning about comparison
1163 // between UINTN and 0 . So we add 1 in each size of the
1166 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
1168 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
+ 1);
1170 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1172 PcdDb
= IsPeiDb
? ((UINT8
*) mPcdDatabase
.PeiDb
) : ((UINT8
*) mPcdDatabase
.DxeDb
);
1175 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->StringTableOffset
);
1177 StringTable
= (UINT8
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->StringTableOffset
);
1181 InternalData
= PcdDb
+ Offset
;
1183 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
1186 Status
= EFI_INVALID_PARAMETER
;
1189 case PCD_TYPE_STRING
:
1190 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1191 CopyMem (StringTable
+ *((STRING_HEAD
*)InternalData
), Data
, *Size
);
1192 Status
= EFI_SUCCESS
;
1194 Status
= EFI_INVALID_PARAMETER
;
1198 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
1201 if (!SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1202 Status
= EFI_INVALID_PARAMETER
;
1208 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1210 GuidTable
= (EFI_GUID
*) ((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1213 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
1215 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1216 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1217 VariableOffset
= VariableHead
->Offset
;
1218 Attributes
= VariableHead
->Attributes
;
1219 Status
= SetHiiVariable (Guid
, Name
, Attributes
, Data
, *Size
, VariableOffset
);
1224 if (SetPtrTypeSize (TmpTokenNumber
, Size
)) {
1225 CopyMem (InternalData
, Data
, *Size
);
1226 Status
= EFI_SUCCESS
;
1228 Status
= EFI_INVALID_PARAMETER
;
1233 Status
= EFI_SUCCESS
;
1236 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
1239 case sizeof(UINT16
):
1240 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
1243 case sizeof(UINT32
):
1244 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
1247 case sizeof(UINT64
):
1248 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
1253 Status
= EFI_NOT_FOUND
;
1260 Status
= EFI_NOT_FOUND
;
1264 EfiReleaseLock (&mPcdDatabaseLock
);
1270 Wrapper function for get PCD value for dynamic-ex PCD.
1272 @param Guid Token space guid for dynamic-ex PCD.
1273 @param ExTokenNumber Token number for dynamic-ex PCD.
1274 @param GetSize The size of dynamic-ex PCD value.
1276 @return PCD entry in PCD database.
1281 IN CONST EFI_GUID
*Guid
,
1282 IN UINTN ExTokenNumber
,
1286 return GetWorker(GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
), GetSize
);
1290 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
1292 @param ExTokenNumber Token number for dynamic-ex PCD.
1293 @param Guid Token space guid for dynamic-ex PCD.
1294 @param Data Value want to be set.
1295 @param SetSize The size of value.
1297 @return status of ExSetWorker().
1302 IN UINTN ExTokenNumber
,
1303 IN CONST EFI_GUID
*Guid
,
1308 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &SetSize
, FALSE
);
1312 Set value for a dynamic-ex PCD entry.
1314 This routine find the local token number according to dynamic-ex PCD's token
1315 space guid and token number firstly, and invoke callback function if this PCD
1316 entry registered callback function. Finally, invoken general SetWorker to set
1319 @param ExTokenNumber Dynamic-ex PCD token number.
1320 @param Guid Token space guid for dynamic-ex PCD.
1321 @param Data PCD value want to be set
1322 @param SetSize Size of value.
1323 @param PtrType If TRUE, this PCD entry is pointer type.
1324 If FALSE, this PCD entry is not pointer type.
1326 @return status of SetWorker().
1331 IN UINTN ExTokenNumber
,
1332 IN CONST EFI_GUID
*Guid
,
1334 IN OUT UINTN
*SetSize
,
1340 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
);
1342 InvokeCallbackOnSet ((UINT32
) ExTokenNumber
, Guid
, TokenNumber
, Data
, *SetSize
);
1344 return SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
1349 Get variable size and data from HII-type PCDs.
1351 @param[in] VariableGuid Guid of variable which stored value of a HII-type PCD.
1352 @param[in] VariableName Unicode name of variable which stored value of a HII-type PCD.
1353 @param[out] VariableSize Pointer to variable size got from HII-type PCDs.
1354 @param[out] VariableData Pointer to variable data got from HII-type PCDs.
1358 GetVariableSizeAndDataFromHiiPcd (
1359 IN EFI_GUID
*VariableGuid
,
1360 IN UINT16
*VariableName
,
1361 OUT UINTN
*VariableSize
,
1362 OUT VOID
*VariableData OPTIONAL
1366 PCD_DATABASE_INIT
*Database
;
1368 UINT32 LocalTokenNumber
;
1370 EFI_GUID
*GuidTable
;
1372 VARIABLE_HEAD
*VariableHead
;
1377 UINT8
*VaraiableDefaultBuffer
;
1378 STRING_HEAD StringTableIdx
;
1383 // Go through PCD database to find out DynamicHii PCDs.
1385 for (TokenNumber
= 1; TokenNumber
<= mPcdTotalTokenCount
; TokenNumber
++) {
1386 IsPeiDb
= (BOOLEAN
) ((TokenNumber
+ 1 < mPeiLocalTokenCount
+ 1) ? TRUE
: FALSE
);
1387 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
1388 LocalTokenNumber
= GetLocalTokenNumber (IsPeiDb
, TokenNumber
);
1389 if ((LocalTokenNumber
& PCD_TYPE_HII
) != 0) {
1391 // Get the Variable Guid and Name pointer.
1393 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1394 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*) Database
+ Offset
);
1395 StringTable
= (UINT8
*) ((UINT8
*) Database
+ Database
->StringTableOffset
);
1396 GuidTable
= (EFI_GUID
*) ((UINT8
*) Database
+ Database
->GuidTableOffset
);
1397 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1398 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1399 if (CompareGuid (VariableGuid
, Guid
) && (StrCmp (VariableName
, Name
) == 0)) {
1401 // It is the matched DynamicHii PCD.
1403 PcdDataSize
= DxePcdGetSize (TokenNumber
);
1404 Size
= VariableHead
->Offset
+ PcdDataSize
;
1405 if (Size
> *VariableSize
) {
1406 *VariableSize
= Size
;
1408 if (VariableData
!= NULL
) {
1409 if ((LocalTokenNumber
& PCD_TYPE_ALL_SET
) == (PCD_TYPE_HII
|PCD_TYPE_STRING
)) {
1411 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
1412 // string array in string table.
1414 StringTableIdx
= *(STRING_HEAD
*) ((UINT8
*) Database
+ VariableHead
->DefaultValueOffset
);
1415 VaraiableDefaultBuffer
= (UINT8
*) (StringTable
+ StringTableIdx
);
1417 VaraiableDefaultBuffer
= (UINT8
*) Database
+ VariableHead
->DefaultValueOffset
;
1419 CopyMem ((UINT8
*) VariableData
+ VariableHead
->Offset
, VaraiableDefaultBuffer
, PcdDataSize
);
1427 Set value for HII-type PCD.
1429 A HII-type PCD's value is stored in a variable. Setting/Getting the value of
1430 HII-type PCD is to visit this variable.
1432 @param VariableGuid Guid of variable which stored value of a HII-type PCD.
1433 @param VariableName Unicode name of variable which stored value of a HII-type PCD.
1434 @param SetAttributes Attributes bitmask to set for the variable.
1435 @param Data Value want to be set.
1436 @param DataSize Size of value
1437 @param Offset Value offset of HII-type PCD in variable.
1439 @return status of GetVariable()/SetVariable().
1444 IN EFI_GUID
*VariableGuid
,
1445 IN UINT16
*VariableName
,
1446 IN UINT32 SetAttributes
,
1447 IN CONST VOID
*Data
,
1462 // Try to get original variable size information.
1464 Status
= gRT
->GetVariable (
1465 (UINT16
*)VariableName
,
1472 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1474 // Patch new PCD's value to offset in given HII variable.
1476 if (Size
>= (DataSize
+ Offset
)) {
1479 SetSize
= DataSize
+ Offset
;
1481 Buffer
= AllocatePool (SetSize
);
1482 ASSERT (Buffer
!= NULL
);
1484 Status
= gRT
->GetVariable (
1492 ASSERT_EFI_ERROR (Status
);
1494 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1496 if (SetAttributes
== 0) {
1497 SetAttributes
= Attribute
;
1500 Status
= gRT
->SetVariable (
1510 } else if (Status
== EFI_NOT_FOUND
) {
1512 // If variable does not exist, a new variable need to be created.
1516 // Get size, allocate buffer and get data.
1518 GetVariableSizeAndDataFromHiiPcd (VariableGuid
, VariableName
, &Size
, NULL
);
1519 Buffer
= AllocateZeroPool (Size
);
1520 ASSERT (Buffer
!= NULL
);
1521 GetVariableSizeAndDataFromHiiPcd (VariableGuid
, VariableName
, &Size
, Buffer
);
1526 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
1528 if (SetAttributes
== 0) {
1529 SetAttributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
1532 Status
= gRT
->SetVariable (
1545 // If we drop to here, the value is failed to be written in to variable area.
1551 Get Token Number according to dynamic-ex PCD's {token space guid:token number}
1553 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
1554 in DEC file. PCD database maintain a mapping table that translate pair of {token
1555 space guid: token number} to Token Number.
1557 @param Guid Token space guid for dynamic-ex PCD entry.
1558 @param ExTokenNumber Dynamic-ex PCD token number.
1560 @return Token Number for dynamic-ex PCD.
1564 GetExPcdTokenNumber (
1565 IN CONST EFI_GUID
*Guid
,
1566 IN UINT32 ExTokenNumber
1570 DYNAMICEX_MAPPING
*ExMap
;
1571 EFI_GUID
*GuidTable
;
1572 EFI_GUID
*MatchGuid
;
1575 if (!mPeiDatabaseEmpty
) {
1576 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->ExMapTableOffset
);
1577 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->GuidTableOffset
);
1579 MatchGuid
= ScanGuid (GuidTable
, mPeiGuidTableSize
, Guid
);
1581 if (MatchGuid
!= NULL
) {
1583 MatchGuidIdx
= MatchGuid
- GuidTable
;
1585 for (Index
= 0; Index
< mPcdDatabase
.PeiDb
->ExTokenCount
; Index
++) {
1586 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1587 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1588 return ExMap
[Index
].TokenNumber
;
1594 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->ExMapTableOffset
);
1595 GuidTable
= (EFI_GUID
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->GuidTableOffset
);
1597 MatchGuid
= ScanGuid (GuidTable
, mDxeGuidTableSize
, Guid
);
1599 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
1600 // error in the BUILD system.
1602 ASSERT (MatchGuid
!= NULL
);
1604 MatchGuidIdx
= MatchGuid
- GuidTable
;
1606 for (Index
= 0; Index
< mPcdDatabase
.DxeDb
->ExTokenCount
; Index
++) {
1607 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1608 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1609 return ExMap
[Index
].TokenNumber
;
1619 Wrapper function of getting index of PCD entry in size table.
1621 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1622 @param IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1623 If FALSE, the pcd entry is initialized in DXE phase.
1625 @return index of PCD entry in size table.
1629 IN UINTN LocalTokenNumberTableIdx
,
1633 UINT32
*LocalTokenNumberTable
;
1634 UINTN LocalTokenNumber
;
1639 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1641 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1646 for (Index
= 0; Index
< LocalTokenNumberTableIdx
; Index
++) {
1647 LocalTokenNumber
= LocalTokenNumberTable
[Index
];
1649 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
1651 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1654 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1656 // We have only two entry for VPD enabled PCD entry:
1659 // Current size is equal to MAX size.
1664 // We have only two entry for Non-Sku enabled PCD entry:
1674 return SizeTableIdx
;
1678 Get size of POINTER type PCD value.
1680 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1681 @param MaxSize Maxmium size of POINTER type PCD value.
1683 @return size of POINTER type PCD value.
1688 IN UINTN LocalTokenNumberTableIdx
,
1693 UINTN LocalTokenNumber
;
1694 SIZE_INFO
*SizeTable
;
1696 UINT32
*LocalTokenNumberTable
;
1698 // EBC compiler is very choosy. It may report warning about comparison
1699 // between UINTN and 0 . So we add 1 in each size of the
1701 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1705 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1706 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1708 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1709 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1710 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1713 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1715 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1717 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1719 *MaxSize
= SizeTable
[SizeTableIdx
];
1721 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1724 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1726 // We have only two entry for VPD enabled PCD entry:
1729 // We consider current size is equal to MAX size.
1734 // We have only two entry for Non-Sku enabled PCD entry:
1738 return SizeTable
[SizeTableIdx
+ 1];
1743 Set size of POINTER type PCD value. The size should not exceed the maximum size
1746 @param LocalTokenNumberTableIdx Index of local token number in local token number table.
1747 @param CurrentSize Size of POINTER type PCD value.
1749 @retval TRUE Success to set size of PCD value.
1750 @retval FALSE Fail to set size of PCD value.
1754 IN UINTN LocalTokenNumberTableIdx
,
1755 IN OUT UINTN
*CurrentSize
1759 UINTN LocalTokenNumber
;
1760 SIZE_INFO
*SizeTable
;
1763 UINT32
*LocalTokenNumberTable
;
1766 // EBC compiler is very choosy. It may report warning about comparison
1767 // between UINTN and 0 . So we add 1 in each size of the
1770 IsPeiDb
= (BOOLEAN
) (LocalTokenNumberTableIdx
+ 1 < mPeiLocalTokenCount
+ 1);
1773 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->LocalTokenNumberTableOffset
);
1774 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.PeiDb
+ mPcdDatabase
.PeiDb
->SizeTableOffset
);
1776 LocalTokenNumberTableIdx
-= mPeiLocalTokenCount
;
1777 LocalTokenNumberTable
= (UINT32
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->LocalTokenNumberTableOffset
);
1778 SizeTable
= (SIZE_INFO
*)((UINT8
*)mPcdDatabase
.DxeDb
+ mPcdDatabase
.DxeDb
->SizeTableOffset
);
1781 LocalTokenNumber
= LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
1783 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
1785 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, IsPeiDb
);
1787 MaxSize
= SizeTable
[SizeTableIdx
];
1789 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1792 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1794 // We shouldn't come here as we don't support SET for VPD
1799 if ((*CurrentSize
> MaxSize
) ||
1800 (*CurrentSize
== MAX_ADDRESS
)) {
1801 *CurrentSize
= MaxSize
;
1806 // We have only two entry for Non-Sku enabled PCD entry:
1810 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
1816 VariableLock DynamicHiiPcd.
1818 @param[in] IsPeiDb If TRUE, the pcd entry is initialized in PEI phase,
1819 If FALSE, the pcd entry is initialized in DXE phase.
1820 @param[in] VariableLock Pointer to VariableLockProtocol.
1824 VariableLockDynamicHiiPcd (
1826 IN EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
1830 PCD_DATABASE_INIT
*Database
;
1831 UINT32 LocalTokenCount
;
1833 UINT32 LocalTokenNumber
;
1835 EFI_GUID
*GuidTable
;
1837 VARIABLE_HEAD
*VariableHead
;
1841 Database
= IsPeiDb
? mPcdDatabase
.PeiDb
: mPcdDatabase
.DxeDb
;
1842 LocalTokenCount
= IsPeiDb
? mPeiLocalTokenCount
: mDxeLocalTokenCount
;
1845 // Go through PCD database to find out DynamicHii PCDs.
1847 for (TokenNumber
= 1; TokenNumber
<= LocalTokenCount
; TokenNumber
++) {
1849 LocalTokenNumber
= GetLocalTokenNumber (TRUE
, TokenNumber
);
1851 LocalTokenNumber
= GetLocalTokenNumber (FALSE
, TokenNumber
+ mPeiLocalTokenCount
);
1853 if ((LocalTokenNumber
& PCD_TYPE_HII
) != 0) {
1854 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
1855 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*) Database
+ Offset
);
1857 // Why not to set property by VarCheckProtocol with Attributes and Property directly here?
1858 // It is because that set property by VarCheckProtocol will indicate the variable to
1859 // be a system variable, but the unknown max size of the variable is dangerous to
1860 // the system variable region.
1862 if ((VariableHead
->Property
& VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY
) != 0) {
1864 // DynamicHii PCD with RO property set in *.dsc.
1866 StringTable
= (UINT8
*) ((UINT8
*) Database
+ Database
->StringTableOffset
);
1867 GuidTable
= (EFI_GUID
*) ((UINT8
*) Database
+ Database
->GuidTableOffset
);
1868 Guid
= GuidTable
+ VariableHead
->GuidTableIndex
;
1869 Name
= (UINT16
*) (StringTable
+ VariableHead
->StringIndex
);
1870 Status
= VariableLock
->RequestToLock (VariableLock
, Name
, Guid
);
1871 ASSERT_EFI_ERROR (Status
);
1878 VariableLockProtocol callback
1879 to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
1881 @param[in] Event Event whose notification function is being invoked.
1882 @param[in] Context Pointer to the notification function's context.
1887 VariableLockCallBack (
1893 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
1895 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
1896 if (!EFI_ERROR (Status
)) {
1897 VariableLockDynamicHiiPcd (TRUE
, VariableLock
);
1898 VariableLockDynamicHiiPcd (FALSE
, VariableLock
);