2 Private functions used by PCD DXE driver.s
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
21 // Build Tool will generate DXE_PCD_DB_INIT_VALUE in Autogen.h
22 // Compression Algorithm will take care of the size optimization.
25 PCD_DATABASE
* mPcdDatabase
;
27 LIST_ENTRY
*mCallbackFnTable
;
35 UINT32
*LocalTokenNumberTable
;
44 VARIABLE_HEAD
*VariableHead
;
50 UINT16 StringTableIdx
;
51 UINT32 LocalTokenNumber
;
54 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
55 // We have to decrement TokenNumber by 1 to make it usable
56 // as the array index.
60 ASSERT (TokenNumber
< PCD_TOTAL_TOKEN_NUMBER
);
62 Size
= DxePcdGetSize (TokenNumber
+ 1);
63 ASSERT (GetSize
== Size
|| GetSize
== 0);
66 IsPeiDb
= (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
) ? TRUE
: FALSE
;
68 LocalTokenNumberTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.LocalTokenNumberTable
:
69 mPcdDatabase
->DxeDb
.Init
.LocalTokenNumberTable
;
71 SizeTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.SizeTable
:
72 mPcdDatabase
->DxeDb
.Init
.SizeTable
;
74 TokenNumber
= IsPeiDb
? TokenNumber
:
75 TokenNumber
- PEI_LOCAL_TOKEN_NUMBER
;
77 LocalTokenNumber
= LocalTokenNumberTable
[TokenNumber
];
79 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
80 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, Size
, IsPeiDb
);
83 PcdDb
= IsPeiDb
? ((UINT8
*) &mPcdDatabase
->PeiDb
) : ((UINT8
*) &mPcdDatabase
->DxeDb
);
84 StringTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.StringTable
:
85 mPcdDatabase
->DxeDb
.Init
.StringTable
;
87 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
89 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
91 VpdHead
= (VPD_HEAD
*) ((UINT8
*) PcdDb
+ Offset
);
92 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
95 GuidTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.GuidTable
:
96 mPcdDatabase
->DxeDb
.Init
.GuidTable
;
98 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
100 Guid
= &(GuidTable
[VariableHead
->GuidTableIndex
]);
101 Name
= &(StringTable
[VariableHead
->StringIndex
]);
103 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
104 if (Status
== EFI_SUCCESS
) {
105 return (UINT8
*) Data
+ VariableHead
->Offset
;
108 // Return the default value specified by Platform Integrator
110 return (VOID
*) ((UINT8
*) PcdDb
+ VariableHead
->DefaultValueOffset
);
113 case PCD_TYPE_STRING
:
114 StringTableIdx
= (UINT16
) *((UINT8
*) PcdDb
+ Offset
);
115 return (VOID
*) &StringTable
[StringTableIdx
];
118 return (VOID
*) ((UINT8
*) PcdDb
+ Offset
);
136 DxeRegisterCallBackWorker (
137 IN UINTN TokenNumber
,
138 IN CONST GUID
*Guid
, OPTIONAL
139 IN PCD_PROTOCOL_CALLBACK CallBackFunction
142 CALLBACK_FN_ENTRY
*FnTableEntry
;
143 LIST_ENTRY
*ListHead
;
144 LIST_ENTRY
*ListNode
;
147 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
151 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
152 // We have to decrement TokenNumber by 1 to make it usable
153 // as the array index.
157 ListHead
= &mCallbackFnTable
[TokenNumber
];
158 ListNode
= GetFirstNode (ListHead
);
160 while (ListNode
!= ListHead
) {
161 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
163 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
165 // We only allow a Callback function to be register once
166 // for a TokenNumber. So just return EFI_SUCCESS
170 ListNode
= GetNextNode (ListHead
, ListNode
);
173 FnTableEntry
= AllocatePool (sizeof(CALLBACK_FN_ENTRY
));
174 ASSERT (FnTableEntry
!= NULL
);
176 FnTableEntry
->CallbackFn
= CallBackFunction
;
177 InsertTailList (ListHead
, &FnTableEntry
->Node
);
186 DxeUnRegisterCallBackWorker (
187 IN UINTN TokenNumber
,
188 IN CONST GUID
*Guid
, OPTIONAL
189 IN PCD_PROTOCOL_CALLBACK CallBackFunction
192 CALLBACK_FN_ENTRY
*FnTableEntry
;
193 LIST_ENTRY
*ListHead
;
194 LIST_ENTRY
*ListNode
;
197 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
201 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
202 // We have to decrement TokenNumber by 1 to make it usable
203 // as the array index.
207 ListHead
= &mCallbackFnTable
[TokenNumber
];
208 ListNode
= GetFirstNode (ListHead
);
210 while (ListNode
!= ListHead
) {
211 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
213 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
215 // We only allow a Callback function to be register once
216 // for a TokenNumber. So we can safely remove the Node from
217 // the Link List and return EFI_SUCCESS.
219 RemoveEntryList (ListNode
);
220 FreePool (FnTableEntry
);
224 ListNode
= GetNextNode (ListHead
, ListNode
);
227 return EFI_INVALID_PARAMETER
;
233 ExGetNextTokeNumber (
234 IN CONST EFI_GUID
*Guid
,
235 IN UINTN TokenNumber
,
236 IN EFI_GUID
*GuidTable
,
237 IN UINTN SizeOfGuidTable
,
238 IN DYNAMICEX_MAPPING
*ExMapTable
,
239 IN UINTN SizeOfExMapTable
247 MatchGuid
= ScanGuid (GuidTable
, SizeOfGuidTable
, Guid
);
248 if (MatchGuid
== NULL
) {
249 return PCD_INVALID_TOKEN_NUMBER
;
253 GuidTableIdx
= MatchGuid
- GuidTable
;
254 for (Idx
= 0; Idx
< SizeOfExMapTable
; Idx
++) {
255 if (ExMapTable
[Idx
].ExGuidIndex
== GuidTableIdx
) {
262 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
263 return ExMapTable
[Idx
].ExTokenNumber
;
266 for ( ; Idx
< SizeOfExMapTable
; Idx
++) {
267 if (ExMapTable
[Idx
].ExTokenNumber
== TokenNumber
) {
269 if (Idx
== SizeOfExMapTable
) {
271 // Exceed the length of ExMap Table
273 return PCD_INVALID_TOKEN_NUMBER
;
274 } else if (ExMapTable
[Idx
].ExGuidIndex
== GuidTableIdx
) {
276 // Found the next match
278 return ExMapTable
[Idx
].ExTokenNumber
;
281 // Guid has been changed. It is the next Token Space Guid.
282 // We should flag no more TokenNumber.
284 return PCD_INVALID_TOKEN_NUMBER
;
290 return PCD_INVALID_TOKEN_NUMBER
;
297 BuildPcdDxeDataBase (
301 PEI_PCD_DATABASE
*PeiDatabase
;
302 EFI_HOB_GUID_TYPE
*GuidHob
;
305 mPcdDatabase
= AllocateZeroPool (sizeof(PCD_DATABASE
));
306 ASSERT (mPcdDatabase
!= NULL
);
308 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
310 if (GuidHob
!= NULL
) {
313 // We will copy over the PEI phase's PCD Database.
315 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
316 // should not be included at all. So the GuidHob could
317 // be NULL. If it is NULL, we just copy over the DXE Default
318 // Value to PCD Database.
321 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
323 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
325 CopyMem (&mPcdDatabase
->PeiDb
, PeiDatabase
, sizeof (PEI_PCD_DATABASE
));
329 // Copy PCD Entries with default value to PCD DATABASE
331 CopyMem (&mPcdDatabase
->DxeDb
.Init
, &gDXEPcdDbInit
, sizeof(DXE_PCD_DATABASE_INIT
));
335 // Initialized the Callback Function Table
338 if (PCD_TOTAL_TOKEN_NUMBER
!= 0) {
339 mCallbackFnTable
= AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER
* sizeof (LIST_ENTRY
));
342 for (Idx
= 0; Idx
< PCD_TOTAL_TOKEN_NUMBER
; Idx
++) {
343 InitializeListHead (&mCallbackFnTable
[Idx
]);
353 IN EFI_GUID
*VariableGuid
,
354 IN UINT16
*VariableName
,
355 OUT VOID
** VariableData
,
356 OUT UINTN
*VariableSize
366 Status
= EfiGetVariable (
367 (UINT16
*)VariableName
,
374 if (Status
== EFI_BUFFER_TOO_SMALL
) {
376 Buffer
= AllocatePool (Size
);
378 ASSERT (Buffer
!= NULL
);
380 Status
= EfiGetVariable (
388 ASSERT (Status
== EFI_SUCCESS
);
391 *VariableData
= Buffer
;
392 *VariableSize
= Size
;
400 GetSkuEnabledTokenNumber (
401 UINT32 LocalTokenNumber
,
410 SKU_ID
*PhaseSkuIdTable
;
413 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
415 PcdDb
= IsPeiDb
? (UINT8
*) &mPcdDatabase
->PeiDb
: (UINT8
*) &mPcdDatabase
->DxeDb
;
417 SkuHead
= (SKU_HEAD
*) (PcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
418 Value
= (UINT8
*) (PcdDb
+ SkuHead
->SkuDataStartOffset
);
420 PhaseSkuIdTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.SkuIdTable
:
421 mPcdDatabase
->DxeDb
.Init
.SkuIdTable
;
423 SkuIdTable
= &PhaseSkuIdTable
[SkuHead
->SkuIdTableOffset
];
425 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
426 if (mPcdDatabase
->PeiDb
.Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
430 ASSERT (i
< SkuIdTable
[0]);
432 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
434 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
435 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_VPD
);
438 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
439 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_HII
);
443 return (UINT32
) (Value
- PcdDb
);
460 InvokeCallbackOnSet (
461 UINT32 ExTokenNumber
,
462 CONST EFI_GUID
*Guid
, OPTIONAL
468 CALLBACK_FN_ENTRY
*FnTableEntry
;
469 LIST_ENTRY
*ListHead
;
470 LIST_ENTRY
*ListNode
;
473 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
474 // We have to decrement TokenNumber by 1 to make it usable
475 // as the array index.
479 ListHead
= &mCallbackFnTable
[TokenNumber
];
480 ListNode
= GetFirstNode (ListHead
);
482 while (ListNode
!= ListHead
) {
483 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
485 FnTableEntry
->CallbackFn(Guid
,
486 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
490 ListNode
= GetNextNode (ListHead
, ListNode
);
507 UINT32
*LocalTokenNumberTable
;
509 UINT32 LocalTokenNumber
;
514 UINTN VariableOffset
;
516 VARIABLE_HEAD
*VariableHead
;
521 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
522 // We have to decrement TokenNumber by 1 to make it usable
523 // as the array index.
527 ASSERT (TokenNumber
< PCD_TOTAL_TOKEN_NUMBER
);
530 ASSERT (Size
<= DxePcdGetSize (TokenNumber
+ 1));
532 ASSERT (Size
== DxePcdGetSize (TokenNumber
+ 1));
535 IsPeiDb
= (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
) ? TRUE
: FALSE
;
537 LocalTokenNumberTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.LocalTokenNumberTable
:
538 mPcdDatabase
->DxeDb
.Init
.LocalTokenNumberTable
;
540 if ((TokenNumber
< PEI_NEX_TOKEN_NUMBER
) ||
541 (TokenNumber
>= PEI_LOCAL_TOKEN_NUMBER
|| TokenNumber
< (PEI_LOCAL_TOKEN_NUMBER
+ DXE_NEX_TOKEN_NUMBER
))) {
542 InvokeCallbackOnSet (0, NULL
, TokenNumber
+ 1, Data
, Size
);
545 TokenNumber
= IsPeiDb
? TokenNumber
546 : TokenNumber
- PEI_LOCAL_TOKEN_NUMBER
;
548 LocalTokenNumber
= LocalTokenNumberTable
[TokenNumber
];
550 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
551 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, Size
, IsPeiDb
);
554 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
556 PcdDb
= IsPeiDb
? ((UINT8
*) &mPcdDatabase
->PeiDb
) : ((UINT8
*) &mPcdDatabase
->DxeDb
);
558 StringTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.StringTable
:
559 mPcdDatabase
->DxeDb
.Init
.StringTable
;
561 InternalData
= PcdDb
+ Offset
;
563 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
566 return EFI_INVALID_PARAMETER
;
568 case PCD_TYPE_STRING
:
569 CopyMem (&StringTable
[*((UINT16
*)InternalData
)], Data
, Size
);
574 // Bug Bug: Please implement this
576 GuidTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.GuidTable
:
577 mPcdDatabase
->DxeDb
.Init
.GuidTable
;
579 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
581 Guid
= &(GuidTable
[VariableHead
->GuidTableIndex
]);
582 Name
= &(StringTable
[VariableHead
->StringIndex
]);
583 VariableOffset
= VariableHead
->Offset
;
585 return SetHiiVariable (Guid
, Name
, Data
, Size
, VariableOffset
);
589 CopyMem (InternalData
, Data
, Size
);
595 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
599 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
603 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
607 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
612 return EFI_NOT_FOUND
;
621 return EFI_NOT_FOUND
;
630 IN CONST EFI_GUID
*Guid
,
631 IN UINTN ExTokenNumber
,
635 return GetWorker(GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
), GetSize
);
644 IN UINTN ExTokenNumber
,
645 IN CONST EFI_GUID
*Guid
,
653 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
);
655 InvokeCallbackOnSet ((UINT32
) ExTokenNumber
, Guid
, TokenNumber
, Data
, SetSize
);
657 SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
668 IN EFI_GUID
*VariableGuid
,
669 IN UINT16
*VariableName
,
682 Status
= EfiGetVariable (
683 (UINT16
*)VariableName
,
690 if (Status
== EFI_BUFFER_TOO_SMALL
) {
692 Buffer
= AllocatePool (Size
);
694 ASSERT (Buffer
!= NULL
);
696 Status
= EfiGetVariable (
704 ASSERT_EFI_ERROR (Status
);
706 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
710 Attribute
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
711 Size
= DataSize
+ Offset
;
712 Buffer
= AllocateZeroPool (Size
);
713 ASSERT (Buffer
!= NULL
);
714 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
718 return EfiSetVariable (
733 GetExPcdTokenNumber (
734 IN CONST EFI_GUID
*Guid
,
735 IN UINT32 ExTokenNumber
739 DYNAMICEX_MAPPING
*ExMap
;
744 if (!PEI_DATABASE_EMPTY
) {
745 ExMap
= mPcdDatabase
->PeiDb
.Init
.ExMapTable
;
746 GuidTable
= mPcdDatabase
->PeiDb
.Init
.GuidTable
;
748 MatchGuid
= ScanGuid (GuidTable
, sizeof(mPcdDatabase
->PeiDb
.Init
.GuidTable
), Guid
);
750 if (MatchGuid
!= NULL
) {
752 MatchGuidIdx
= MatchGuid
- GuidTable
;
754 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
755 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
756 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
757 return ExMap
[i
].LocalTokenNumber
;
764 ExMap
= mPcdDatabase
->DxeDb
.Init
.ExMapTable
;
765 GuidTable
= mPcdDatabase
->DxeDb
.Init
.GuidTable
;
767 MatchGuid
= ScanGuid (GuidTable
, sizeof(mPcdDatabase
->DxeDb
.Init
.GuidTable
), Guid
);
769 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
770 // error in the BUILD system.
772 ASSERT (MatchGuid
!= NULL
);
774 MatchGuidIdx
= MatchGuid
- GuidTable
;
776 for (i
= 0; i
< DXE_EXMAPPING_TABLE_SIZE
; i
++) {
777 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
778 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
779 return ExMap
[i
].LocalTokenNumber
;