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 TokenNumber The token number.
24 @param Guid The GUID space.
25 @param CallBackFunction The Callback function to be registered.
26 @param Register To register or unregister the callback function.
28 @retval EFI_SUCCESS If the Callback function is registered.
29 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
30 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
31 slot left in the CallbackFnTable.
34 PeiRegisterCallBackWorker (
35 IN UINTN ExTokenNumber
,
36 IN CONST EFI_GUID
*Guid
, OPTIONAL
37 IN PCD_PPI_CALLBACK CallBackFunction
,
41 EFI_HOB_GUID_TYPE
*GuidHob
;
42 PCD_PPI_CALLBACK
*CallbackTable
;
43 PCD_PPI_CALLBACK Compare
;
44 PCD_PPI_CALLBACK Assign
;
45 UINT32 LocalTokenNumber
;
50 TokenNumber
= ExTokenNumber
;
53 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
54 // We have to decrement TokenNumber by 1 to make it usable
55 // as the array index.
58 ASSERT (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1);
60 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
63 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
64 // We have to decrement TokenNumber by 1 to make it usable
65 // as the array index.
68 // EBC compiler is very choosy. It may report warning about comparison
69 // between UINTN and 0 . So we add 1 in each size of the
71 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
75 LocalTokenNumber
= GetPcdDatabase()->Init
.LocalTokenNumberTable
[TokenNumber
];
78 // We don't support SET for HII and VPD type PCD entry in PEI phase.
79 // So we will assert if any register callback for such PCD entry.
81 ASSERT ((LocalTokenNumber
& PCD_TYPE_HII
) == 0);
82 ASSERT ((LocalTokenNumber
& PCD_TYPE_VPD
) == 0);
84 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
85 ASSERT (GuidHob
!= NULL
);
87 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
88 CallbackTable
= CallbackTable
+ (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
90 Compare
= Register
? NULL
: CallBackFunction
;
91 Assign
= Register
? CallBackFunction
: NULL
;
94 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
95 if (CallbackTable
[Idx
] == Compare
) {
96 CallbackTable
[Idx
] = Assign
;
101 return Register
? EFI_OUT_OF_RESOURCES
: EFI_NOT_FOUND
;
109 The function builds the PCD database.
120 PEI_PCD_DATABASE
*Database
;
121 VOID
*CallbackFnTable
;
122 UINTN SizeOfCallbackFnTable
;
124 Database
= BuildGuidHob (&gPcdDataBaseHobGuid
, sizeof (PEI_PCD_DATABASE
));
126 ZeroMem (Database
, sizeof (PEI_PCD_DATABASE
));
129 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
132 CopyMem (&Database
->Init
, &gPEIPcdDbInit
, sizeof (gPEIPcdDbInit
));
134 SizeOfCallbackFnTable
= PEI_LOCAL_TOKEN_NUMBER
* sizeof (PCD_PPI_CALLBACK
) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
);
136 CallbackFnTable
= BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid
, SizeOfCallbackFnTable
);
138 ZeroMem (CallbackFnTable
, SizeOfCallbackFnTable
);
146 The function is provided by PCD PEIM and PCD DXE driver to
147 do the work of reading a HII variable from variable service.
149 @param VariableGuid The Variable GUID.
150 @param VariableName The Variable Name.
151 @param VariableData The output data.
152 @param VariableSize The size of the variable.
154 @retval EFI_SUCCESS Operation successful.
155 @retval EFI_NOT_FOUND Variablel not found.
159 IN CONST EFI_GUID
*VariableGuid
,
160 IN UINT16
*VariableName
,
161 OUT VOID
**VariableData
,
162 OUT UINTN
*VariableSize
168 EFI_PEI_READ_ONLY_VARIABLE_PPI
*VariablePpi
;
170 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
171 ASSERT_EFI_ERROR (Status
);
174 Status
= VariablePpi
->PeiGetVariable (
175 GetPeiServicesTablePointer (),
177 (EFI_GUID
*) VariableGuid
,
182 if (Status
== EFI_BUFFER_TOO_SMALL
) {
185 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
186 ASSERT_EFI_ERROR (Status
);
188 Status
= VariablePpi
->PeiGetVariable (
189 GetPeiServicesTablePointer (),
190 (UINT16
*) VariableName
,
191 (EFI_GUID
*) VariableGuid
,
196 ASSERT_EFI_ERROR (Status
);
198 *VariableSize
= Size
;
199 *VariableData
= Buffer
;
203 return EFI_NOT_FOUND
;
210 GetSkuEnabledTokenNumber (
211 UINT32 LocalTokenNumber
,
215 PEI_PCD_DATABASE
*PeiPcdDb
;
221 PeiPcdDb
= GetPcdDatabase ();
223 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
225 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
226 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
227 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
229 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
230 if (PeiPcdDb
->Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
235 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
237 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
238 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
241 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
242 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
244 case PCD_TYPE_STRING
:
245 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[i
]);
246 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
250 return (UINT32
) (Value
- (UINT8
*) PeiPcdDb
);
266 InvokeCallbackOnSet (
268 CONST EFI_GUID
*Guid
, OPTIONAL
274 EFI_HOB_GUID_TYPE
*GuidHob
;
275 PCD_PPI_CALLBACK
*CallbackTable
;
279 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
280 // We have to decrement TokenNumber by 1 to make it usable
281 // as the array index.
286 // EBC compiler is very choosy. It may report warning about comparison
287 // between UINTN and 0 . So we add 1 in each size of the
289 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
292 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
293 ASSERT (GuidHob
!= NULL
);
295 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
297 CallbackTable
+= (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
299 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
300 if (CallbackTable
[Idx
] != NULL
) {
301 CallbackTable
[Idx
] (Guid
,
302 (Guid
== NULL
)? TokenNumber
: ExTokenNumber
,
315 IN UINTN TokenNumber
,
320 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
327 IN UINTN TokenNumber
,
333 UINT32 LocalTokenNumber
;
334 PEI_PCD_DATABASE
*PeiPcdDb
;
335 UINT16 StringTableIdx
;
341 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
342 // We have to decrement TokenNumber by 1 to make it usable
343 // as the array index.
347 // EBC compiler is very choosy. It may report warning about comparison
348 // between UINTN and 0 . So we add 1 in each size of the
350 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
352 PeiPcdDb
= GetPcdDatabase ();
354 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
357 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
361 // We only invoke the callback function for Dynamic Type PCD Entry.
362 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
363 // type PCD entry in ExSetWorker.
365 if (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1) {
366 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
369 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
371 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
375 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
378 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
379 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
381 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
386 return EFI_INVALID_PARAMETER
;
389 case PCD_TYPE_STRING
:
390 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
391 StringTableIdx
= *((UINT16
*)InternalData
);
392 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
395 return EFI_INVALID_PARAMETER
;
401 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
402 CopyMem (InternalData
, Data
, *Size
);
405 return EFI_INVALID_PARAMETER
;
411 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
415 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
419 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
423 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
428 return EFI_NOT_FOUND
;
435 return EFI_NOT_FOUND
;
443 IN UINTN ExTokenNumber
,
444 IN CONST EFI_GUID
*Guid
,
449 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
456 IN UINTN ExTokenNumber
,
457 IN CONST EFI_GUID
*Guid
,
465 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
467 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
469 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
478 IN CONST EFI_GUID
*Guid
,
479 IN UINTN ExTokenNumber
,
483 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
498 VARIABLE_HEAD
*VariableHead
;
503 UINT16 StringTableIdx
;
504 PEI_PCD_DATABASE
*PeiPcdDb
;
505 UINT32 LocalTokenNumber
;
509 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
510 // We have to decrement TokenNumber by 1 to make it usable
511 // as the array index.
515 // EBC compiler is very choosy. It may report warning about comparison
516 // between UINTN and 0 . So we add 1 in each size of the
518 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
520 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
522 PeiPcdDb
= GetPcdDatabase ();
524 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
526 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
528 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
532 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
535 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
536 StringTable
= PeiPcdDb
->Init
.StringTable
;
538 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
542 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
543 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
548 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
550 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
551 Name
= &StringTable
[VariableHead
->StringIndex
];
553 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
555 if (Status
== EFI_SUCCESS
) {
556 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
559 // Return the default value specified by Platform Integrator
561 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
566 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
568 case PCD_TYPE_STRING
:
569 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
570 return (VOID
*) (&StringTable
[StringTableIdx
]);
587 GetExPcdTokenNumber (
588 IN CONST EFI_GUID
*Guid
,
589 IN UINTN ExTokenNumber
593 DYNAMICEX_MAPPING
*ExMap
;
597 PEI_PCD_DATABASE
*PeiPcdDb
;
599 PeiPcdDb
= GetPcdDatabase();
601 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
602 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
604 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
606 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
607 // error in the BUILD system.
609 ASSERT (MatchGuid
!= NULL
);
611 MatchGuidIdx
= MatchGuid
- GuidTable
;
613 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
614 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
615 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
616 return ExMap
[i
].LocalTokenNumber
;
632 EFI_HOB_GUID_TYPE
*GuidHob
;
634 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
635 ASSERT (GuidHob
!= NULL
);
637 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
644 IN UINTN LocalTokenNumberTableIdx
,
645 IN PEI_PCD_DATABASE
*Database
649 UINTN LocalTokenNumber
;
651 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
653 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
655 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
657 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
665 IN UINTN LocalTokenNumberTableIdx
,
666 IN PEI_PCD_DATABASE
*Database
671 UINTN LocalTokenNumber
;
676 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
677 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
679 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
681 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
684 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
686 // We have only one entry for VPD enabled PCD entry:
688 // We consider current size is equal to MAX size.
692 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
694 // We have only two entry for Non-Sku enabled PCD entry:
701 // We have these entry for SKU enabled PCD entry
703 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
705 SkuIdTable
= GetSkuIdArray (i
, Database
);
706 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
721 IN UINTN LocalTokenNumberTableIdx
,
723 IN PEI_PCD_DATABASE
*Database
727 UINTN LocalTokenNumber
;
729 SIZE_INFO
*SizeTable
;
732 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
734 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
736 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
738 SizeTable
= Database
->Init
.SizeTable
;
740 *MaxSize
= SizeTable
[SizeTableIdx
];
742 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
745 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
747 // We have only one entry for VPD enabled PCD entry:
749 // We consider current size is equal to MAX size.
753 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
755 // We have only two entry for Non-Sku enabled PCD entry:
759 return SizeTable
[SizeTableIdx
+ 1];
762 // We have these entry for SKU enabled PCD entry
764 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
766 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
767 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
768 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
769 return SizeTable
[SizeTableIdx
+ 1 + i
];
772 return SizeTable
[SizeTableIdx
+ 1];
781 IN UINTN LocalTokenNumberTableIdx
,
782 IN OUT UINTN
*CurrentSize
,
783 IN PEI_PCD_DATABASE
*Database
787 UINTN LocalTokenNumber
;
789 SIZE_INFO
*SizeTable
;
793 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
795 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
797 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
799 SizeTable
= Database
->Init
.SizeTable
;
801 MaxSize
= SizeTable
[SizeTableIdx
];
803 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
806 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
808 // We shouldn't come here as we don't support SET for VPD
813 if ((*CurrentSize
> MaxSize
) ||
814 (*CurrentSize
== MAX_ADDRESS
)) {
815 *CurrentSize
= MaxSize
;
819 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
821 // We have only two entry for Non-Sku enabled PCD entry:
825 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
829 // We have these entry for SKU enabled PCD entry
831 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
833 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
834 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
835 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
836 SizeTable
[SizeTableIdx
+ 1 + i
] = (SIZE_INFO
) *CurrentSize
;
840 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;