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
< PEI_NEX_TOKEN_NUMBER
);
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 ASSERT (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
);
69 LocalTokenNumber
= GetPcdDatabase()->Init
.LocalTokenNumberTable
[TokenNumber
];
72 // We don't support SET for HII and VPD type PCD entry in PEI phase.
73 // So we will assert if any register callback for such PCD entry.
75 ASSERT ((LocalTokenNumber
& PCD_TYPE_HII
) == 0);
76 ASSERT ((LocalTokenNumber
& PCD_TYPE_VPD
) == 0);
78 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
79 ASSERT (GuidHob
!= NULL
);
81 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
82 CallbackTable
= CallbackTable
+ (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
84 Compare
= Register
? NULL
: CallBackFunction
;
85 Assign
= Register
? CallBackFunction
: NULL
;
88 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
89 if (CallbackTable
[Idx
] == Compare
) {
90 CallbackTable
[Idx
] = Assign
;
95 return Register
? EFI_OUT_OF_RESOURCES
: EFI_NOT_FOUND
;
103 The function builds the PCD database based on the
104 PCD_IMAGE on the flash.
106 @param[in] PcdImageOnFlash The PCD image on flash.
115 PEI_PCD_DATABASE
*Database
;
116 VOID
*CallbackFnTable
;
117 UINTN SizeOfCallbackFnTable
;
119 Database
= BuildGuidHob (&gPcdDataBaseHobGuid
, sizeof (PEI_PCD_DATABASE
));
121 ZeroMem (Database
, sizeof (PEI_PCD_DATABASE
));
124 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
127 CopyMem (&Database
->Init
, &gPEIPcdDbInit
, sizeof (gPEIPcdDbInit
));
129 SizeOfCallbackFnTable
= PEI_LOCAL_TOKEN_NUMBER
* sizeof (PCD_PPI_CALLBACK
) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
);
131 CallbackFnTable
= BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid
, SizeOfCallbackFnTable
);
133 ZeroMem (CallbackFnTable
, SizeOfCallbackFnTable
);
141 The function is provided by PCD PEIM and PCD DXE driver to
142 do the work of reading a HII variable from variable service.
144 @param[in] VariableGuid The Variable GUID.
145 @param[in] VariableName The Variable Name.
146 @param[out] VariableData The output data.
147 @param[out] VariableSize The size of the variable.
149 @retval EFI_SUCCESS Operation successful.
150 @retval EFI_SUCCESS Variablel not found.
154 IN CONST EFI_GUID
*VariableGuid
,
155 IN UINT16
*VariableName
,
156 OUT VOID
**VariableData
,
157 OUT UINTN
*VariableSize
163 EFI_PEI_READ_ONLY_VARIABLE_PPI
*VariablePpi
;
165 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
166 ASSERT_EFI_ERROR (Status
);
169 Status
= VariablePpi
->PeiGetVariable (
170 GetPeiServicesTablePointer (),
172 (EFI_GUID
*) VariableGuid
,
177 if (Status
== EFI_BUFFER_TOO_SMALL
) {
180 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
181 ASSERT_EFI_ERROR (Status
);
183 Status
= VariablePpi
->PeiGetVariable (
184 GetPeiServicesTablePointer (),
185 (UINT16
*) VariableName
,
186 (EFI_GUID
*) VariableGuid
,
191 ASSERT_EFI_ERROR (Status
);
193 *VariableSize
= Size
;
194 *VariableData
= Buffer
;
198 return EFI_NOT_FOUND
;
205 GetSkuEnabledTokenNumber (
206 UINT32 LocalTokenNumber
,
210 PEI_PCD_DATABASE
*PeiPcdDb
;
216 PeiPcdDb
= GetPcdDatabase ();
218 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
220 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
221 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
222 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
224 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
225 if (PeiPcdDb
->Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
230 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
232 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
233 return ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
236 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
237 return ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
239 case PCD_TYPE_STRING
:
240 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[i
]);
241 return ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
245 return (Value
- (UINT8
*) PeiPcdDb
);
261 InvokeCallbackOnSet (
262 UINT32 ExTokenNumber
,
263 CONST EFI_GUID
*Guid
, OPTIONAL
269 EFI_HOB_GUID_TYPE
*GuidHob
;
270 PCD_PPI_CALLBACK
*CallbackTable
;
274 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
275 // We have to decrement TokenNumber by 1 to make it usable
276 // as the array index.
281 ASSERT (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
);
283 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
284 ASSERT (GuidHob
!= NULL
);
286 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
288 CallbackTable
+= (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
290 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
291 if (CallbackTable
[Idx
] != NULL
) {
292 CallbackTable
[Idx
] (Guid
,
293 (Guid
== NULL
)? TokenNumber
: ExTokenNumber
,
306 IN UINTN TokenNumber
,
311 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
318 IN UINTN TokenNumber
,
324 UINT32 LocalTokenNumber
;
325 PEI_PCD_DATABASE
*PeiPcdDb
;
326 UINT16 StringTableIdx
;
332 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
333 // We have to decrement TokenNumber by 1 to make it usable
334 // as the array index.
338 ASSERT (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
);
340 PeiPcdDb
= GetPcdDatabase ();
342 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
345 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
349 // We only invoke the callback function for Dynamic Type PCD Entry.
350 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
351 // type PCD entry in ExSetWorker.
353 if (TokenNumber
< PEI_NEX_TOKEN_NUMBER
) {
354 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
357 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
359 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
363 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
366 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
367 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
369 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
374 return EFI_INVALID_PARAMETER
;
377 case PCD_TYPE_STRING
:
378 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
379 StringTableIdx
= *((UINT16
*)InternalData
);
380 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
383 return EFI_INVALID_PARAMETER
;
389 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
390 CopyMem (InternalData
, Data
, *Size
);
393 return EFI_INVALID_PARAMETER
;
399 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
403 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
407 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
411 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
416 return EFI_NOT_FOUND
;
423 return EFI_NOT_FOUND
;
431 IN UINTN ExTokenNumber
,
432 IN CONST EFI_GUID
*Guid
,
437 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
444 IN UINTN ExTokenNumber
,
445 IN CONST EFI_GUID
*Guid
,
453 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
455 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
457 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
466 IN CONST EFI_GUID
*Guid
,
467 IN UINTN ExTokenNumber
,
471 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
486 VARIABLE_HEAD
*VariableHead
;
491 UINT16 StringTableIdx
;
492 PEI_PCD_DATABASE
*PeiPcdDb
;
493 UINT32 LocalTokenNumber
;
497 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
498 // We have to decrement TokenNumber by 1 to make it usable
499 // as the array index.
503 ASSERT (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
);
505 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
507 PeiPcdDb
= GetPcdDatabase ();
509 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
511 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
513 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
517 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
520 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
521 StringTable
= PeiPcdDb
->Init
.StringTable
;
523 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
527 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
528 return (VOID
*) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
533 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
535 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
536 Name
= &StringTable
[VariableHead
->StringIndex
];
538 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
540 if (Status
== EFI_SUCCESS
) {
541 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
544 // Return the default value specified by Platform Integrator
546 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
551 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
553 case PCD_TYPE_STRING
:
554 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
555 return (VOID
*) (&StringTable
[StringTableIdx
]);
571 GetExPcdTokenNumber (
572 IN CONST EFI_GUID
*Guid
,
573 IN UINT32 ExTokenNumber
577 DYNAMICEX_MAPPING
*ExMap
;
581 PEI_PCD_DATABASE
*PeiPcdDb
;
583 PeiPcdDb
= GetPcdDatabase();
585 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
586 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
588 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
590 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
591 // error in the BUILD system.
593 ASSERT (MatchGuid
!= NULL
);
595 MatchGuidIdx
= MatchGuid
- GuidTable
;
597 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
598 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
599 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
600 return ExMap
[i
].LocalTokenNumber
;
616 EFI_HOB_GUID_TYPE
*GuidHob
;
618 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
619 ASSERT (GuidHob
!= NULL
);
621 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
627 IN UINTN LocalTokenNumberTableIdx
,
628 IN PEI_PCD_DATABASE
*Database
632 UINTN LocalTokenNumber
;
634 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
636 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
638 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
640 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
648 IN UINTN LocalTokenNumberTableIdx
,
649 IN PEI_PCD_DATABASE
*Database
654 UINTN LocalTokenNumber
;
659 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
660 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
662 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
664 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
667 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
669 // We have only one entry for VPD enabled PCD entry:
671 // We consider current size is equal to MAX size.
675 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
677 // We have only two entry for Non-Sku enabled PCD entry:
684 // We have these entry for SKU enabled PCD entry
686 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
688 SkuIdTable
= GetSkuIdArray (i
, Database
);
689 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;
704 IN UINTN LocalTokenNumberTableIdx
,
706 IN PEI_PCD_DATABASE
*Database
710 UINTN LocalTokenNumber
;
712 SIZE_INFO
*SizeTable
;
715 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
717 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
719 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
721 SizeTable
= Database
->Init
.SizeTable
;
723 *MaxSize
= SizeTable
[SizeTableIdx
];
725 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
728 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
730 // We have only one entry for VPD enabled PCD entry:
732 // We consider current size is equal to MAX size.
736 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
738 // We have only two entry for Non-Sku enabled PCD entry:
742 return SizeTable
[SizeTableIdx
+ 1];
745 // We have these entry for SKU enabled PCD entry
747 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
749 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
750 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
751 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
752 return SizeTable
[SizeTableIdx
+ 1 + i
];
755 return SizeTable
[SizeTableIdx
+ 1];
764 IN UINTN LocalTokenNumberTableIdx
,
765 IN OUT UINTN
*CurrentSize
,
766 IN PEI_PCD_DATABASE
*Database
770 UINTN LocalTokenNumber
;
772 SIZE_INFO
*SizeTable
;
776 SizeTableIdx
= GetSizeTableIndex (LocalTokenNumberTableIdx
, Database
);
778 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
780 ASSERT ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
);
782 SizeTable
= Database
->Init
.SizeTable
;
784 MaxSize
= SizeTable
[SizeTableIdx
];
786 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
789 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
791 // We shouldn't come here as we don't support SET for VPD
796 if ((*CurrentSize
> MaxSize
) ||
797 (*CurrentSize
== MAX_ADDRESS
)) {
798 *CurrentSize
= MaxSize
;
802 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
804 // We have only two entry for Non-Sku enabled PCD entry:
808 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;
812 // We have these entry for SKU enabled PCD entry
814 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
816 SkuIdTable
= GetSkuIdArray (LocalTokenNumberTableIdx
, Database
);
817 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
818 if (SkuIdTable
[1 + i
] == Database
->Init
.SystemSkuId
) {
819 SizeTable
[SizeTableIdx
+ 1 + i
] = (SIZE_INFO
) *CurrentSize
;
823 SizeTable
[SizeTableIdx
+ 1] = (SIZE_INFO
) *CurrentSize
;