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 ASSERT (TokenNumber
< PCD_TOTAL_TOKEN_NUMBER
);
56 Size
= DxePcdGetSize (TokenNumber
);
57 ASSERT (GetSize
== Size
|| GetSize
== 0);
60 IsPeiDb
= (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
) ? TRUE
: FALSE
;
62 LocalTokenNumberTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.LocalTokenNumberTable
:
63 mPcdDatabase
->DxeDb
.Init
.LocalTokenNumberTable
;
65 SizeTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.SizeTable
:
66 mPcdDatabase
->DxeDb
.Init
.SizeTable
;
68 TokenNumber
= IsPeiDb
? TokenNumber
:
69 TokenNumber
- PEI_LOCAL_TOKEN_NUMBER
;
71 LocalTokenNumber
= LocalTokenNumberTable
[TokenNumber
];
73 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
74 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, Size
, IsPeiDb
);
77 PcdDb
= IsPeiDb
? ((UINT8
*) &mPcdDatabase
->PeiDb
) : ((UINT8
*) &mPcdDatabase
->DxeDb
);
78 StringTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.StringTable
:
79 mPcdDatabase
->DxeDb
.Init
.StringTable
;
81 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
83 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
85 VpdHead
= (VPD_HEAD
*) ((UINT8
*) PcdDb
+ Offset
);
86 return (VOID
*) (UINTN
) (FixedPcdGet32(PcdVpdBaseAddress
) + VpdHead
->Offset
);
89 GuidTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.GuidTable
:
90 mPcdDatabase
->DxeDb
.Init
.GuidTable
;
92 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
94 Guid
= &(GuidTable
[VariableHead
->GuidTableIndex
]);
95 Name
= &(StringTable
[VariableHead
->StringIndex
]);
97 Status
= GetHiiVariable (Guid
, Name
, &Data
, &DataSize
);
98 if (Status
== EFI_SUCCESS
) {
99 ASSERT (DataSize
>= (UINTN
) (VariableHead
->Offset
+ Size
));
100 return (UINT8
*) Data
+ VariableHead
->Offset
;
103 // BugBug: Need to support default value. The current implementation
104 // will return a memory buffer with ALL ZERO.
106 return AllocateZeroPool (Size
);
109 case PCD_TYPE_STRING
:
110 StringTableIdx
= (UINT16
) *((UINT8
*) PcdDb
+ Offset
);
111 return (VOID
*) &StringTable
[StringTableIdx
];
114 return (VOID
*) ((UINT8
*) PcdDb
+ Offset
);
132 DxeRegisterCallBackWorker (
133 IN UINTN TokenNumber
,
134 IN CONST GUID
*Guid
, OPTIONAL
135 IN PCD_PROTOCOL_CALLBACK CallBackFunction
138 CALLBACK_FN_ENTRY
*FnTableEntry
;
139 LIST_ENTRY
*ListHead
;
140 LIST_ENTRY
*ListNode
;
143 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
146 ListHead
= &mCallbackFnTable
[TokenNumber
];
147 ListNode
= GetFirstNode (ListHead
);
149 while (ListNode
!= ListHead
) {
150 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
152 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
154 // We only allow a Callback function to be register once
155 // for a TokenNumber. So just return EFI_SUCCESS
159 ListNode
= GetNextNode (ListHead
, ListNode
);
162 FnTableEntry
= AllocatePool (sizeof(CALLBACK_FN_ENTRY
));
163 ASSERT (FnTableEntry
!= NULL
);
165 FnTableEntry
->CallbackFn
= CallBackFunction
;
166 InsertTailList (ListHead
, &FnTableEntry
->Node
);
175 DxeUnRegisterCallBackWorker (
176 IN UINTN TokenNumber
,
177 IN CONST GUID
*Guid
, OPTIONAL
178 IN PCD_PROTOCOL_CALLBACK CallBackFunction
181 CALLBACK_FN_ENTRY
*FnTableEntry
;
182 LIST_ENTRY
*ListHead
;
183 LIST_ENTRY
*ListNode
;
186 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) TokenNumber
);
189 ListHead
= &mCallbackFnTable
[TokenNumber
];
190 ListNode
= GetFirstNode (ListHead
);
192 while (ListNode
!= ListHead
) {
193 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
195 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
197 // We only allow a Callback function to be register once
198 // for a TokenNumber. So we can safely remove the Node from
199 // the Link List and return EFI_SUCCESS.
201 RemoveEntryList (ListNode
);
202 FreePool (FnTableEntry
);
206 ListNode
= GetNextNode (ListHead
, ListNode
);
209 return EFI_INVALID_PARAMETER
;
215 ExGetNextTokeNumber (
216 IN CONST EFI_GUID
*Guid
,
217 IN UINTN TokenNumber
,
218 IN EFI_GUID
*GuidTable
,
219 IN UINTN SizeOfGuidTable
,
220 IN DYNAMICEX_MAPPING
*ExMapTable
,
221 IN UINTN SizeOfExMapTable
229 MatchGuid
= ScanGuid (GuidTable
, SizeOfGuidTable
, Guid
);
230 if (MatchGuid
== NULL
) {
231 return PCD_INVALID_TOKEN_NUMBER
;
235 GuidTableIdx
= MatchGuid
- GuidTable
;
236 for (Idx
= 0; Idx
< SizeOfExMapTable
; Idx
++) {
237 if (ExMapTable
[Idx
].ExGuidIndex
== GuidTableIdx
) {
244 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
245 return ExMapTable
[Idx
].ExTokenNumber
;
248 for ( ; Idx
< SizeOfExMapTable
; Idx
++) {
249 if (ExMapTable
[Idx
].ExTokenNumber
== TokenNumber
) {
251 if (Idx
== SizeOfExMapTable
) {
253 // Exceed the length of ExMap Table
255 return PCD_INVALID_TOKEN_NUMBER
;
256 } else if (ExMapTable
[Idx
].ExGuidIndex
== GuidTableIdx
) {
258 // Found the next match
260 return ExMapTable
[Idx
].ExTokenNumber
;
263 // Guid has been changed. It is the next Token Space Guid.
264 // We should flag no more TokenNumber.
266 return PCD_INVALID_TOKEN_NUMBER
;
272 return PCD_INVALID_TOKEN_NUMBER
;
279 BuildPcdDxeDataBase (
283 PEI_PCD_DATABASE
*PeiDatabase
;
284 EFI_HOB_GUID_TYPE
*GuidHob
;
287 mPcdDatabase
= AllocateZeroPool (sizeof(PCD_DATABASE
));
288 ASSERT (mPcdDatabase
!= NULL
);
290 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
292 if (GuidHob
!= NULL
) {
295 // We will copy over the PEI phase's PCD Database.
297 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
298 // should not be included at all. So the GuidHob could
299 // be NULL. If it is NULL, we just copy over the DXE Default
300 // Value to PCD Database.
303 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
305 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
307 CopyMem (&mPcdDatabase
->PeiDb
, PeiDatabase
, sizeof (PEI_PCD_DATABASE
));
311 // Copy PCD Entries with default value to PCD DATABASE
313 CopyMem (&mPcdDatabase
->DxeDb
.Init
, &gDXEPcdDbInit
, sizeof(DXE_PCD_DATABASE_INIT
));
317 // Initialized the Callback Function Table
320 if (PCD_TOTAL_TOKEN_NUMBER
!= 0) {
321 mCallbackFnTable
= AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER
* sizeof (LIST_ENTRY
));
324 for (Idx
= 0; Idx
< PCD_TOTAL_TOKEN_NUMBER
; Idx
++) {
325 InitializeListHead (&mCallbackFnTable
[Idx
]);
335 IN EFI_GUID
*VariableGuid
,
336 IN UINT16
*VariableName
,
337 OUT VOID
** VariableData
,
338 OUT UINTN
*VariableSize
345 Status
= EfiGetVariable (
346 (UINT16
*)VariableName
,
352 if (Status
== EFI_BUFFER_TOO_SMALL
) {
354 Buffer
= AllocatePool (Size
);
356 ASSERT (Buffer
!= NULL
);
358 Status
= EfiGetVariable (
366 ASSERT (Status
== EFI_SUCCESS
);
375 GetSkuEnabledTokenNumber (
376 UINT32 LocalTokenNumber
,
385 SKU_ID
*PhaseSkuIdTable
;
388 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
390 PcdDb
= IsPeiDb
? (UINT8
*) &mPcdDatabase
->PeiDb
: (UINT8
*) &mPcdDatabase
->DxeDb
;
392 SkuHead
= (SKU_HEAD
*) (PcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
393 Value
= (UINT8
*) (PcdDb
+ SkuHead
->SkuDataStartOffset
);
395 PhaseSkuIdTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.SkuIdTable
:
396 mPcdDatabase
->DxeDb
.Init
.SkuIdTable
;
398 SkuIdTable
= &PhaseSkuIdTable
[SkuHead
->SkuIdTableOffset
];
400 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
401 if (mPcdDatabase
->PeiDb
.Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
405 ASSERT (i
< SkuIdTable
[0]);
407 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
409 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
410 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_VPD
);
413 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
414 return (UINT32
) ((Value
- PcdDb
) | PCD_TYPE_HII
);
418 return (UINT32
) (Value
- PcdDb
);
435 InvokeCallbackOnSet (
436 UINT32 ExTokenNumber
,
437 CONST EFI_GUID
*Guid
, OPTIONAL
443 CALLBACK_FN_ENTRY
*FnTableEntry
;
444 LIST_ENTRY
*ListHead
;
445 LIST_ENTRY
*ListNode
;
447 ListHead
= &mCallbackFnTable
[TokenNumber
];
448 ListNode
= GetFirstNode (ListHead
);
450 while (ListNode
!= ListHead
) {
451 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
453 FnTableEntry
->CallbackFn(Guid
,
454 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
458 ListNode
= GetNextNode (ListHead
, ListNode
);
475 UINT32
*LocalTokenNumberTable
;
477 UINT32 LocalTokenNumber
;
482 UINTN VariableOffset
;
484 VARIABLE_HEAD
*VariableHead
;
489 ASSERT (TokenNumber
< PCD_TOTAL_TOKEN_NUMBER
);
492 ASSERT (Size
<= DxePcdGetSize (TokenNumber
));
494 ASSERT (Size
== DxePcdGetSize (TokenNumber
));
497 IsPeiDb
= (TokenNumber
< PEI_LOCAL_TOKEN_NUMBER
) ? TRUE
: FALSE
;
499 LocalTokenNumberTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.LocalTokenNumberTable
:
500 mPcdDatabase
->DxeDb
.Init
.LocalTokenNumberTable
;
502 if ((TokenNumber
< PEI_NEX_TOKEN_NUMBER
) ||
503 (TokenNumber
>= PEI_LOCAL_TOKEN_NUMBER
|| TokenNumber
< (PEI_LOCAL_TOKEN_NUMBER
+ DXE_NEX_TOKEN_NUMBER
))) {
504 InvokeCallbackOnSet (0, NULL
, TokenNumber
, Data
, Size
);
507 TokenNumber
= IsPeiDb
? TokenNumber
508 : TokenNumber
- PEI_LOCAL_TOKEN_NUMBER
;
510 LocalTokenNumber
= LocalTokenNumberTable
[TokenNumber
];
512 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
513 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, Size
, IsPeiDb
);
516 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
518 PcdDb
= IsPeiDb
? ((UINT8
*) &mPcdDatabase
->PeiDb
) : ((UINT8
*) &mPcdDatabase
->DxeDb
);
520 StringTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.StringTable
:
521 mPcdDatabase
->DxeDb
.Init
.StringTable
;
523 InternalData
= PcdDb
+ Offset
;
525 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
528 return EFI_INVALID_PARAMETER
;
530 case PCD_TYPE_STRING
:
531 CopyMem (&StringTable
[*((UINT16
*)InternalData
)], Data
, Size
);
536 // Bug Bug: Please implement this
538 GuidTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.GuidTable
:
539 mPcdDatabase
->DxeDb
.Init
.GuidTable
;
541 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
543 Guid
= &(GuidTable
[VariableHead
->GuidTableIndex
]);
544 Name
= &(StringTable
[VariableHead
->StringIndex
]);
545 VariableOffset
= VariableHead
->Offset
;
547 return SetHiiVariable (Guid
, Name
, Data
, Size
, VariableOffset
);
551 CopyMem (InternalData
, Data
, Size
);
557 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
561 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
565 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
569 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
574 return EFI_NOT_FOUND
;
583 return EFI_NOT_FOUND
;
592 IN CONST EFI_GUID
*Guid
,
593 IN UINTN ExTokenNumber
,
597 return GetWorker(GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
), GetSize
);
606 IN UINTN ExTokenNumber
,
607 IN CONST EFI_GUID
*Guid
,
615 TokenNumber
= GetExPcdTokenNumber (Guid
, (UINT32
) ExTokenNumber
);
617 InvokeCallbackOnSet ((UINT32
) ExTokenNumber
, Guid
, TokenNumber
, Data
, SetSize
);
619 SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
630 IN EFI_GUID
*VariableGuid
,
631 IN UINT16
*VariableName
,
644 Status
= EfiGetVariable (
645 (UINT16
*)VariableName
,
652 if (Status
== EFI_BUFFER_TOO_SMALL
) {
654 Buffer
= AllocatePool (Size
);
656 ASSERT (Buffer
!= NULL
);
658 Status
= EfiGetVariable (
666 ASSERT_EFI_ERROR (Status
);
668 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
672 Attribute
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
673 Size
= DataSize
+ Offset
;
674 Buffer
= AllocateZeroPool (Size
);
675 ASSERT (Buffer
!= NULL
);
676 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
680 return EfiSetVariable (
695 GetExPcdTokenNumber (
696 IN CONST EFI_GUID
*Guid
,
697 IN UINT32 ExTokenNumber
701 DYNAMICEX_MAPPING
*ExMap
;
706 ExMap
= mPcdDatabase
->PeiDb
.Init
.ExMapTable
;
707 GuidTable
= mPcdDatabase
->PeiDb
.Init
.GuidTable
;
709 MatchGuid
= ScanGuid (GuidTable
, sizeof(mPcdDatabase
->PeiDb
.Init
.GuidTable
), Guid
);
710 ASSERT (MatchGuid
!= NULL
);
712 MatchGuidIdx
= MatchGuid
- GuidTable
;
714 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
715 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
716 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
717 return ExMap
[i
].LocalTokenNumber
;
722 ExMap
= mPcdDatabase
->DxeDb
.Init
.ExMapTable
;
723 GuidTable
= mPcdDatabase
->DxeDb
.Init
.GuidTable
;
725 MatchGuid
= ScanGuid (GuidTable
, sizeof(mPcdDatabase
->DxeDb
.Init
.GuidTable
), Guid
);
726 ASSERT (MatchGuid
!= NULL
);
728 MatchGuidIdx
= MatchGuid
- GuidTable
;
730 for (i
= 0; i
< DXE_EXMAPPING_TABLE_SIZE
; i
++) {
731 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
732 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
733 return ExMap
[i
].LocalTokenNumber
+ PEI_LOCAL_TOKEN_NUMBER
;