2 The driver internal functions are implmented here.
3 They build Pei PCD database, and provide access service to PCD database.
5 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Get Local Token Number by Token Number.
21 @param[in] Database PCD database.
22 @param[in] TokenNumber The PCD token number.
24 @return Local Token Number.
28 IN PEI_PCD_DATABASE
*Database
,
32 UINT32 LocalTokenNumber
;
37 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
38 // We have to decrement TokenNumber by 1 to make it usable
39 // as the array index.
43 LocalTokenNumber
= *((UINT32
*)((UINT8
*)Database
+ Database
->LocalTokenNumberTableOffset
) + TokenNumber
);
45 Size
= (LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) >> PCD_DATUM_TYPE_SHIFT
;
47 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
49 GetPtrTypeSize (TokenNumber
, &MaxSize
, Database
);
53 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
56 return LocalTokenNumber
;
60 Get PCD type by Local Token Number.
62 @param[in] LocalTokenNumber The PCD local token number.
68 IN UINT32 LocalTokenNumber
71 switch (LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) {
72 case PCD_DATUM_TYPE_POINTER
:
73 return EFI_PCD_TYPE_PTR
;
74 case PCD_DATUM_TYPE_UINT8
:
75 if ((LocalTokenNumber
& PCD_DATUM_TYPE_UINT8_BOOLEAN
) == PCD_DATUM_TYPE_UINT8_BOOLEAN
) {
76 return EFI_PCD_TYPE_BOOL
;
78 return EFI_PCD_TYPE_8
;
80 case PCD_DATUM_TYPE_UINT16
:
81 return EFI_PCD_TYPE_16
;
82 case PCD_DATUM_TYPE_UINT32
:
83 return EFI_PCD_TYPE_32
;
84 case PCD_DATUM_TYPE_UINT64
:
85 return EFI_PCD_TYPE_64
;
88 return EFI_PCD_TYPE_8
;
95 @param[in] OnlyTokenSpaceName If TRUE, only need to get the TokenSpaceCName.
96 If FALSE, need to get the full PCD name.
97 @param[in] Database PCD database.
98 @param[in] TokenNumber The PCD token number.
100 @return The TokenSpaceCName or full PCD name.
104 IN BOOLEAN OnlyTokenSpaceName
,
105 IN PEI_PCD_DATABASE
*Database
,
111 PCD_NAME_INDEX
*PcdNameIndex
;
112 CHAR8
*TokenSpaceName
;
117 // Return NULL when PCD name table is absent.
119 if (Database
->PcdNameTableOffset
== 0) {
124 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
125 // We have to decrement TokenNumber by 1 to make it usable
126 // as the array index.
130 StringTable
= (UINT8
*) Database
+ Database
->StringTableOffset
;
133 // Get the PCD name index.
135 PcdNameIndex
= (PCD_NAME_INDEX
*)((UINT8
*) Database
+ Database
->PcdNameTableOffset
) + TokenNumber
;
136 TokenSpaceName
= (CHAR8
*)&StringTable
[PcdNameIndex
->TokenSpaceCNameIndex
];
137 PcdName
= (CHAR8
*)&StringTable
[PcdNameIndex
->PcdCNameIndex
];
139 if (OnlyTokenSpaceName
) {
141 // Only need to get the TokenSpaceCName.
143 Name
= AllocateCopyPool (AsciiStrSize (TokenSpaceName
), TokenSpaceName
);
146 // Need to get the full PCD name.
148 NameSize
= AsciiStrSize (TokenSpaceName
) + AsciiStrSize (PcdName
);
149 Name
= AllocateZeroPool (NameSize
);
150 ASSERT (Name
!= NULL
);
152 // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.
154 AsciiStrCatS (Name
, NameSize
, TokenSpaceName
);
155 Name
[AsciiStrSize (TokenSpaceName
) - sizeof (CHAR8
)] = '.';
156 AsciiStrCatS (Name
, NameSize
, PcdName
);
163 Retrieve additional information associated with a PCD token.
165 This includes information such as the type of value the TokenNumber is associated with as well as possible
166 human readable name that is associated with the token.
168 @param[in] Database PCD database.
169 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
170 @param[in] TokenNumber The PCD token number.
171 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
172 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
174 @retval EFI_SUCCESS The PCD information was returned successfully
175 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
179 IN PEI_PCD_DATABASE
*Database
,
180 IN CONST EFI_GUID
*Guid
,
181 IN UINTN TokenNumber
,
182 OUT EFI_PCD_INFO
*PcdInfo
188 DYNAMICEX_MAPPING
*ExMapTable
;
190 UINT32 LocalTokenNumber
;
192 GuidTable
= (EFI_GUID
*)((UINT8
*)Database
+ Database
->GuidTableOffset
);
193 MatchGuid
= ScanGuid (GuidTable
, Database
->GuidTableCount
* sizeof(EFI_GUID
), Guid
);
195 if (MatchGuid
== NULL
) {
196 return EFI_NOT_FOUND
;
199 GuidTableIdx
= MatchGuid
- GuidTable
;
201 ExMapTable
= (DYNAMICEX_MAPPING
*)((UINT8
*)Database
+ Database
->ExMapTableOffset
);
204 // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.
206 for (Index
= 0; Index
< Database
->ExTokenCount
; Index
++) {
207 if (ExMapTable
[Index
].ExGuidIndex
== GuidTableIdx
) {
208 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
210 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
211 // PcdSize to 0 and PcdName to the null-terminated ASCII string
212 // associated with the token's namespace Guid.
214 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
215 PcdInfo
->PcdSize
= 0;
217 // Here use one representative in the token space to get the TokenSpaceCName.
219 PcdInfo
->PcdName
= GetPcdName (TRUE
, Database
, ExMapTable
[Index
].TokenNumber
);
221 } else if (ExMapTable
[Index
].ExTokenNumber
== TokenNumber
) {
222 PcdInfo
->PcdSize
= PeiPcdGetSize (ExMapTable
[Index
].TokenNumber
);
223 LocalTokenNumber
= GetLocalTokenNumber (Database
, ExMapTable
[Index
].TokenNumber
);
224 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
225 PcdInfo
->PcdName
= GetPcdName (FALSE
, Database
, ExMapTable
[Index
].TokenNumber
);
231 return EFI_NOT_FOUND
;
235 Retrieve additional information associated with a PCD token.
237 This includes information such as the type of value the TokenNumber is associated with as well as possible
238 human readable name that is associated with the token.
240 @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value.
241 @param[in] TokenNumber The PCD token number.
242 @param[out] PcdInfo The returned information associated with the requested TokenNumber.
243 The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
245 @retval EFI_SUCCESS The PCD information was returned successfully.
246 @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
250 IN CONST EFI_GUID
*Guid
,
251 IN UINTN TokenNumber
,
252 OUT EFI_PCD_INFO
*PcdInfo
255 PEI_PCD_DATABASE
*PeiPcdDb
;
256 BOOLEAN PeiExMapTableEmpty
;
257 UINTN PeiNexTokenNumber
;
258 UINT32 LocalTokenNumber
;
260 ASSERT (PcdInfo
!= NULL
);
262 PeiPcdDb
= GetPcdDatabase ();
263 PeiNexTokenNumber
= PeiPcdDb
->LocalTokenCount
- PeiPcdDb
->ExTokenCount
;
265 if (PeiPcdDb
->ExTokenCount
== 0) {
266 PeiExMapTableEmpty
= TRUE
;
268 PeiExMapTableEmpty
= FALSE
;
272 if (TokenNumber
> PeiNexTokenNumber
) {
273 return EFI_NOT_FOUND
;
274 } else if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
276 // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,
277 // PcdSize to 0 and PcdName to NULL for default Token Space.
279 PcdInfo
->PcdType
= EFI_PCD_TYPE_8
;
280 PcdInfo
->PcdSize
= 0;
281 PcdInfo
->PcdName
= NULL
;
283 PcdInfo
->PcdSize
= PeiPcdGetSize (TokenNumber
);
284 LocalTokenNumber
= GetLocalTokenNumber (PeiPcdDb
, TokenNumber
);
285 PcdInfo
->PcdType
= GetPcdType (LocalTokenNumber
);
286 PcdInfo
->PcdName
= GetPcdName (FALSE
, PeiPcdDb
, TokenNumber
);
290 if (PeiExMapTableEmpty
) {
291 return EFI_NOT_FOUND
;
293 return ExGetPcdInfo (
303 The function registers the CallBackOnSet fucntion
304 according to TokenNumber and EFI_GUID space.
306 @param ExTokenNumber The token number.
307 @param Guid The GUID space.
308 @param CallBackFunction The Callback function to be registered.
309 @param Register To register or unregister the callback function.
311 @retval EFI_SUCCESS If the Callback function is registered.
312 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
313 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
314 slot left in the CallbackFnTable.
315 @retval EFI_INVALID_PARAMETER If the callback function want to be de-registered can not be found.
318 PeiRegisterCallBackWorker (
319 IN UINTN ExTokenNumber
,
320 IN CONST EFI_GUID
*Guid
, OPTIONAL
321 IN PCD_PPI_CALLBACK CallBackFunction
,
325 EFI_HOB_GUID_TYPE
*GuidHob
;
326 PCD_PPI_CALLBACK
*CallbackTable
;
327 PCD_PPI_CALLBACK Compare
;
328 PCD_PPI_CALLBACK Assign
;
329 UINT32 LocalTokenNumber
;
330 UINT32 LocalTokenCount
;
331 UINTN PeiNexTokenNumber
;
334 PEI_PCD_DATABASE
*PeiPcdDb
;
336 PeiPcdDb
= GetPcdDatabase();
337 LocalTokenCount
= PeiPcdDb
->LocalTokenCount
;
338 PeiNexTokenNumber
= PeiPcdDb
->LocalTokenCount
- PeiPcdDb
->ExTokenCount
;
341 TokenNumber
= ExTokenNumber
;
343 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
344 // We have to decrement TokenNumber by 1 to make it usable
345 // as the array index.
348 ASSERT (TokenNumber
+ 1 < (PeiNexTokenNumber
+ 1));
350 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
351 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
352 return EFI_NOT_FOUND
;
355 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
356 // We have to decrement TokenNumber by 1 to make it usable
357 // as the array index.
360 // EBC compiler is very choosy. It may report warning about comparison
361 // between UINTN and 0 . So we add 1 in each size of the
363 ASSERT ((TokenNumber
+ 1) < (LocalTokenCount
+ 1));
367 LocalTokenNumber
= *((UINT32
*)((UINT8
*)PeiPcdDb
+ PeiPcdDb
->LocalTokenNumberTableOffset
) + TokenNumber
);
370 // We don't support SET for HII and VPD type PCD entry in PEI phase.
371 // So we will assert if any register callback for such PCD entry.
373 ASSERT ((LocalTokenNumber
& PCD_TYPE_HII
) == 0);
374 ASSERT ((LocalTokenNumber
& PCD_TYPE_VPD
) == 0);
376 GuidHob
= GetFirstGuidHob (&gEfiCallerIdGuid
);
377 ASSERT (GuidHob
!= NULL
);
379 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
380 CallbackTable
= CallbackTable
+ (TokenNumber
* PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
382 Compare
= Register
? NULL
: CallBackFunction
;
383 Assign
= Register
? CallBackFunction
: NULL
;
386 for (Idx
= 0; Idx
< PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
387 if (CallbackTable
[Idx
] == Compare
) {
388 CallbackTable
[Idx
] = Assign
;
393 return Register
? EFI_OUT_OF_RESOURCES
: EFI_INVALID_PARAMETER
;
399 Find the Pcd database.
401 @param FileHandle Handle of the file the external PCD database binary located.
403 @retval The base address of external PCD database binary.
404 @retval NULL Return NULL if not find.
408 IN EFI_PEI_FILE_HANDLE FileHandle
416 ASSERT (FileHandle
!= NULL
);
418 Status
= PeiServicesFfsFindSectionData (EFI_SECTION_RAW
, FileHandle
, &PcdDb
);
419 ASSERT_EFI_ERROR (Status
);
422 // Check the first bytes (Header Signature Guid) and build version.
424 if (!CompareGuid (PcdDb
, &gPcdDataBaseSignatureGuid
) ||
425 (((PEI_PCD_DATABASE
*) PcdDb
)->BuildVersion
!= PCD_SERVICE_PEIM_VERSION
)) {
433 The function builds the PCD database.
435 @param FileHandle Handle of the file the external PCD database binary located.
437 @return Pointer to PCD database.
441 IN EFI_PEI_FILE_HANDLE FileHandle
444 PEI_PCD_DATABASE
*Database
;
445 PEI_PCD_DATABASE
*PeiPcdDbBinary
;
446 VOID
*CallbackFnTable
;
447 UINTN SizeOfCallbackFnTable
;
450 // Locate the external PCD database binary for one section of current FFS
452 PeiPcdDbBinary
= LocateExPcdBinary (FileHandle
);
454 ASSERT(PeiPcdDbBinary
!= NULL
);
456 Database
= BuildGuidHob (&gPcdDataBaseHobGuid
, PeiPcdDbBinary
->Length
+ PeiPcdDbBinary
->UninitDataBaseSize
);
458 ZeroMem (Database
, PeiPcdDbBinary
->Length
+ PeiPcdDbBinary
->UninitDataBaseSize
);
461 // PeiPcdDbBinary is smaller than Database
463 CopyMem (Database
, PeiPcdDbBinary
, PeiPcdDbBinary
->Length
);
465 SizeOfCallbackFnTable
= Database
->LocalTokenCount
* sizeof (PCD_PPI_CALLBACK
) * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry
);
467 CallbackFnTable
= BuildGuidHob (&gEfiCallerIdGuid
, SizeOfCallbackFnTable
);
469 ZeroMem (CallbackFnTable
, SizeOfCallbackFnTable
);
475 The function is provided by PCD PEIM and PCD DXE driver to
476 do the work of reading a HII variable from variable service.
478 @param VariableGuid The Variable GUID.
479 @param VariableName The Variable Name.
480 @param VariableData The output data.
481 @param VariableSize The size of the variable.
483 @retval EFI_SUCCESS Operation successful.
484 @retval EFI_NOT_FOUND Variablel not found.
488 IN CONST EFI_GUID
*VariableGuid
,
489 IN UINT16
*VariableName
,
490 OUT VOID
**VariableData
,
491 OUT UINTN
*VariableSize
497 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*VariablePpi
;
499 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
500 ASSERT_EFI_ERROR (Status
);
503 Status
= VariablePpi
->GetVariable (
506 (EFI_GUID
*) VariableGuid
,
512 if (Status
== EFI_BUFFER_TOO_SMALL
) {
513 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
514 ASSERT_EFI_ERROR (Status
);
516 Status
= VariablePpi
->GetVariable (
518 (UINT16
*) VariableName
,
519 (EFI_GUID
*) VariableGuid
,
524 ASSERT_EFI_ERROR (Status
);
526 *VariableSize
= Size
;
527 *VariableData
= Buffer
;
532 return EFI_NOT_FOUND
;
536 Find the local token number according to system SKU ID.
538 @param LocalTokenNumber PCD token number
539 @param Size The size of PCD entry.
541 @return Token number according to system SKU ID.
545 GetSkuEnabledTokenNumber (
546 UINT32 LocalTokenNumber
,
550 PEI_PCD_DATABASE
*PeiPcdDb
;
557 PeiPcdDb
= GetPcdDatabase ();
559 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
561 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
562 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
563 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
566 // Find the current system's SKU ID entry in SKU ID table.
569 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
570 if (PeiPcdDb
->SystemSkuId
== SkuIdTable
[Index
+ 1]) {
577 // Find the default SKU ID entry in SKU ID table.
580 for (Index
= 0; Index
< SkuIdTable
[0]; Index
++) {
581 if (0 == SkuIdTable
[Index
+ 1]) {
586 ASSERT (Index
< SkuIdTable
[0]);
588 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
590 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[Index
]);
591 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
594 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[Index
]);
595 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
597 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
598 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[Index
]);
599 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
| PCD_TYPE_STRING
);
601 case PCD_TYPE_STRING
:
602 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[Index
]);
603 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
606 Value
+= Size
* Index
;
607 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_DATA
);
619 Invoke the callback function when dynamic PCD entry was set, if this PCD entry
620 has registered callback function.
622 @param ExTokenNumber DynamicEx PCD's token number, if this PCD entry is dyanmicEx
624 @param Guid DynamicEx PCD's guid, if this PCD entry is dynamicEx type
626 @param TokenNumber PCD token number generated by build tools.
627 @param Data Value want to be set for this PCD entry
628 @param Size The size of value
632 InvokeCallbackOnSet (
634 CONST EFI_GUID
*Guid
, OPTIONAL
640 EFI_HOB_GUID_TYPE
*GuidHob
;
641 PCD_PPI_CALLBACK
*CallbackTable
;
643 PEI_PCD_DATABASE
*PeiPcdDb
;
644 UINT32 LocalTokenCount
;
647 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
648 // We have to decrement TokenNumber by 1 to make it usable
649 // as the array index.
653 PeiPcdDb
= GetPcdDatabase ();
654 LocalTokenCount
= PeiPcdDb
->LocalTokenCount
;
657 // EBC compiler is very choosy. It may report warning about comparison
658 // between UINTN and 0 . So we add 1 in each size of the
660 ASSERT (TokenNumber
+ 1 < (LocalTokenCount
+ 1));
663 GuidHob
= GetFirstGuidHob (&gEfiCallerIdGuid
);
664 ASSERT (GuidHob
!= NULL
);
666 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
668 CallbackTable
+= (TokenNumber
* PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
670 for (Idx
= 0; Idx
< PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
671 if (CallbackTable
[Idx
] != NULL
) {
672 CallbackTable
[Idx
] (Guid
,
673 (Guid
== NULL
) ? (TokenNumber
+ 1) : ExTokenNumber
,
682 Wrapper function for setting non-pointer type value for a PCD entry.
684 @param TokenNumber Pcd token number autogenerated by build tools.
685 @param Data Value want to be set for PCD entry
686 @param Size Size of value.
688 @return status of SetWorker.
693 IN UINTN TokenNumber
,
698 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
702 Set value for an PCD entry
704 @param TokenNumber Pcd token number autogenerated by build tools.
705 @param Data Value want to be set for PCD entry
706 @param Size Size of value.
707 @param PtrType If TRUE, the type of PCD entry's value is Pointer.
708 If False, the type of PCD entry's value is not Pointer.
710 @retval EFI_INVALID_PARAMETER If this PCD type is VPD, VPD PCD can not be set.
711 @retval EFI_INVALID_PARAMETER If Size can not be set to size table.
712 @retval EFI_INVALID_PARAMETER If Size of non-Ptr type PCD does not match the size information in PCD database.
713 @retval EFI_NOT_FOUND If value type of PCD entry is intergrate, but not in
714 range of UINT8, UINT16, UINT32, UINT64
715 @retval EFI_NOT_FOUND Can not find the PCD type according to token number.
719 IN UINTN TokenNumber
,
725 UINT32 LocalTokenNumber
;
726 UINTN PeiNexTokenNumber
;
727 PEI_PCD_DATABASE
*PeiPcdDb
;
728 STRING_HEAD StringTableIdx
;
732 UINT32 LocalTokenCount
;
734 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable
)) {
735 return EFI_UNSUPPORTED
;
739 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
740 // We have to decrement TokenNumber by 1 to make it usable
741 // as the array index.
744 PeiPcdDb
= GetPcdDatabase ();
745 LocalTokenCount
= PeiPcdDb
->LocalTokenCount
;
747 // EBC compiler is very choosy. It may report warning about comparison
748 // between UINTN and 0 . So we add 1 in each size of the
750 ASSERT (TokenNumber
+ 1 < (LocalTokenCount
+ 1));
754 // Get MaxSize first, then check new size with max buffer size.
756 GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
757 if (*Size
> MaxSize
) {
759 return EFI_INVALID_PARAMETER
;
762 if (*Size
!= PeiPcdGetSize (TokenNumber
+ 1)) {
763 return EFI_INVALID_PARAMETER
;
768 // We only invoke the callback function for Dynamic Type PCD Entry.
769 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
770 // type PCD entry in ExSetWorker.
772 PeiNexTokenNumber
= PeiPcdDb
->LocalTokenCount
- PeiPcdDb
->ExTokenCount
;
773 if (TokenNumber
+ 1 < PeiNexTokenNumber
+ 1) {
774 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
777 LocalTokenNumber
= GetLocalTokenNumber (PeiPcdDb
, TokenNumber
+ 1);
779 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
780 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
782 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
785 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
788 return EFI_INVALID_PARAMETER
;
791 case PCD_TYPE_STRING
:
792 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
793 StringTableIdx
= *((STRING_HEAD
*)InternalData
);
794 CopyMem ((UINT8
*)PeiPcdDb
+ PeiPcdDb
->StringTableOffset
+ StringTableIdx
, Data
, *Size
);
797 return EFI_INVALID_PARAMETER
;
803 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
804 CopyMem (InternalData
, Data
, *Size
);
807 return EFI_INVALID_PARAMETER
;
813 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
817 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
821 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
825 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
830 return EFI_NOT_FOUND
;
837 return EFI_NOT_FOUND
;
842 Wrapper function for set PCD value for non-Pointer type dynamic-ex PCD.
844 @param ExTokenNumber Token number for dynamic-ex PCD.
845 @param Guid Token space guid for dynamic-ex PCD.
846 @param Data Value want to be set.
847 @param SetSize The size of value.
849 @return status of ExSetWorker().
854 IN UINTN ExTokenNumber
,
855 IN CONST EFI_GUID
*Guid
,
860 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
864 Set value for a dynamic-ex PCD entry.
866 This routine find the local token number according to dynamic-ex PCD's token
867 space guid and token number firstly, and invoke callback function if this PCD
868 entry registered callback function. Finally, invoken general SetWorker to set
871 @param ExTokenNumber Dynamic-ex PCD token number.
872 @param Guid Token space guid for dynamic-ex PCD.
873 @param Data PCD value want to be set
874 @param SetSize Size of value.
875 @param PtrType If TRUE, this PCD entry is pointer type.
876 If FALSE, this PCD entry is not pointer type.
878 @return status of SetWorker().
883 IN UINTN ExTokenNumber
,
884 IN CONST EFI_GUID
*Guid
,
892 if (!FeaturePcdGet(PcdPeiFullPcdDatabaseEnable
)) {
893 return EFI_UNSUPPORTED
;
896 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
897 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
898 return EFI_NOT_FOUND
;
901 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
903 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
908 Wrapper function for get PCD value for dynamic-ex PCD.
910 @param Guid Token space guid for dynamic-ex PCD.
911 @param ExTokenNumber Token number for dyanmic-ex PCD.
912 @param GetSize The size of dynamic-ex PCD value.
914 @return PCD entry in PCD database.
919 IN CONST EFI_GUID
*Guid
,
920 IN UINTN ExTokenNumber
,
924 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
928 Get the PCD entry pointer in PCD database.
930 This routine will visit PCD database to find the PCD entry according to given
931 token number. The given token number is autogened by build tools and it will be
932 translated to local token number. Local token number contains PCD's type and
933 offset of PCD entry in PCD database.
935 @param TokenNumber Token's number, it is autogened by build tools
936 @param GetSize The size of token's value
938 @return PCD entry pointer in PCD database
943 IN UINTN TokenNumber
,
950 VARIABLE_HEAD
*VariableHead
;
955 STRING_HEAD StringTableIdx
;
956 PEI_PCD_DATABASE
*PeiPcdDb
;
957 UINT32 LocalTokenNumber
;
958 UINT32 LocalTokenCount
;
959 UINT8
*VaraiableDefaultBuffer
;
962 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
963 // We have to decrement TokenNumber by 1 to make it usable
964 // as the array index.
968 PeiPcdDb
= GetPcdDatabase ();
969 LocalTokenCount
= PeiPcdDb
->LocalTokenCount
;
971 // EBC compiler is very choosy. It may report warning about comparison
972 // between UINTN and 0 . So we add 1 in each size of the
974 ASSERT (TokenNumber
+ 1 < (LocalTokenCount
+ 1));
976 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
978 LocalTokenNumber
= GetLocalTokenNumber (PeiPcdDb
, TokenNumber
+ 1);
980 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
981 StringTable
= (UINT8
*)PeiPcdDb
+ PeiPcdDb
->StringTableOffset
;
983 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
987 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
988 return (VOID
*) (UINTN
) (PcdGet32 (PcdVpdBaseAddress
) + VpdHead
->Offset
);
991 case PCD_TYPE_HII
|PCD_TYPE_STRING
:
994 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
996 Guid
= (EFI_GUID
*) ((UINT8
*)PeiPcdDb
+ PeiPcdDb
->GuidTableOffset
) + VariableHead
->GuidTableIndex
;
997 Name
= (UINT16
*)&StringTable
[VariableHead
->StringIndex
];
999 if ((LocalTokenNumber
& PCD_TYPE_ALL_SET
) == (PCD_TYPE_HII
|PCD_TYPE_STRING
)) {
1001 // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of
1002 // string array in string table.
1004 VaraiableDefaultBuffer
= (UINT8
*) &StringTable
[*(STRING_HEAD
*)((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
)];
1006 VaraiableDefaultBuffer
= (UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
;
1008 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
1009 if ((Status
== EFI_SUCCESS
) && (DataSize
>= (VariableHead
->Offset
+ GetSize
))) {
1012 // It is a pointer type. So get the MaxSize reserved for
1015 GetPtrTypeSize (TokenNumber
, &GetSize
, PeiPcdDb
);
1016 if (GetSize
> (DataSize
- VariableHead
->Offset
)) {
1018 // Use actual valid size.
1020 GetSize
= DataSize
- VariableHead
->Offset
;
1024 // If the operation is successful, we copy the data
1025 // to the default value buffer in the PCD Database.
1027 CopyMem (VaraiableDefaultBuffer
, (UINT8
*) Data
+ VariableHead
->Offset
, GetSize
);
1029 return (VOID
*) VaraiableDefaultBuffer
;
1033 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
1035 case PCD_TYPE_STRING
:
1036 StringTableIdx
= * (STRING_HEAD
*) ((UINT8
*) PeiPcdDb
+ Offset
);
1037 return (VOID
*) (&StringTable
[StringTableIdx
]);
1052 Get Token Number according to dynamic-ex PCD's {token space guid:token number}
1054 A dynamic-ex type PCD, developer must provide pair of token space guid: token number
1055 in DEC file. PCD database maintain a mapping table that translate pair of {token
1056 space guid: token number} to Token Number.
1058 @param Guid Token space guid for dynamic-ex PCD entry.
1059 @param ExTokenNumber Dynamic-ex PCD token number.
1061 @return Token Number for dynamic-ex PCD.
1065 GetExPcdTokenNumber (
1066 IN CONST EFI_GUID
*Guid
,
1067 IN UINTN ExTokenNumber
1071 DYNAMICEX_MAPPING
*ExMap
;
1072 EFI_GUID
*GuidTable
;
1073 EFI_GUID
*MatchGuid
;
1075 PEI_PCD_DATABASE
*PeiPcdDb
;
1077 PeiPcdDb
= GetPcdDatabase();
1079 ExMap
= (DYNAMICEX_MAPPING
*)((UINT8
*)PeiPcdDb
+ PeiPcdDb
->ExMapTableOffset
);
1080 GuidTable
= (EFI_GUID
*)((UINT8
*)PeiPcdDb
+ PeiPcdDb
->GuidTableOffset
);
1082 MatchGuid
= ScanGuid (GuidTable
, PeiPcdDb
->GuidTableCount
* sizeof(EFI_GUID
), Guid
);
1084 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
1085 // error in the BUILD system.
1087 ASSERT (MatchGuid
!= NULL
);
1089 MatchGuidIdx
= MatchGuid
- GuidTable
;
1091 for (Index
= 0; Index
< PeiPcdDb
->ExTokenCount
; Index
++) {
1092 if ((ExTokenNumber
== ExMap
[Index
].ExTokenNumber
) &&
1093 (MatchGuidIdx
== ExMap
[Index
].ExGuidIndex
)) {
1094 return ExMap
[Index
].TokenNumber
;
1098 return PCD_INVALID_TOKEN_NUMBER
;
1102 Get PCD database from GUID HOB in PEI phase.
1104 @return Pointer to PCD database.
1112 EFI_HOB_GUID_TYPE
*GuidHob
;
1114 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
1115 ASSERT (GuidHob
!= NULL
);
1117 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
1121 Get SKU ID table from PCD database.
1123 @param LocalTokenNumberTableIdx Index of local token number in token number table.
1124 @param Database PCD database.
1126 @return Pointer to SKU ID array table
1131 IN UINTN LocalTokenNumberTableIdx
,
1132 IN PEI_PCD_DATABASE
*Database
1136 UINTN LocalTokenNumber
;
1138 LocalTokenNumber
= *((UINT32
*)((UINT8
*)Database
+ Database
->LocalTokenNumberTableOffset
) + LocalTokenNumberTableIdx
);
1140 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
1142 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
1144 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
1149 Get index of PCD entry in size table.
1151 @param LocalTokenNumberTableIdx Index of this PCD in local token number table.
1152 @param Database Pointer to PCD database in PEI phase.
1154 @return index of PCD entry in size table.
1159 IN UINTN LocalTokenNumberTableIdx
,
1160 IN PEI_PCD_DATABASE
*Database
1165 UINTN LocalTokenNumber
;
1170 for (Index
= 0; Index
< LocalTokenNumberTableIdx
; Index
++) {
1171 LocalTokenNumber
= *((UINT32
*)((UINT8
*)Database
+ Database
->LocalTokenNumberTableOffset
) + Index
);
1173 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
1175 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
1178 if ((LocalTokenNumber
& PCD_TYPE_VPD
) != 0) {
1180 // We have only two entry for VPD enabled PCD entry:
1183 // Current size is equal to MAX size.
1187 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
1189 // We have only two entry for Non-Sku enabled PCD entry:
1196 // We have these entry for SKU enabled PCD entry
1198 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
1200 SkuIdTable
= GetSkuIdArray (Index
, Database
);
1201 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
1208 return SizeTableIdx
;