2 Private functions used by PCD DXE driver.s
\r
4 Copyright (c) 2006, Intel Corporation
\r
5 All rights reserved. This program and the accompanying materials
\r
6 are licensed and made available under the terms and conditions of the BSD License
\r
7 which accompanies this distribution. The full text of the license may be found at
\r
8 http://opensource.org/licenses/bsd-license.php
\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
14 Module Name: Service.c
\r
17 #include "Service.h"
\r
21 // Build Tool will generate DXE_PCD_DB_INIT_VALUE in Autogen.h
\r
22 // Compression Algorithm will take care of the size optimization.
\r
25 PCD_DATABASE * mPcdDatabase;
\r
27 LIST_ENTRY *mCallbackFnTable;
\r
31 PCD_TOKEN_NUMBER TokenNumber,
\r
35 UINT32 *LocalTokenNumberTable;
\r
40 EFI_GUID *GuidTable;
\r
41 UINT16 *StringTable;
\r
44 VARIABLE_HEAD *VariableHead;
\r
50 UINT16 StringTableIdx;
\r
51 UINT32 LocalTokenNumber;
\r
54 ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER);
\r
56 Size = DxePcdGetSize (TokenNumber);
\r
57 ASSERT (GetSize == Size || GetSize == 0);
\r
60 IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE;
\r
62 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
\r
63 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
\r
65 SizeTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SizeTable:
\r
66 mPcdDatabase->DxeDb.Init.SizeTable;
\r
68 TokenNumber = IsPeiDb ? TokenNumber :
\r
69 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
\r
71 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
\r
73 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
\r
74 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb);
\r
77 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
\r
78 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
\r
79 mPcdDatabase->DxeDb.Init.StringTable;
\r
81 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
\r
83 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {
\r
85 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);
\r
86 return (VOID *) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);
\r
89 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
\r
90 mPcdDatabase->DxeDb.Init.GuidTable;
\r
92 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
\r
94 Guid = &(GuidTable[VariableHead->GuidTableIndex]);
\r
95 Name = &(StringTable[VariableHead->StringIndex]);
\r
97 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
\r
98 ASSERT_EFI_ERROR (Status);
\r
99 ASSERT (DataSize >= (UINTN) (VariableHead->Offset + Size));
\r
101 return (UINT8 *) Data + VariableHead->Offset;
\r
103 case PCD_TYPE_STRING:
\r
104 StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);
\r
105 return (VOID *) &StringTable[StringTableIdx];
\r
107 case PCD_TYPE_DATA:
\r
108 return (VOID *) ((UINT8 *) PcdDb + Offset);
\r
126 DxeRegisterCallBackWorker (
\r
127 IN PCD_TOKEN_NUMBER TokenNumber,
\r
128 IN CONST GUID *Guid, OPTIONAL
\r
129 IN PCD_PROTOCOL_CALLBACK CallBackFunction
\r
132 CALLBACK_FN_ENTRY *FnTableEntry;
\r
133 LIST_ENTRY *ListHead;
\r
134 LIST_ENTRY *ListNode;
\r
136 if (Guid != NULL) {
\r
137 TokenNumber = GetExPcdTokenNumber (Guid, TokenNumber);
\r
140 ListHead = &mCallbackFnTable[TokenNumber];
\r
141 ListNode = GetFirstNode (ListHead);
\r
143 while (ListNode != ListHead) {
\r
144 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
\r
146 if (FnTableEntry->CallbackFn == CallBackFunction) {
\r
148 // We only allow a Callback function to be register once
\r
149 // for a TokenNumber. So just return EFI_SUCCESS
\r
151 return EFI_SUCCESS;
\r
153 ListNode = GetNextNode (ListHead, ListNode);
\r
156 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));
\r
157 ASSERT (FnTableEntry != NULL);
\r
159 FnTableEntry->CallbackFn = CallBackFunction;
\r
160 InsertTailList (ListHead, &FnTableEntry->Node);
\r
162 return EFI_SUCCESS;
\r
169 DxeUnRegisterCallBackWorker (
\r
170 IN PCD_TOKEN_NUMBER TokenNumber,
\r
171 IN CONST GUID *Guid, OPTIONAL
\r
172 IN PCD_PROTOCOL_CALLBACK CallBackFunction
\r
175 CALLBACK_FN_ENTRY *FnTableEntry;
\r
176 LIST_ENTRY *ListHead;
\r
177 LIST_ENTRY *ListNode;
\r
179 if (Guid != NULL) {
\r
180 TokenNumber = GetExPcdTokenNumber (Guid, TokenNumber);
\r
183 ListHead = &mCallbackFnTable[TokenNumber];
\r
184 ListNode = GetFirstNode (ListHead);
\r
186 while (ListNode != ListHead) {
\r
187 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
\r
189 if (FnTableEntry->CallbackFn == CallBackFunction) {
\r
191 // We only allow a Callback function to be register once
\r
192 // for a TokenNumber. So we can safely remove the Node from
\r
193 // the Link List and return EFI_SUCCESS.
\r
195 RemoveEntryList (ListNode);
\r
196 FreePool (FnTableEntry);
\r
198 return EFI_SUCCESS;
\r
200 ListNode = GetNextNode (ListHead, ListNode);
\r
203 return EFI_INVALID_PARAMETER;
\r
209 ExGetNextTokeNumber (
\r
210 IN CONST EFI_GUID *Guid,
\r
211 IN PCD_TOKEN_NUMBER TokenNumber,
\r
212 IN EFI_GUID *GuidTable,
\r
213 IN UINTN SizeOfGuidTable,
\r
214 IN DYNAMICEX_MAPPING *ExMapTable,
\r
215 IN UINTN SizeOfExMapTable
\r
218 EFI_GUID *MatchGuid;
\r
220 UINTN GuidTableIdx;
\r
223 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);
\r
224 if (MatchGuid == NULL) {
\r
225 return PCD_INVALID_TOKEN_NUMBER;
\r
229 GuidTableIdx = MatchGuid - GuidTable;
\r
230 for (Idx = 0; Idx < SizeOfExMapTable; Idx++) {
\r
231 if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
\r
238 if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
\r
239 return ExMapTable[Idx].ExTokenNumber;
\r
242 for ( ; Idx < SizeOfExMapTable; Idx++) {
\r
243 if (ExMapTable[Idx].ExTokenNumber == TokenNumber) {
\r
245 if (Idx == SizeOfExMapTable) {
\r
247 // Exceed the length of ExMap Table
\r
249 return PCD_INVALID_TOKEN_NUMBER;
\r
250 } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {
\r
252 // Found the next match
\r
254 return ExMapTable[Idx].ExTokenNumber;
\r
257 // Guid has been changed. It is the next Token Space Guid.
\r
258 // We should flag no more TokenNumber.
\r
260 return PCD_INVALID_TOKEN_NUMBER;
\r
266 return PCD_INVALID_TOKEN_NUMBER;
\r
273 BuildPcdDxeDataBase (
\r
277 PEI_PCD_DATABASE *PeiDatabase;
\r
278 EFI_HOB_GUID_TYPE *GuidHob;
\r
281 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));
\r
282 ASSERT (mPcdDatabase != NULL);
\r
284 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
\r
286 if (GuidHob != NULL) {
\r
289 // We will copy over the PEI phase's PCD Database.
\r
291 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM
\r
292 // should not be included at all. So the GuidHob could
\r
293 // be NULL. If it is NULL, we just copy over the DXE Default
\r
294 // Value to PCD Database.
\r
297 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);
\r
299 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE
\r
301 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));
\r
305 // Copy PCD Entries with default value to PCD DATABASE
\r
307 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));
\r
311 // Initialized the Callback Function Table
\r
314 if (PCD_TOTAL_TOKEN_NUMBER != 0) {
\r
315 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER);
\r
318 for (Idx = 0; Idx < PCD_TOTAL_TOKEN_NUMBER; Idx++) {
\r
319 InitializeListHead (&mCallbackFnTable[Idx]);
\r
329 IN EFI_GUID *VariableGuid,
\r
330 IN UINT16 *VariableName,
\r
331 OUT VOID ** VariableData,
\r
332 OUT UINTN *VariableSize
\r
339 Status = EfiGetVariable (
\r
340 (UINT16 *)VariableName,
\r
346 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
\r
348 Buffer = AllocatePool (Size);
\r
350 ASSERT (Buffer != NULL);
\r
352 Status = EfiGetVariable (
\r
366 GetSkuEnabledTokenNumber (
\r
367 UINT32 LocalTokenNumber,
\r
373 SKU_ID *SkuIdTable;
\r
376 SKU_ID *PhaseSkuIdTable;
\r
379 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);
\r
381 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;
\r
383 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));
\r
384 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset);
\r
386 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :
\r
387 mPcdDatabase->DxeDb.Init.SkuIdTable;
\r
389 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];
\r
391 for (i = 0; i < SkuIdTable[0]; i++) {
\r
392 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {
\r
396 ASSERT (i < SkuIdTable[0]);
\r
398 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {
\r
400 Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);
\r
401 return ((Value - PcdDb) | PCD_TYPE_VPD);
\r
404 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);
\r
405 return ((Value - PcdDb) | PCD_TYPE_HII);
\r
407 case PCD_TYPE_DATA:
\r
409 return (Value - PcdDb);
\r
426 InvokeCallbackOnSet (
\r
427 UINT32 ExTokenNumber,
\r
428 CONST EFI_GUID *Guid, OPTIONAL
\r
434 CALLBACK_FN_ENTRY *FnTableEntry;
\r
435 LIST_ENTRY *ListHead;
\r
436 LIST_ENTRY *ListNode;
\r
438 ListHead = &mCallbackFnTable[TokenNumber];
\r
439 ListNode = GetFirstNode (ListHead);
\r
441 while (ListNode != ListHead) {
\r
442 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);
\r
444 FnTableEntry->CallbackFn(Guid,
\r
445 (Guid == NULL) ? TokenNumber : ExTokenNumber,
\r
449 ListNode = GetNextNode (ListHead, ListNode);
\r
460 PCD_TOKEN_NUMBER TokenNumber,
\r
466 UINT32 *LocalTokenNumberTable;
\r
468 UINT32 LocalTokenNumber;
\r
469 EFI_GUID *GuidTable;
\r
470 UINT16 *StringTable;
\r
473 VOID *InternalData;
\r
474 VARIABLE_HEAD *VariableHead;
\r
479 ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER);
\r
482 ASSERT (Size <= DxePcdGetSize (TokenNumber));
\r
484 ASSERT (Size == DxePcdGetSize (TokenNumber));
\r
487 IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE;
\r
489 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable :
\r
490 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;
\r
492 if ((TokenNumber < PEI_NEX_TOKEN_NUMBER) ||
\r
493 (TokenNumber >= PEI_LOCAL_TOKEN_NUMBER || TokenNumber < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER))) {
\r
494 InvokeCallbackOnSet (0, NULL, TokenNumber, Data, Size);
\r
497 TokenNumber = IsPeiDb ? TokenNumber
\r
498 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;
\r
500 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];
\r
502 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {
\r
503 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb);
\r
506 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
\r
508 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);
\r
510 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :
\r
511 mPcdDatabase->DxeDb.Init.StringTable;
\r
513 InternalData = PcdDb + Offset;
\r
515 switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {
\r
518 return EFI_INVALID_PARAMETER;
\r
520 case PCD_TYPE_STRING:
\r
521 CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, Size);
\r
526 // Bug Bug: Please implement this
\r
528 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :
\r
529 mPcdDatabase->DxeDb.Init.GuidTable;
\r
531 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);
\r
533 Guid = &(GuidTable[VariableHead->GuidTableIndex]);
\r
534 Name = &(StringTable[VariableHead->StringIndex]);
\r
536 return EFI_SUCCESS;
\r
538 case PCD_TYPE_DATA:
\r
540 CopyMem (InternalData, Data, Size);
\r
541 return EFI_SUCCESS;
\r
545 case sizeof(UINT8):
\r
546 *((UINT8 *) InternalData) = *((UINT8 *) Data);
\r
547 return EFI_SUCCESS;
\r
549 case sizeof(UINT16):
\r
550 *((UINT16 *) InternalData) = *((UINT16 *) Data);
\r
551 return EFI_SUCCESS;
\r
553 case sizeof(UINT32):
\r
554 *((UINT32 *) InternalData) = *((UINT32 *) Data);
\r
555 return EFI_SUCCESS;
\r
557 case sizeof(UINT64):
\r
558 *((UINT64 *) InternalData) = *((UINT64 *) Data);
\r
559 return EFI_SUCCESS;
\r
563 return EFI_NOT_FOUND;
\r
572 return EFI_NOT_FOUND;
\r
581 IN CONST EFI_GUID *Guid,
\r
582 IN UINTN ExTokenNumber,
\r
586 return GetWorker(GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);
\r
595 IN PCD_TOKEN_NUMBER ExTokenNumber,
\r
596 IN CONST EFI_GUID *Guid,
\r
602 PCD_TOKEN_NUMBER TokenNumber;
\r
604 TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
\r
606 InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, SetSize);
\r
608 SetWorker (TokenNumber, Data, SetSize, PtrType);
\r
610 return EFI_SUCCESS;
\r
619 IN EFI_GUID *VariableGuid,
\r
620 IN UINT16 *VariableName,
\r
621 IN CONST VOID *Data,
\r
633 Status = EfiGetVariable (
\r
634 (UINT16 *)VariableName,
\r
641 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
\r
643 Buffer = AllocatePool (Size);
\r
645 ASSERT (Buffer != NULL);
\r
647 Status = EfiGetVariable (
\r
656 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);
\r
658 return EfiSetVariable (
\r
673 GetExPcdTokenNumber (
\r
674 IN CONST EFI_GUID *Guid,
\r
675 IN PCD_TOKEN_NUMBER ExTokenNumber
\r
679 DYNAMICEX_MAPPING *ExMap;
\r
680 EFI_GUID *GuidTable;
\r
681 EFI_GUID *MatchGuid;
\r
682 UINTN MatchGuidIdx;
\r
684 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;
\r
685 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;
\r
687 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);
\r
688 ASSERT (MatchGuid != NULL);
\r
690 MatchGuidIdx = MatchGuid - GuidTable;
\r
692 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
\r
693 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
\r
694 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
\r
695 return ExMap[i].LocalTokenNumber;
\r
700 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;
\r
701 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;
\r
703 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);
\r
704 ASSERT (MatchGuid != NULL);
\r
706 MatchGuidIdx = MatchGuid - GuidTable;
\r
708 for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {
\r
709 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&
\r
710 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {
\r
711 return ExMap[i].LocalTokenNumber + PEI_LOCAL_TOKEN_NUMBER;
\r