2 Private functions used by PCD PEIM.
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 Module Name: Service.c
20 The function registers the CallBackOnSet fucntion
21 according to TokenNumber and EFI_GUID space.
23 @param[in] TokenNumber The token number.
24 @param[in] Guid The GUID space.
25 @param[in] CallBackFunction The Callback function to be registered.
27 @retval EFI_SUCCESS If the Callback function is registered.
28 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
31 PeiRegisterCallBackWorker (
32 IN UINTN ExTokenNumber
,
33 IN CONST EFI_GUID
*Guid
, OPTIONAL
34 IN PCD_PPI_CALLBACK CallBackFunction
,
38 EFI_HOB_GUID_TYPE
*GuidHob
;
39 PCD_PPI_CALLBACK
*CallbackTable
;
40 PCD_PPI_CALLBACK Compare
;
41 PCD_PPI_CALLBACK Assign
;
42 UINT32 LocalTokenNumber
;
47 TokenNumber
= ExTokenNumber
;
50 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
51 // We have to decrement TokenNumber by 1 to make it usable
52 // as the array index.
55 ASSERT (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1);
57 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
60 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
61 // We have to decrement TokenNumber by 1 to make it usable
62 // as the array index.
65 // EBC compiler is very choosy. It may report warning about comparison
66 // between UINTN and 0 . So we add 1 in each size of the
68 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
72 LocalTokenNumber
= GetPcdDatabase()->Init
.LocalTokenNumberTable
[TokenNumber
];
75 // We don't support SET for HII and VPD type PCD entry in PEI phase.
76 // So we will assert if any register callback for such PCD entry.
78 ASSERT ((LocalTokenNumber
& PCD_TYPE_HII
) == 0);
79 ASSERT ((LocalTokenNumber
& PCD_TYPE_VPD
) == 0);
81 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
82 ASSERT (GuidHob
!= NULL
);
84 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
85 CallbackTable
= CallbackTable
+ (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
87 Compare
= Register
? NULL
: CallBackFunction
;
88 Assign
= Register
? CallBackFunction
: NULL
;
91 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
92 if (CallbackTable
[Idx
] == Compare
) {
93 CallbackTable
[Idx
] = Assign
;
98 return Register
? EFI_OUT_OF_RESOURCES
: EFI_NOT_FOUND
;
106 The function builds the PCD database based on the
107 PCD_IMAGE on the flash.
109 @param[in] PcdImageOnFlash The PCD image on flash.
118 PEI_PCD_DATABASE
*Database
;
119 VOID
*CallbackFnTable
;
120 UINTN SizeOfCallbackFnTable
;
122 Database
= BuildGuidHob (&gPcdDataBaseHobGuid
, sizeof (PEI_PCD_DATABASE
));
124 ZeroMem (Database
, sizeof (PEI_PCD_DATABASE
));
127 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
130 CopyMem (&Database
->Init
, &gPEIPcdDbInit
, sizeof (gPEIPcdDbInit
));
132 SizeOfCallbackFnTable
= PEI_LOCAL_TOKEN_NUMBER
* sizeof (PCD_PPI_CALLBACK
) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
);
134 CallbackFnTable
= BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid
, SizeOfCallbackFnTable
);
136 ZeroMem (CallbackFnTable
, SizeOfCallbackFnTable
);
144 The function is provided by PCD PEIM and PCD DXE driver to
145 do the work of reading a HII variable from variable service.
147 @param[in] VariableGuid The Variable GUID.
148 @param[in] VariableName The Variable Name.
149 @param[out] VariableData The output data.
150 @param[out] VariableSize The size of the variable.
152 @retval EFI_SUCCESS Operation successful.
153 @retval EFI_SUCCESS Variablel not found.
157 IN CONST EFI_GUID
*VariableGuid
,
158 IN UINT16
*VariableName
,
159 OUT VOID
**VariableData
,
160 OUT UINTN
*VariableSize
166 EFI_PEI_READ_ONLY_VARIABLE_PPI
*VariablePpi
;
168 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
169 ASSERT_EFI_ERROR (Status
);
172 Status
= VariablePpi
->PeiGetVariable (
173 GetPeiServicesTablePointer (),
175 (EFI_GUID
*) VariableGuid
,
180 if (Status
== EFI_BUFFER_TOO_SMALL
) {
183 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
184 ASSERT_EFI_ERROR (Status
);
186 Status
= VariablePpi
->PeiGetVariable (
187 GetPeiServicesTablePointer (),
188 (UINT16
*) VariableName
,
189 (EFI_GUID
*) VariableGuid
,
194 ASSERT_EFI_ERROR (Status
);
196 *VariableSize
= Size
;
197 *VariableData
= Buffer
;
201 return EFI_NOT_FOUND
;
208 GetSkuEnabledTokenNumber (
209 UINT32 LocalTokenNumber
,
213 PEI_PCD_DATABASE
*PeiPcdDb
;
219 PeiPcdDb
= GetPcdDatabase ();
221 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
223 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
224 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
225 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
227 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
228 if (PeiPcdDb
->Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
233 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
235 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
236 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
239 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
240 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
242 case PCD_TYPE_STRING
:
243 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[i
]);
244 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
248 return (UINT32
) (Value
- (UINT8
*) PeiPcdDb
);
264 InvokeCallbackOnSet (
266 CONST EFI_GUID
*Guid
, OPTIONAL
272 EFI_HOB_GUID_TYPE
*GuidHob
;
273 PCD_PPI_CALLBACK
*CallbackTable
;
277 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
278 // We have to decrement TokenNumber by 1 to make it usable
279 // as the array index.
284 // EBC compiler is very choosy. It may report warning about comparison
285 // between UINTN and 0 . So we add 1 in each size of the
287 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
290 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
291 ASSERT (GuidHob
!= NULL
);
293 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
295 CallbackTable
+= (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
297 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
298 if (CallbackTable
[Idx
] != NULL
) {
299 CallbackTable
[Idx
] (Guid
,
300 (Guid
== NULL
)? TokenNumber
: ExTokenNumber
,
313 IN UINTN TokenNumber
,
318 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
325 IN UINTN TokenNumber
,
331 UINT32 LocalTokenNumber
;
332 PEI_PCD_DATABASE
*PeiPcdDb
;
333 UINT16 StringTableIdx
;
339 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
340 // We have to decrement TokenNumber by 1 to make it usable
341 // as the array index.
345 // EBC compiler is very choosy. It may report warning about comparison
346 // between UINTN and 0 . So we add 1 in each size of the
348 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
350 PeiPcdDb
= GetPcdDatabase ();
352 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
355 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
359 // We only invoke the callback function for Dynamic Type PCD Entry.
360 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
361 // type PCD entry in ExSetWorker.
363 if (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1) {
364 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
367 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
369 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
373 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
376 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
377 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
379 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
384 return EFI_INVALID_PARAMETER
;
387 case PCD_TYPE_STRING
:
388 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
389 StringTableIdx
= *((UINT16
*)InternalData
);
390 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
393 return EFI_INVALID_PARAMETER
;
399 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
400 CopyMem (InternalData
, Data
, *Size
);
403 return EFI_INVALID_PARAMETER
;
409 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
413 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
417 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
421 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
426 return EFI_NOT_FOUND
;
433 return EFI_NOT_FOUND
;
441 IN UINTN ExTokenNumber
,
442 IN CONST EFI_GUID
*Guid
,
447 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
454 IN UINTN ExTokenNumber
,
455 IN CONST EFI_GUID
*Guid
,
463 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
465 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
467 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
476 IN CONST EFI_GUID
*Guid
,
477 IN UINTN ExTokenNumber
,
481 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
496 VARIABLE_HEAD
*VariableHead
;
501 UINT16 StringTableIdx
;
502 PEI_PCD_DATABASE
*PeiPcdDb
;
503 UINT32 LocalTokenNumber
;
507 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
508 // We have to decrement TokenNumber by 1 to make it usable
509 // as the array index.
513 // EBC compiler is very choosy. It may report warning about comparison
514 // between UINTN and 0 . So we add 1 in each size of the
516 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
518 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
520 PeiPcdDb
= GetPcdDatabase ();
522 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
524 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
526 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
530 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
533 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
534 StringTable
= PeiPcdDb
->Init
.StringTable
;
536 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
540 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
541 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
546 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
548 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
549 Name
= &StringTable
[VariableHead
->StringIndex
];
551 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
553 if (Status
== EFI_SUCCESS
) {
554 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
557 // Return the default value specified by Platform Integrator
559 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
564 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
566 case PCD_TYPE_STRING
:
567 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
568 return (VOID
*) (&StringTable
[StringTableIdx
]);
584 GetExPcdTokenNumber (
585 IN CONST EFI_GUID
*Guid
,
586 IN UINTN ExTokenNumber
590 DYNAMICEX_MAPPING
*ExMap
;
594 PEI_PCD_DATABASE
*PeiPcdDb
;
596 PeiPcdDb
= GetPcdDatabase();
598 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
599 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
601 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
603 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
604 // error in the BUILD system.
606 ASSERT (MatchGuid
!= NULL
);
608 MatchGuidIdx
= MatchGuid
- GuidTable
;
610 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
611 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
612 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
613 return ExMap
[i
].LocalTokenNumber
;
629 EFI_HOB_GUID_TYPE
*GuidHob
;
631 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
632 ASSERT (GuidHob
!= NULL
);
634 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
640 IN UINTN LocalTokenNumberTableIdx
,
641 IN PEI_PCD_DATABASE
*Database
645 UINTN LocalTokenNumber
;
647 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
649 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
651 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
653 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
661 IN UINTN LocalTokenNumberTableIdx
,
662 IN PEI_PCD_DATABASE
*Database
667 UINTN LocalTokenNumber
;
672 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
673 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
675 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
677 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
680 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
682 // We have only one entry for VPD enabled PCD entry:
684 // We consider current size is equal to MAX size.
688 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
690 // We have only two entry for Non-Sku enabled PCD entry:
697 // We have these entry for SKU enabled PCD entry
699 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
701 SkuIdTable
= GetSkuIdArray (i
, Database
);
702 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
717 IN UINTN LocalTokenNumberTableIdx
,
719 IN PEI_PCD_DATABASE
*Database
723 UINTN LocalTokenNumber
;
725 SIZE_INFO
*SizeTable
;
728 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
730 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
732 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
734 SizeTable
= Database
->Init
.SizeTable
;
736 *MaxSize
= SizeTable
[SizeTableIdx
];
738 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
741 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
743 // We have only one entry for VPD enabled PCD entry:
745 // We consider current size is equal to MAX size.
749 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
751 // We have only two entry for Non-Sku enabled PCD entry:
755 return SizeTable
[SizeTableIdx
+ 1];
758 // We have these entry for SKU enabled PCD entry
760 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
762 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
763 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
764 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
765 return SizeTable
[SizeTableIdx
+ 1 + i
];
768 return SizeTable
[SizeTableIdx
+ 1];
777 IN UINTN LocalTokenNumberTableIdx
,
778 IN OUT UINTN
*CurrentSize
,
779 IN PEI_PCD_DATABASE
*Database
783 UINTN LocalTokenNumber
;
785 SIZE_INFO
*SizeTable
;
789 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
791 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
793 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
795 SizeTable
= Database
->Init
.SizeTable
;
797 MaxSize
= SizeTable
[SizeTableIdx
];
799 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
802 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
804 // We shouldn't come here as we don't support SET for VPD
809 if ((*CurrentSize
> MaxSize
) ||
810 (*CurrentSize
== MAX_ADDRESS
)) {
811 *CurrentSize
= MaxSize
;
815 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
817 // We have only two entry for Non-Sku enabled PCD entry:
821 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
825 // We have these entry for SKU enabled PCD entry
827 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
829 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
830 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
831 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
832 SizeTable
[SizeTableIdx
+ 1 + i
] = (SIZE_INFO
) *CurrentSize
;
836 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;