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
[PCD_TOTAL_TOKEN_NUMBER
];
31 PCD_TOKEN_NUMBER TokenNumber
,
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
*) (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 ASSERT_EFI_ERROR (Status
);
99 ASSERT (DataSize
>= (UINTN
) (VariableHead
->Offset
+ Size
));
101 return (UINT8
*) Data
+ VariableHead
->Offset
;
103 case PCD_TYPE_STRING
:
104 StringTableIdx
= (UINT16
) *((UINT8
*) PcdDb
+ Offset
);
105 return (VOID
*) &StringTable
[StringTableIdx
];
108 return (VOID
*) ((UINT8
*) PcdDb
+ Offset
);
126 DxeRegisterCallBackWorker (
127 IN PCD_TOKEN_NUMBER TokenNumber
,
128 IN CONST GUID
*Guid
, OPTIONAL
129 IN PCD_PROTOCOL_CALLBACK CallBackFunction
132 CALLBACK_FN_ENTRY
*FnTableEntry
;
133 LIST_ENTRY
*ListHead
;
134 LIST_ENTRY
*ListNode
;
137 TokenNumber
= GetExPcdTokenNumber (Guid
, TokenNumber
);
140 ListHead
= &mCallbackFnTable
[TokenNumber
];
141 ListNode
= GetFirstNode (ListHead
);
143 while (ListNode
!= ListHead
) {
144 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
146 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
148 // We only allow a Callback function to be register once
149 // for a TokenNumber. So just return EFI_SUCCESS
153 ListNode
= GetNextNode (ListHead
, ListNode
);
156 FnTableEntry
= AllocatePool (sizeof(CALLBACK_FN_ENTRY
));
157 ASSERT (FnTableEntry
!= NULL
);
159 FnTableEntry
->CallbackFn
= CallBackFunction
;
160 InsertTailList (ListHead
, &FnTableEntry
->Node
);
169 DxeUnRegisterCallBackWorker (
170 IN PCD_TOKEN_NUMBER TokenNumber
,
171 IN CONST GUID
*Guid
, OPTIONAL
172 IN PCD_PROTOCOL_CALLBACK CallBackFunction
175 CALLBACK_FN_ENTRY
*FnTableEntry
;
176 LIST_ENTRY
*ListHead
;
177 LIST_ENTRY
*ListNode
;
180 TokenNumber
= GetExPcdTokenNumber (Guid
, TokenNumber
);
183 ListHead
= &mCallbackFnTable
[TokenNumber
];
184 ListNode
= GetFirstNode (ListHead
);
186 while (ListNode
!= ListHead
) {
187 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
189 if (FnTableEntry
->CallbackFn
== CallBackFunction
) {
191 // We only allow a Callback function to be register once
192 // for a TokenNumber. So we can safely remove the Node from
193 // the Link List and return EFI_SUCCESS.
195 RemoveEntryList (ListNode
);
196 FreePool (FnTableEntry
);
200 ListNode
= GetNextNode (ListHead
, ListNode
);
203 return EFI_INVALID_PARAMETER
;
209 ExGetNextTokeNumber (
210 IN CONST EFI_GUID
*Guid
,
211 IN PCD_TOKEN_NUMBER TokenNumber
,
212 IN EFI_GUID
*GuidTable
,
213 IN UINTN SizeOfGuidTable
,
214 IN DYNAMICEX_MAPPING
*ExMapTable
,
215 IN UINTN SizeOfExMapTable
223 MatchGuid
= ScanGuid (GuidTable
, SizeOfGuidTable
, Guid
);
224 if (MatchGuid
== NULL
) {
225 return PCD_INVALID_TOKEN_NUMBER
;
229 GuidTableIdx
= MatchGuid
- GuidTable
;
230 for (Idx
= 0; Idx
< SizeOfExMapTable
; Idx
++) {
231 if (ExMapTable
[Idx
].ExGuidIndex
== GuidTableIdx
) {
238 if (TokenNumber
== PCD_INVALID_TOKEN_NUMBER
) {
239 return ExMapTable
[Idx
].ExTokenNumber
;
242 for ( ; Idx
< SizeOfExMapTable
; Idx
++) {
243 if (ExMapTable
[Idx
].ExTokenNumber
== TokenNumber
) {
245 if (Idx
== SizeOfExMapTable
) {
247 // Exceed the length of ExMap Table
249 return PCD_INVALID_TOKEN_NUMBER
;
250 } else if (ExMapTable
[Idx
].ExGuidIndex
== GuidTableIdx
) {
252 // Found the next match
254 return ExMapTable
[Idx
].ExTokenNumber
;
257 // Guid has been changed. It is the next Token Space Guid.
258 // We should flag no more TokenNumber.
260 return PCD_INVALID_TOKEN_NUMBER
;
266 return PCD_INVALID_TOKEN_NUMBER
;
273 BuildPcdDxeDataBase (
277 PEI_PCD_DATABASE
*PeiDatabase
;
278 EFI_HOB_GUID_TYPE
*GuidHob
;
281 mPcdDatabase
= AllocateZeroPool (sizeof(PCD_DATABASE
));
282 ASSERT (mPcdDatabase
!= NULL
);
284 GuidHob
= GetFirstGuidHob (&gPcdDataBaseHobGuid
);
285 ASSERT (GuidHob
!= NULL
);
287 PeiDatabase
= (PEI_PCD_DATABASE
*) GET_GUID_HOB_DATA (GuidHob
);
289 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
291 CopyMem (&mPcdDatabase
->PeiDb
, PeiDatabase
, sizeof (PEI_PCD_DATABASE
));
294 // Copy PCD Entries with default value to PCD DATABASE
296 CopyMem (&mPcdDatabase
->DxeDb
.Init
, &gDXEPcdDbInit
, sizeof(DXE_PCD_DATABASE_INIT
));
300 // Initialized the Callback Function Table
302 for (Idx
= 0; Idx
< PCD_TOTAL_TOKEN_NUMBER
; Idx
++) {
303 InitializeListHead (&mCallbackFnTable
[Idx
]);
313 IN EFI_GUID
*VariableGuid
,
314 IN UINT16
*VariableName
,
315 OUT VOID
** VariableData
,
316 OUT UINTN
*VariableSize
323 Status
= EfiGetVariable (
324 (UINT16
*)VariableName
,
330 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
332 Buffer
= AllocatePool (Size
);
334 ASSERT (Buffer
!= NULL
);
336 Status
= EfiGetVariable (
350 GetSkuEnabledTokenNumber (
351 UINT32 LocalTokenNumber
,
360 SKU_ID
*PhaseSkuIdTable
;
363 ASSERT ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == 0);
365 PcdDb
= IsPeiDb
? (UINT8
*) &mPcdDatabase
->PeiDb
: (UINT8
*) &mPcdDatabase
->DxeDb
;
367 SkuHead
= (SKU_HEAD
*) (PcdDb
+ (LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
));
368 Value
= (UINT8
*) (PcdDb
+ SkuHead
->SkuDataStartOffset
);
370 PhaseSkuIdTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.SkuIdTable
:
371 mPcdDatabase
->DxeDb
.Init
.SkuIdTable
;
373 SkuIdTable
= &PhaseSkuIdTable
[SkuHead
->SkuIdTableOffset
];
375 for (i
= 0; i
< SkuIdTable
[0]; i
++) {
376 if (mPcdDatabase
->PeiDb
.Init
.SystemSkuId
== SkuIdTable
[i
+ 1]) {
380 ASSERT (i
< SkuIdTable
[0]);
382 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
384 Value
= (UINT8
*) &(((VPD_HEAD
*) Value
)[i
]);
385 return ((Value
- PcdDb
) | PCD_TYPE_VPD
);
388 Value
= (UINT8
*) &(((VARIABLE_HEAD
*) Value
)[i
]);
389 return ((Value
- PcdDb
) | PCD_TYPE_HII
);
393 return (Value
- PcdDb
);
410 InvokeCallbackOnSet (
411 UINT32 ExTokenNumber
,
412 CONST EFI_GUID
*Guid
, OPTIONAL
418 CALLBACK_FN_ENTRY
*FnTableEntry
;
419 LIST_ENTRY
*ListHead
;
420 LIST_ENTRY
*ListNode
;
422 ListHead
= &mCallbackFnTable
[TokenNumber
];
423 ListNode
= GetFirstNode (ListHead
);
425 while (ListNode
!= ListHead
) {
426 FnTableEntry
= CR_FNENTRY_FROM_LISTNODE(ListNode
, CALLBACK_FN_ENTRY
, Node
);
428 FnTableEntry
->CallbackFn(Guid
,
429 (Guid
== NULL
) ? TokenNumber
: ExTokenNumber
,
433 ListNode
= GetNextNode (ListHead
, ListNode
);
444 PCD_TOKEN_NUMBER TokenNumber
,
450 UINT32
*LocalTokenNumberTable
;
452 UINT32 LocalTokenNumber
;
458 VARIABLE_HEAD
*VariableHead
;
463 ASSERT (TokenNumber
< PCD_TOTAL_TOKEN_NUMBER
);
466 ASSERT (Size
<= DxePcdGetSize (TokenNumber
));
468 ASSERT (Size
== DxePcdGetSize (TokenNumber
));
471 IsPeiDb
= (TokenNumber
<= PEI_LOCAL_TOKEN_NUMBER
) ? TRUE
: FALSE
;
473 LocalTokenNumberTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.LocalTokenNumberTable
:
474 mPcdDatabase
->DxeDb
.Init
.LocalTokenNumberTable
;
476 if ((TokenNumber
< PEI_NEX_TOKEN_NUMBER
) ||
477 (TokenNumber
>= PEI_LOCAL_TOKEN_NUMBER
|| TokenNumber
< (PEI_LOCAL_TOKEN_NUMBER
+ DXE_NEX_TOKEN_NUMBER
))) {
478 InvokeCallbackOnSet (0, NULL
, TokenNumber
, Data
, Size
);
481 TokenNumber
= IsPeiDb
? TokenNumber
482 : TokenNumber
- PEI_LOCAL_TOKEN_NUMBER
;
484 LocalTokenNumber
= LocalTokenNumberTable
[TokenNumber
];
486 if ((LocalTokenNumber
& PCD_TYPE_SKU_ENABLED
) == PCD_TYPE_SKU_ENABLED
) {
487 LocalTokenNumber
= GetSkuEnabledTokenNumber (LocalTokenNumber
& ~PCD_TYPE_SKU_ENABLED
, Size
, IsPeiDb
);
490 Offset
= LocalTokenNumber
& PCD_DATABASE_OFFSET_MASK
;
492 PcdDb
= IsPeiDb
? ((UINT8
*) &mPcdDatabase
->PeiDb
) : ((UINT8
*) &mPcdDatabase
->DxeDb
);
494 StringTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.StringTable
:
495 mPcdDatabase
->DxeDb
.Init
.StringTable
;
497 InternalData
= PcdDb
+ Offset
;
499 switch (LocalTokenNumber
& ~PCD_DATABASE_OFFSET_MASK
) {
502 return EFI_INVALID_PARAMETER
;
504 case PCD_TYPE_STRING
:
505 CopyMem (&StringTable
[*((UINT16
*)InternalData
)], Data
, Size
);
510 // Bug Bug: Please implement this
512 GuidTable
= IsPeiDb
? mPcdDatabase
->PeiDb
.Init
.GuidTable
:
513 mPcdDatabase
->DxeDb
.Init
.GuidTable
;
515 VariableHead
= (VARIABLE_HEAD
*) (PcdDb
+ Offset
);
517 Guid
= &(GuidTable
[VariableHead
->GuidTableIndex
]);
518 Name
= &(StringTable
[VariableHead
->StringIndex
]);
524 CopyMem (InternalData
, Data
, Size
);
530 *((UINT8
*) InternalData
) = *((UINT8
*) Data
);
534 *((UINT16
*) InternalData
) = *((UINT16
*) Data
);
538 *((UINT32
*) InternalData
) = *((UINT32
*) Data
);
542 *((UINT64
*) InternalData
) = *((UINT64
*) Data
);
547 return EFI_NOT_FOUND
;
556 return EFI_NOT_FOUND
;
565 IN CONST EFI_GUID
*Guid
,
566 IN UINTN ExTokenNumber
,
570 return GetWorker(GetExPcdTokenNumber (Guid
, ExTokenNumber
), GetSize
);
579 IN PCD_TOKEN_NUMBER ExTokenNumber
,
580 IN CONST EFI_GUID
*Guid
,
586 PCD_TOKEN_NUMBER TokenNumber
;
588 TokenNumber
= GetExPcdTokenNumber (Guid
, ExTokenNumber
);
590 InvokeCallbackOnSet (ExTokenNumber
, Guid
, TokenNumber
, Data
, SetSize
);
592 SetWorker (TokenNumber
, Data
, SetSize
, PtrType
);
603 IN EFI_GUID
*VariableGuid
,
604 IN UINT16
*VariableName
,
617 Status
= EfiGetVariable (
618 (UINT16
*)VariableName
,
625 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
627 Buffer
= AllocatePool (Size
);
629 ASSERT (Buffer
!= NULL
);
631 Status
= EfiGetVariable (
640 CopyMem ((UINT8
*)Buffer
+ Offset
, Data
, DataSize
);
642 return EfiSetVariable (
657 GetExPcdTokenNumber (
658 IN CONST EFI_GUID
*Guid
,
659 IN PCD_TOKEN_NUMBER ExTokenNumber
663 DYNAMICEX_MAPPING
*ExMap
;
668 ExMap
= mPcdDatabase
->PeiDb
.Init
.ExMapTable
;
669 GuidTable
= mPcdDatabase
->PeiDb
.Init
.GuidTable
;
671 MatchGuid
= ScanGuid (GuidTable
, sizeof(mPcdDatabase
->PeiDb
.Init
.GuidTable
), Guid
);
672 ASSERT (MatchGuid
!= NULL
);
674 MatchGuidIdx
= MatchGuid
- GuidTable
;
676 for (i
= 0; i
< PEI_EXMAPPING_TABLE_SIZE
; i
++) {
677 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
678 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
679 return ExMap
[i
].LocalTokenNumber
;
684 ExMap
= mPcdDatabase
->DxeDb
.Init
.ExMapTable
;
685 GuidTable
= mPcdDatabase
->DxeDb
.Init
.GuidTable
;
687 MatchGuid
= ScanGuid (GuidTable
, sizeof(mPcdDatabase
->DxeDb
.Init
.GuidTable
), Guid
);
688 ASSERT (MatchGuid
!= NULL
);
690 MatchGuidIdx
= MatchGuid
- GuidTable
;
692 for (i
= 0; i
< DXE_EXMAPPING_TABLE_SIZE
; i
++) {
693 if ((ExTokenNumber
== ExMap
[i
].ExTokenNumber
) &&
694 (MatchGuidIdx
== ExMap
[i
].ExGuidIndex
)) {
695 return ExMap
[i
].LocalTokenNumber
+ PEI_LOCAL_TOKEN_NUMBER
;