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
18 // Include common header file for this module.
20 #include "CommonHeader.h"
25 The function registers the CallBackOnSet fucntion
26 according to TokenNumber and EFI_GUID space.
28 @param TokenNumber The token number.
29 @param Guid The GUID space.
30 @param CallBackFunction The Callback function to be registered.
31 @param Register To register or unregister the callback function.
33 @retval EFI_SUCCESS If the Callback function is registered.
34 @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
35 @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
36 slot left in the CallbackFnTable.
39 PeiRegisterCallBackWorker (
40 IN UINTN ExTokenNumber
,
41 IN CONST EFI_GUID
*Guid
, OPTIONAL
42 IN PCD_PPI_CALLBACK CallBackFunction
,
46 EFI_HOB_GUID_TYPE
*GuidHob
;
47 PCD_PPI_CALLBACK
*CallbackTable
;
48 PCD_PPI_CALLBACK Compare
;
49 PCD_PPI_CALLBACK Assign
;
50 UINT32 LocalTokenNumber
;
55 TokenNumber
= ExTokenNumber
;
58 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
59 // We have to decrement TokenNumber by 1 to make it usable
60 // as the array index.
63 ASSERT (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1);
65 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
68 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
69 // We have to decrement TokenNumber by 1 to make it usable
70 // as the array index.
73 // EBC compiler is very choosy. It may report warning about comparison
74 // between UINTN and 0 . So we add 1 in each size of the
76 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
80 LocalTokenNumber
= GetPcdDatabase()->Init
.LocalTokenNumberTable
[TokenNumber
];
83 // We don't support SET for HII and VPD type PCD entry in PEI phase.
84 // So we will assert if any register callback for such PCD entry.
86 ASSERT ((LocalTokenNumber
& PCD_TYPE_HII
) == 0);
87 ASSERT ((LocalTokenNumber
& PCD_TYPE_VPD
) == 0);
89 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
90 ASSERT (GuidHob
!= NULL
);
92 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
93 CallbackTable
= CallbackTable
+ (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
95 Compare
= Register
? NULL
: CallBackFunction
;
96 Assign
= Register
? CallBackFunction
: NULL
;
99 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
100 if (CallbackTable
[Idx
] == Compare
) {
101 CallbackTable
[Idx
] = Assign
;
106 return Register
? EFI_OUT_OF_RESOURCES
: EFI_NOT_FOUND
;
114 The function builds the PCD database.
125 PEI_PCD_DATABASE
*Database
;
126 VOID
*CallbackFnTable
;
127 UINTN SizeOfCallbackFnTable
;
129 Database
= BuildGuidHob (&gPcdDataBaseHobGuid
, sizeof (PEI_PCD_DATABASE
));
131 ZeroMem (Database
, sizeof (PEI_PCD_DATABASE
));
134 // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE
137 CopyMem (&Database
->Init
, &gPEIPcdDbInit
, sizeof (gPEIPcdDbInit
));
139 SizeOfCallbackFnTable
= PEI_LOCAL_TOKEN_NUMBER
* sizeof (PCD_PPI_CALLBACK
) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
);
141 CallbackFnTable
= BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid
, SizeOfCallbackFnTable
);
143 ZeroMem (CallbackFnTable
, SizeOfCallbackFnTable
);
151 The function is provided by PCD PEIM and PCD DXE driver to
152 do the work of reading a HII variable from variable service.
154 @param VariableGuid The Variable GUID.
155 @param VariableName The Variable Name.
156 @param VariableData The output data.
157 @param VariableSize The size of the variable.
159 @retval EFI_SUCCESS Operation successful.
160 @retval EFI_NOT_FOUND Variablel not found.
165 IN CONST EFI_GUID
*VariableGuid
,
166 IN UINT16
*VariableName
,
167 OUT VOID
**VariableData
,
168 OUT UINTN
*VariableSize
174 EFI_PEI_READ_ONLY_VARIABLE_PPI
*VariablePpi
;
176 Status
= PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid
, 0, NULL
, (VOID
**) &VariablePpi
);
177 ASSERT_EFI_ERROR (Status
);
180 Status
= VariablePpi
->PeiGetVariable (
181 GetPeiServicesTablePointer (),
183 (EFI_GUID
*) VariableGuid
,
188 if (Status
== EFI_BUFFER_TOO_SMALL
) {
191 Status
= PeiServicesAllocatePool (Size
, &Buffer
);
192 ASSERT_EFI_ERROR (Status
);
194 Status
= VariablePpi
->PeiGetVariable (
195 GetPeiServicesTablePointer (),
196 (UINT16
*) VariableName
,
197 (EFI_GUID
*) VariableGuid
,
202 ASSERT_EFI_ERROR (Status
);
204 *VariableSize
= Size
;
205 *VariableData
= Buffer
;
209 return EFI_NOT_FOUND
;
216 GetSkuEnabledTokenNumber (
217 UINT32 LocalTokenNumber
,
221 PEI_PCD_DATABASE
*PeiPcdDb
;
227 PeiPcdDb
= GetPcdDatabase ();
229 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
231 SkuHead
= (SKU_HEAD
*) ((UINT8
*)PeiPcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
232 Value
= (UINT8
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuDataStartOffset
));
233 SkuIdTable
= (SKU_ID
*) ((UINT8
*)PeiPcdDb
+ (SkuHead
->SkuIdTableOffset
));
235 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
236 if (PeiPcdDb
->Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
241 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
243 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
244 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_VPD
);
247 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
248 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_HII
);
250 case PCD_TYPE_STRING
:
251 Value
= (UINT8
*) &(((STRING_HEAD
*) Value
)[i
]);
252 return (UINT32
) ((Value
- (UINT8
*) PeiPcdDb
) | PCD_TYPE_STRING
);
256 return (UINT32
) (Value
- (UINT8
*) PeiPcdDb
);
272 InvokeCallbackOnSet (
274 CONST EFI_GUID
*Guid
, OPTIONAL
280 EFI_HOB_GUID_TYPE
*GuidHob
;
281 PCD_PPI_CALLBACK
*CallbackTable
;
285 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
286 // We have to decrement TokenNumber by 1 to make it usable
287 // as the array index.
292 // EBC compiler is very choosy. It may report warning about comparison
293 // between UINTN and 0 . So we add 1 in each size of the
295 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
298 GuidHob
= GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid
);
299 ASSERT (GuidHob
!= NULL
);
301 CallbackTable
= GET_GUID_HOB_DATA (GuidHob
);
303 CallbackTable
+= (TokenNumber
* FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
));
305 for (Idx
= 0; Idx
< FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry
); Idx
++) {
306 if (CallbackTable
[Idx
] != NULL
) {
307 CallbackTable
[Idx
] (Guid
,
308 (Guid
== NULL
)? TokenNumber
: ExTokenNumber
,
321 IN UINTN TokenNumber
,
326 return SetWorker (TokenNumber
, Data
, &Size
, FALSE
);
333 IN UINTN TokenNumber
,
339 UINT32 LocalTokenNumber
;
340 PEI_PCD_DATABASE
*PeiPcdDb
;
341 UINT16 StringTableIdx
;
346 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
347 return EFI_UNSUPPORTED
;
351 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
352 // We have to decrement TokenNumber by 1 to make it usable
353 // as the array index.
357 // EBC compiler is very choosy. It may report warning about comparison
358 // between UINTN and 0 . So we add 1 in each size of the
360 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
362 PeiPcdDb
= GetPcdDatabase ();
364 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
367 ASSERT (PeiPcdGetSize(TokenNumber
+ 1) == *Size
);
371 // We only invoke the callback function for Dynamic Type PCD Entry.
372 // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX
373 // type PCD entry in ExSetWorker.
375 if (TokenNumber
+ 1 < PEI_NEX_TOKEN_NUMBER
+ 1) {
376 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, *Size
);
379 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
381 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
385 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
388 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
389 InternalData
= (VOID
*) ((UINT8
*) PeiPcdDb
+ Offset
);
391 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
396 return EFI_INVALID_PARAMETER
;
399 case PCD_TYPE_STRING
:
400 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
401 StringTableIdx
= *((UINT16
*)InternalData
);
402 CopyMem (&PeiPcdDb
->Init
.StringTable
[StringTableIdx
], Data
, *Size
);
405 return EFI_INVALID_PARAMETER
;
411 if (SetPtrTypeSize (TokenNumber
, Size
, PeiPcdDb
)) {
412 CopyMem (InternalData
, Data
, *Size
);
415 return EFI_INVALID_PARAMETER
;
421 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
425 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
429 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
433 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
438 return EFI_NOT_FOUND
;
445 return EFI_NOT_FOUND
;
453 IN UINTN ExTokenNumber
,
454 IN CONST EFI_GUID
*Guid
,
459 return ExSetWorker (ExTokenNumber
, Guid
, Data
, &Size
, FALSE
);
466 IN UINTN ExTokenNumber
,
467 IN CONST EFI_GUID
*Guid
,
475 if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled
)) {
476 return EFI_UNSUPPORTED
;
479 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
481 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, *Size
);
483 return SetWorker (TokenNumber
, Data
, Size
, PtrType
);
492 IN CONST EFI_GUID
*Guid
,
493 IN UINTN ExTokenNumber
,
497 if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled
)) {
502 return GetWorker (GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
517 VARIABLE_HEAD
*VariableHead
;
522 UINT16 StringTableIdx
;
523 PEI_PCD_DATABASE
*PeiPcdDb
;
524 UINT32 LocalTokenNumber
;
528 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
529 // We have to decrement TokenNumber by 1 to make it usable
530 // as the array index.
534 // EBC compiler is very choosy. It may report warning about comparison
535 // between UINTN and 0 . So we add 1 in each size of the
537 ASSERT (TokenNumber
+ 1 < PEI_LOCAL_TOKEN_NUMBER
+ 1);
539 ASSERT ((GetSize
== PeiPcdGetSize(TokenNumber
+ 1)) || (GetSize
== 0));
541 PeiPcdDb
= GetPcdDatabase ();
543 LocalTokenNumber
= PeiPcdDb
->Init
.LocalTokenNumberTable
[TokenNumber
];
545 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
547 MaxSize
= GetPtrTypeSize (TokenNumber
, &MaxSize
, PeiPcdDb
);
551 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, MaxSize
);
554 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
555 StringTable
= PeiPcdDb
->Init
.StringTable
;
557 switch (LocalTokenNumber
& PCD_TYPE_ALL_SET
) {
561 VpdHead
= (VPD_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
562 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
567 VariableHead
= (VARIABLE_HEAD
*) ((UINT8
*)PeiPcdDb
+ Offset
);
569 Guid
= &(PeiPcdDb
->Init
.GuidTable
[VariableHead
->GuidTableIndex
]);
570 Name
= &StringTable
[VariableHead
->StringIndex
];
572 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
574 if (Status
== EFI_SUCCESS
) {
575 return (VOID
*) ((UINT8
*) Data
+ VariableHead
->Offset
);
578 // Return the default value specified by Platform Integrator
580 return (VOID
*) ((UINT8
*) PeiPcdDb
+ VariableHead
->DefaultValueOffset
);
585 return (VOID
*) ((UINT8
*)PeiPcdDb
+ Offset
);
587 case PCD_TYPE_STRING
:
588 StringTableIdx
= (UINT16
) *((UINT8
*) PeiPcdDb
+ Offset
);
589 return (VOID
*) (&StringTable
[StringTableIdx
]);
606 GetExPcdTokenNumber (
607 IN CONST EFI_GUID
*Guid
,
608 IN UINTN ExTokenNumber
612 DYNAMICEX_MAPPING
*ExMap
;
616 PEI_PCD_DATABASE
*PeiPcdDb
;
618 PeiPcdDb
= GetPcdDatabase();
620 ExMap
= PeiPcdDb
->Init
.ExMapTable
;
621 GuidTable
= PeiPcdDb
->Init
.GuidTable
;
623 MatchGuid
= ScanGuid (GuidTable
, sizeof(PeiPcdDb
->Init
.GuidTable
), Guid
);
625 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
626 // error in the BUILD system.
628 ASSERT (MatchGuid
!= NULL
);
630 MatchGuidIdx
= MatchGuid
- GuidTable
;
632 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
633 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
634 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
635 return ExMap
[i
].LocalTokenNumber
;
651 EFI_HOB_GUID_TYPE
*GuidHob
;
653 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
654 ASSERT (GuidHob
!= NULL
);
656 return (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
663 IN UINTN LocalTokenNumberTableIdx
,
664 IN PEI_PCD_DATABASE
*Database
668 UINTN LocalTokenNumber
;
670 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[LocalTokenNumberTableIdx
];
672 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) != 0);
674 SkuHead
= (SKU_HEAD
*) ((UINT8
*)Database
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
676 return (SKU_ID
*) ((UINT8
*)Database
+ SkuHead
->SkuIdTableOffset
);
684 IN UINTN LocalTokenNumberTableIdx
,
685 IN PEI_PCD_DATABASE
*Database
690 UINTN LocalTokenNumber
;
695 for (i
=0; i
<LocalTokenNumberTableIdx
; i
++) {
696 LocalTokenNumber
= Database
->Init
.LocalTokenNumberTable
[i
];
698 if ((LocalTokenNumber
& PCD_DATUM_TYPE_ALL_SET
) == PCD_DATUM_TYPE_POINTER
) {
700 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
703 if (LocalTokenNumber
& PCD_TYPE_VPD
) {
705 // We have only one entry for VPD enabled PCD entry:
707 // We consider current size is equal to MAX size.
711 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0) {
713 // We have only two entry for Non-Sku enabled PCD entry:
720 // We have these entry for SKU enabled PCD entry
722 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
724 SkuIdTable
= GetSkuIdArray (i
, Database
);
725 SizeTableIdx
+= (UINTN
)*SkuIdTable
+ 1;