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
;
340 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
341 return EFI_UNSUPPORTED
;
345 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
346 // We have to decrement TokenNumber by 1 to make it usable
347 // as the array index.
351 // EBC compiler is very choosy. It may report warning about comparison
352 // between UINTN and 0 . So we add 1 in each size of the
354 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
356 PeiPcdDb
= GetPcdDatabase ();
358 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
361 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
365 // We only invoke the callback function for Dynamic Type PCD Entry.
366 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
367 // type PCD entry in ExSetWorker.
369 if (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1) {
370 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
373 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
375 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
379 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
382 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
383 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
385 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
390 return EFI_INVALID_PARAMETER
;
393 case PCD_TYPE_STRING
:
394 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
395 StringTableIdx
= *((UINT16
*)InternalData
);
396 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
399 return EFI_INVALID_PARAMETER
;
405 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
406 CopyMem (InternalData
, Data
, *Size
);
409 return EFI_INVALID_PARAMETER
;
415 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
419 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
423 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
427 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
432 return EFI_NOT_FOUND
;
439 return EFI_NOT_FOUND
;
447 IN UINTN ExTokenNumber
,
448 IN CONST EFI_GUID
*Guid
,
453 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
460 IN UINTN ExTokenNumber
,
461 IN CONST EFI_GUID
*Guid
,
469 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
470 return EFI_UNSUPPORTED
;
473 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
475 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
477 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
486 IN CONST EFI_GUID
*Guid
,
487 IN UINTN ExTokenNumber
,
491 if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled
)) {
496 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
511 VARIABLE_HEAD
*VariableHead
;
516 UINT16 StringTableIdx
;
517 PEI_PCD_DATABASE
*PeiPcdDb
;
518 UINT32 LocalTokenNumber
;
522 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
523 // We have to decrement TokenNumber by 1 to make it usable
524 // as the array index.
528 // EBC compiler is very choosy. It may report warning about comparison
529 // between UINTN and 0 . So we add 1 in each size of the
531 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
533 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
535 PeiPcdDb
= GetPcdDatabase ();
537 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
539 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
541 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
545 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
548 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
549 StringTable
= PeiPcdDb
->Init
.StringTable
;
551 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
555 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
556 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
561 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
563 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
564 Name
= &StringTable
[VariableHead
->StringIndex
];
566 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
568 if (Status
== EFI_SUCCESS
) {
569 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
572 // Return the default value specified by Platform Integrator
574 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
579 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
581 case PCD_TYPE_STRING
:
582 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
583 return (VOID
*) (&StringTable
[StringTableIdx
]);
600 GetExPcdTokenNumber (
601 IN CONST EFI_GUID
*Guid
,
602 IN UINTN ExTokenNumber
606 DYNAMICEX_MAPPING
*ExMap
;
610 PEI_PCD_DATABASE
*PeiPcdDb
;
612 PeiPcdDb
= GetPcdDatabase();
614 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
615 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
617 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
619 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
620 // error in the BUILD system.
622 ASSERT (MatchGuid
!= NULL
);
624 MatchGuidIdx
= MatchGuid
- GuidTable
;
626 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
627 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
628 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
629 return ExMap
[i
].LocalTokenNumber
;
645 EFI_HOB_GUID_TYPE
*GuidHob
;
647 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
648 ASSERT (GuidHob
!= NULL
);
650 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
657 IN UINTN LocalTokenNumberTableIdx
,
658 IN PEI_PCD_DATABASE
*Database
662 UINTN LocalTokenNumber
;
664 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
666 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
668 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
670 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
678 IN UINTN LocalTokenNumberTableIdx
,
679 IN PEI_PCD_DATABASE
*Database
684 UINTN LocalTokenNumber
;
689 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
690 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
692 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
694 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
697 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
699 // We have only one entry for VPD enabled PCD entry:
701 // We consider current size is equal to MAX size.
705 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
707 // We have only two entry for Non-Sku enabled PCD entry:
714 // We have these entry for SKU enabled PCD entry
716 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
718 SkuIdTable
= GetSkuIdArray (i
, Database
);
719 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
734 IN UINTN LocalTokenNumberTableIdx
,
736 IN PEI_PCD_DATABASE
*Database
740 UINTN LocalTokenNumber
;
742 SIZE_INFO
*SizeTable
;
745 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
747 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
749 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
751 SizeTable
= Database
->Init
.SizeTable
;
753 *MaxSize
= SizeTable
[SizeTableIdx
];
755 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
758 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
760 // We have only one entry for VPD enabled PCD entry:
762 // We consider current size is equal to MAX size.
766 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
768 // We have only two entry for Non-Sku enabled PCD entry:
772 return SizeTable
[SizeTableIdx
+ 1];
775 // We have these entry for SKU enabled PCD entry
777 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
779 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
780 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
781 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
782 return SizeTable
[SizeTableIdx
+ 1 + i
];
785 return SizeTable
[SizeTableIdx
+ 1];
794 IN UINTN LocalTokenNumberTableIdx
,
795 IN OUT UINTN
*CurrentSize
,
796 IN PEI_PCD_DATABASE
*Database
800 UINTN LocalTokenNumber
;
802 SIZE_INFO
*SizeTable
;
806 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
808 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
810 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
812 SizeTable
= Database
->Init
.SizeTable
;
814 MaxSize
= SizeTable
[SizeTableIdx
];
816 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
819 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
821 // We shouldn't come here as we don't support SET for VPD
826 if ((*CurrentSize
> MaxSize
) ||
827 (*CurrentSize
== MAX_ADDRESS
)) {
828 *CurrentSize
= MaxSize
;
832 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
834 // We have only two entry for Non-Sku enabled PCD entry:
838 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
842 // We have these entry for SKU enabled PCD entry
844 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
846 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
847 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
848 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
849 SizeTable
[SizeTableIdx
+ 1 + i
] = (SIZE_INFO
) *CurrentSize
;
853 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;