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
21 The function registers the CallBackOnSet fucntion
22 according to TokenNumber and EFI_GUID space.
24 @param TokenNumber The token number.
25 @param Guid The GUID space.
26 @param CallBackFunction The Callback function to be registered.
27 @param Register To register or unregister the callback function.
29 @retval EFI_SUCCESS If the Callback function is registered.
30 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
31 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
32 slot left in the CallbackFnTable.
35 PeiRegisterCallBackWorker (
36 IN UINTN ExTokenNumber
,
37 IN CONST EFI_GUID
*Guid
, OPTIONAL
38 IN PCD_PPI_CALLBACK CallBackFunction
,
42 EFI_HOB_GUID_TYPE
*GuidHob
;
43 PCD_PPI_CALLBACK
*CallbackTable
;
44 PCD_PPI_CALLBACK Compare
;
45 PCD_PPI_CALLBACK Assign
;
46 UINT32 LocalTokenNumber
;
51 TokenNumber
= ExTokenNumber
;
54 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
55 // We have to decrement TokenNumber by 1 to make it usable
56 // as the array index.
59 ASSERT (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1);
61 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
64 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
65 // We have to decrement TokenNumber by 1 to make it usable
66 // as the array index.
69 // EBC compiler is very choosy. It may report warning about comparison
70 // between UINTN and 0 . So we add 1 in each size of the
72 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
76 LocalTokenNumber
= GetPcdDatabase()->Init
.LocalTokenNumberTable
[TokenNumber
];
79 // We don't support SET for HII and VPD type PCD entry in PEI phase.
80 // So we will assert if any register callback for such PCD entry.
82 ASSERT ((LocalTokenNumber
& PCD_TYPE_HII
) == 0);
83 ASSERT ((LocalTokenNumber
& PCD_TYPE_VPD
) == 0);
85 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
86 ASSERT (GuidHob
!= NULL
);
88 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
89 CallbackTable
= CallbackTable
+ (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
91 Compare
= Register
? NULL
: CallBackFunction
;
92 Assign
= Register
? CallBackFunction
: NULL
;
95 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
96 if (CallbackTable
[Idx
] == Compare
) {
97 CallbackTable
[Idx
] = Assign
;
102 return Register
? EFI_OUT_OF_RESOURCES
: EFI_NOT_FOUND
;
110 The function builds the PCD database.
121 PEI_PCD_DATABASE
*Database
;
122 VOID
*CallbackFnTable
;
123 UINTN SizeOfCallbackFnTable
;
125 Database
= BuildGuidHob (&gPcdDataBaseHobGuid
, sizeof (PEI_PCD_DATABASE
));
127 ZeroMem (Database
, sizeof (PEI_PCD_DATABASE
));
130 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
133 CopyMem (&Database
->Init
, &gPEIPcdDbInit
, sizeof (gPEIPcdDbInit
));
135 SizeOfCallbackFnTable
= PEI_LOCAL_TOKEN_NUMBER
* sizeof (PCD_PPI_CALLBACK
) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
);
137 CallbackFnTable
= BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid
, SizeOfCallbackFnTable
);
139 ZeroMem (CallbackFnTable
, SizeOfCallbackFnTable
);
147 The function is provided by PCD PEIM and PCD DXE driver to
148 do the work of reading a HII variable from variable service.
150 @param VariableGuid The Variable GUID.
151 @param VariableName The Variable Name.
152 @param VariableData The output data.
153 @param VariableSize The size of the variable.
155 @retval EFI_SUCCESS Operation successful.
156 @retval EFI_NOT_FOUND Variablel not found.
161 IN CONST EFI_GUID
*VariableGuid
,
162 IN UINT16
*VariableName
,
163 OUT VOID
**VariableData
,
164 OUT UINTN
*VariableSize
170 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*VariablePpi
;
172 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
173 ASSERT_EFI_ERROR (Status
);
176 Status
= VariablePpi
->GetVariable (
179 (EFI_GUID
*) VariableGuid
,
184 if (Status
== EFI_BUFFER_TOO_SMALL
) {
187 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
188 ASSERT_EFI_ERROR (Status
);
190 Status
= VariablePpi
->GetVariable (
192 (UINT16
*) VariableName
,
193 (EFI_GUID
*) VariableGuid
,
198 ASSERT_EFI_ERROR (Status
);
200 *VariableSize
= Size
;
201 *VariableData
= Buffer
;
205 return EFI_NOT_FOUND
;
212 GetSkuEnabledTokenNumber (
213 UINT32 LocalTokenNumber
,
217 PEI_PCD_DATABASE
*PeiPcdDb
;
223 PeiPcdDb
= GetPcdDatabase ();
225 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
227 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
228 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
229 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
231 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
232 if (PeiPcdDb
->Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
237 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
239 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
240 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
243 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
244 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
246 case PCD_TYPE_STRING
:
247 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[i
]);
248 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
252 return (UINT32
) (Value
- (UINT8
*) PeiPcdDb
);
268 InvokeCallbackOnSet (
270 CONST EFI_GUID
*Guid
, OPTIONAL
276 EFI_HOB_GUID_TYPE
*GuidHob
;
277 PCD_PPI_CALLBACK
*CallbackTable
;
281 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
282 // We have to decrement TokenNumber by 1 to make it usable
283 // as the array index.
288 // EBC compiler is very choosy. It may report warning about comparison
289 // between UINTN and 0 . So we add 1 in each size of the
291 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
294 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
295 ASSERT (GuidHob
!= NULL
);
297 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
299 CallbackTable
+= (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
301 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
302 if (CallbackTable
[Idx
] != NULL
) {
303 CallbackTable
[Idx
] (Guid
,
304 (Guid
== NULL
)? TokenNumber
: ExTokenNumber
,
317 IN UINTN TokenNumber
,
322 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
329 IN UINTN TokenNumber
,
335 UINT32 LocalTokenNumber
;
336 PEI_PCD_DATABASE
*PeiPcdDb
;
337 UINT16 StringTableIdx
;
342 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
343 return EFI_UNSUPPORTED
;
347 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
348 // We have to decrement TokenNumber by 1 to make it usable
349 // as the array index.
353 // EBC compiler is very choosy. It may report warning about comparison
354 // between UINTN and 0 . So we add 1 in each size of the
356 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
358 PeiPcdDb
= GetPcdDatabase ();
360 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
363 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
367 // We only invoke the callback function for Dynamic Type PCD Entry.
368 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
369 // type PCD entry in ExSetWorker.
371 if (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1) {
372 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
375 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
377 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
381 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
384 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
385 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
387 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
392 return EFI_INVALID_PARAMETER
;
395 case PCD_TYPE_STRING
:
396 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
397 StringTableIdx
= *((UINT16
*)InternalData
);
398 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
401 return EFI_INVALID_PARAMETER
;
407 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
408 CopyMem (InternalData
, Data
, *Size
);
411 return EFI_INVALID_PARAMETER
;
417 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
421 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
425 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
429 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
434 return EFI_NOT_FOUND
;
441 return EFI_NOT_FOUND
;
449 IN UINTN ExTokenNumber
,
450 IN CONST EFI_GUID
*Guid
,
455 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
462 IN UINTN ExTokenNumber
,
463 IN CONST EFI_GUID
*Guid
,
471 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
472 return EFI_UNSUPPORTED
;
475 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
477 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
479 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
488 IN CONST EFI_GUID
*Guid
,
489 IN UINTN ExTokenNumber
,
493 if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled
)) {
498 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
513 VARIABLE_HEAD
*VariableHead
;
518 UINT16 StringTableIdx
;
519 PEI_PCD_DATABASE
*PeiPcdDb
;
520 UINT32 LocalTokenNumber
;
524 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
525 // We have to decrement TokenNumber by 1 to make it usable
526 // as the array index.
530 // EBC compiler is very choosy. It may report warning about comparison
531 // between UINTN and 0 . So we add 1 in each size of the
533 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
535 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
537 PeiPcdDb
= GetPcdDatabase ();
539 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
541 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
543 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
547 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
550 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
551 StringTable
= PeiPcdDb
->Init
.StringTable
;
553 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
557 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
558 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
563 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
565 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
566 Name
= &StringTable
[VariableHead
->StringIndex
];
568 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
570 if (Status
== EFI_SUCCESS
) {
571 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
574 // Return the default value specified by Platform Integrator
576 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
581 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
583 case PCD_TYPE_STRING
:
584 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
585 return (VOID
*) (&StringTable
[StringTableIdx
]);
602 GetExPcdTokenNumber (
603 IN CONST EFI_GUID
*Guid
,
604 IN UINTN ExTokenNumber
608 DYNAMICEX_MAPPING
*ExMap
;
612 PEI_PCD_DATABASE
*PeiPcdDb
;
614 PeiPcdDb
= GetPcdDatabase();
616 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
617 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
619 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
621 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
622 // error in the BUILD system.
624 ASSERT (MatchGuid
!= NULL
);
626 MatchGuidIdx
= MatchGuid
- GuidTable
;
628 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
629 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
630 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
631 return ExMap
[i
].LocalTokenNumber
;
647 EFI_HOB_GUID_TYPE
*GuidHob
;
649 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
650 ASSERT (GuidHob
!= NULL
);
652 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
659 IN UINTN LocalTokenNumberTableIdx
,
660 IN PEI_PCD_DATABASE
*Database
664 UINTN LocalTokenNumber
;
666 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
668 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
670 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
672 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
680 IN UINTN LocalTokenNumberTableIdx
,
681 IN PEI_PCD_DATABASE
*Database
686 UINTN LocalTokenNumber
;
691 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
692 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
694 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
696 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
699 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
701 // We have only one entry for VPD enabled PCD entry:
703 // We consider current size is equal to MAX size.
707 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
709 // We have only two entry for Non-Sku enabled PCD entry:
716 // We have these entry for SKU enabled PCD entry
718 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
720 SkuIdTable
= GetSkuIdArray (i
, Database
);
721 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;