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.
160 IN CONST EFI_GUID
*VariableGuid
,
161 IN UINT16
*VariableName
,
162 OUT VOID
**VariableData
,
163 OUT UINTN
*VariableSize
169 EFI_PEI_READ_ONLY_VARIABLE_PPI
*VariablePpi
;
171 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
172 ASSERT_EFI_ERROR (Status
);
175 Status
= VariablePpi
->PeiGetVariable (
176 GetPeiServicesTablePointer (),
178 (EFI_GUID
*) VariableGuid
,
183 if (Status
== EFI_BUFFER_TOO_SMALL
) {
186 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
187 ASSERT_EFI_ERROR (Status
);
189 Status
= VariablePpi
->PeiGetVariable (
190 GetPeiServicesTablePointer (),
191 (UINT16
*) VariableName
,
192 (EFI_GUID
*) VariableGuid
,
197 ASSERT_EFI_ERROR (Status
);
199 *VariableSize
= Size
;
200 *VariableData
= Buffer
;
204 return EFI_NOT_FOUND
;
211 GetSkuEnabledTokenNumber (
212 UINT32 LocalTokenNumber
,
216 PEI_PCD_DATABASE
*PeiPcdDb
;
222 PeiPcdDb
= GetPcdDatabase ();
224 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
226 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
227 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
228 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
230 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
231 if (PeiPcdDb
->Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
236 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
238 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
239 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
242 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
243 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
245 case PCD_TYPE_STRING
:
246 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[i
]);
247 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
251 return (UINT32
) (Value
- (UINT8
*) PeiPcdDb
);
267 InvokeCallbackOnSet (
269 CONST EFI_GUID
*Guid
, OPTIONAL
275 EFI_HOB_GUID_TYPE
*GuidHob
;
276 PCD_PPI_CALLBACK
*CallbackTable
;
280 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
281 // We have to decrement TokenNumber by 1 to make it usable
282 // as the array index.
287 // EBC compiler is very choosy. It may report warning about comparison
288 // between UINTN and 0 . So we add 1 in each size of the
290 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
293 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
294 ASSERT (GuidHob
!= NULL
);
296 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
298 CallbackTable
+= (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
300 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
301 if (CallbackTable
[Idx
] != NULL
) {
302 CallbackTable
[Idx
] (Guid
,
303 (Guid
== NULL
)? TokenNumber
: ExTokenNumber
,
316 IN UINTN TokenNumber
,
321 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
328 IN UINTN TokenNumber
,
334 UINT32 LocalTokenNumber
;
335 PEI_PCD_DATABASE
*PeiPcdDb
;
336 UINT16 StringTableIdx
;
341 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
342 return EFI_UNSUPPORTED
;
346 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
347 // We have to decrement TokenNumber by 1 to make it usable
348 // as the array index.
352 // EBC compiler is very choosy. It may report warning about comparison
353 // between UINTN and 0 . So we add 1 in each size of the
355 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
357 PeiPcdDb
= GetPcdDatabase ();
359 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
362 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
366 // We only invoke the callback function for Dynamic Type PCD Entry.
367 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
368 // type PCD entry in ExSetWorker.
370 if (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1) {
371 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
374 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
376 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
380 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
383 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
384 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
386 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
391 return EFI_INVALID_PARAMETER
;
394 case PCD_TYPE_STRING
:
395 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
396 StringTableIdx
= *((UINT16
*)InternalData
);
397 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
400 return EFI_INVALID_PARAMETER
;
406 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
407 CopyMem (InternalData
, Data
, *Size
);
410 return EFI_INVALID_PARAMETER
;
416 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
420 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
424 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
428 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
433 return EFI_NOT_FOUND
;
440 return EFI_NOT_FOUND
;
448 IN UINTN ExTokenNumber
,
449 IN CONST EFI_GUID
*Guid
,
454 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
461 IN UINTN ExTokenNumber
,
462 IN CONST EFI_GUID
*Guid
,
470 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
471 return EFI_UNSUPPORTED
;
474 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
476 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
478 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
487 IN CONST EFI_GUID
*Guid
,
488 IN UINTN ExTokenNumber
,
492 if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled
)) {
497 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
512 VARIABLE_HEAD
*VariableHead
;
517 UINT16 StringTableIdx
;
518 PEI_PCD_DATABASE
*PeiPcdDb
;
519 UINT32 LocalTokenNumber
;
523 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
524 // We have to decrement TokenNumber by 1 to make it usable
525 // as the array index.
529 // EBC compiler is very choosy. It may report warning about comparison
530 // between UINTN and 0 . So we add 1 in each size of the
532 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
534 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
536 PeiPcdDb
= GetPcdDatabase ();
538 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
540 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
542 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
546 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
549 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
550 StringTable
= PeiPcdDb
->Init
.StringTable
;
552 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
556 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
557 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
562 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
564 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
565 Name
= &StringTable
[VariableHead
->StringIndex
];
567 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
569 if (Status
== EFI_SUCCESS
) {
570 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
573 // Return the default value specified by Platform Integrator
575 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
580 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
582 case PCD_TYPE_STRING
:
583 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
584 return (VOID
*) (&StringTable
[StringTableIdx
]);
601 GetExPcdTokenNumber (
602 IN CONST EFI_GUID
*Guid
,
603 IN UINTN ExTokenNumber
607 DYNAMICEX_MAPPING
*ExMap
;
611 PEI_PCD_DATABASE
*PeiPcdDb
;
613 PeiPcdDb
= GetPcdDatabase();
615 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
616 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
618 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
620 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
621 // error in the BUILD system.
623 ASSERT (MatchGuid
!= NULL
);
625 MatchGuidIdx
= MatchGuid
- GuidTable
;
627 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
628 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
629 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
630 return ExMap
[i
].LocalTokenNumber
;
646 EFI_HOB_GUID_TYPE
*GuidHob
;
648 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
649 ASSERT (GuidHob
!= NULL
);
651 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
658 IN UINTN LocalTokenNumberTableIdx
,
659 IN PEI_PCD_DATABASE
*Database
663 UINTN LocalTokenNumber
;
665 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
667 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
669 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
671 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
679 IN UINTN LocalTokenNumberTableIdx
,
680 IN PEI_PCD_DATABASE
*Database
685 UINTN LocalTokenNumber
;
690 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
691 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
693 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
695 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
698 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
700 // We have only one entry for VPD enabled PCD entry:
702 // We consider current size is equal to MAX size.
706 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
708 // We have only two entry for Non-Sku enabled PCD entry:
715 // We have these entry for SKU enabled PCD entry
717 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
719 SkuIdTable
= GetSkuIdArray (i
, Database
);
720 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
735 IN UINTN LocalTokenNumberTableIdx
,
737 IN PEI_PCD_DATABASE
*Database
741 UINTN LocalTokenNumber
;
743 SIZE_INFO
*SizeTable
;
746 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
748 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
750 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
752 SizeTable
= Database
->Init
.SizeTable
;
754 *MaxSize
= SizeTable
[SizeTableIdx
];
756 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
759 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
761 // We have only one entry for VPD enabled PCD entry:
763 // We consider current size is equal to MAX size.
767 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
769 // We have only two entry for Non-Sku enabled PCD entry:
773 return SizeTable
[SizeTableIdx
+ 1];
776 // We have these entry for SKU enabled PCD entry
778 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
780 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
781 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
782 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
783 return SizeTable
[SizeTableIdx
+ 1 + i
];
786 return SizeTable
[SizeTableIdx
+ 1];
795 IN UINTN LocalTokenNumberTableIdx
,
796 IN OUT UINTN
*CurrentSize
,
797 IN PEI_PCD_DATABASE
*Database
801 UINTN LocalTokenNumber
;
803 SIZE_INFO
*SizeTable
;
807 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
809 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
811 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
813 SizeTable
= Database
->Init
.SizeTable
;
815 MaxSize
= SizeTable
[SizeTableIdx
];
817 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
820 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
822 // We shouldn't come here as we don't support SET for VPD
827 if ((*CurrentSize
> MaxSize
) ||
828 (*CurrentSize
== MAX_ADDRESS
)) {
829 *CurrentSize
= MaxSize
;
833 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
835 // We have only two entry for Non-Sku enabled PCD entry:
839 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
843 // We have these entry for SKU enabled PCD entry
845 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
847 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
848 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
849 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
850 SizeTable
[SizeTableIdx
+ 1 + i
] = (SIZE_INFO
) *CurrentSize
;
854 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;