Import PCD dxe and PCD pei modules.
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Dxe / Service.c
CommitLineData
80408db0 1/** @file\r
2Private functions used by PCD DXE driver.\r
3\r
4Copyright (c) 2006 - 2007, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13\r
14Module Name: Service.c\r
15\r
16**/\r
17//\r
18// Include common header file for this module.\r
19//\r
20#include "CommonHeader.h"\r
21\r
22#include "Service.h"\r
23\r
24\r
25PCD_DATABASE * mPcdDatabase;\r
26\r
27LIST_ENTRY *mCallbackFnTable;\r
28\r
29VOID *\r
30GetWorker (\r
31 UINTN TokenNumber,\r
32 UINTN GetSize\r
33 )\r
34{\r
35 UINT32 *LocalTokenNumberTable;\r
36 EFI_GUID *GuidTable;\r
37 UINT16 *StringTable;\r
38 EFI_GUID *Guid;\r
39 UINT16 *Name;\r
40 VARIABLE_HEAD *VariableHead;\r
41 UINT8 *VaraiableDefaultBuffer;\r
42 UINT8 *Data;\r
43 VPD_HEAD *VpdHead;\r
44 UINT8 *PcdDb;\r
45 VOID *RetPtr;\r
46 UINTN MaxSize;\r
47 UINTN TmpTokenNumber;\r
48 UINTN DataSize;\r
49 EFI_STATUS Status;\r
50 UINT32 LocalTokenNumber;\r
51 UINT32 Offset;\r
52 UINT16 StringTableIdx; \r
53 BOOLEAN IsPeiDb;\r
54\r
55 //\r
56 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
57 //\r
58 EfiAcquireLock (&mPcdDatabaseLock);\r
59\r
60 RetPtr = NULL;\r
61 //\r
62 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
63 // We have to decrement TokenNumber by 1 to make it usable\r
64 // as the array index.\r
65 //\r
66 TokenNumber--;\r
67\r
68 TmpTokenNumber = TokenNumber;\r
69 \r
70 //\r
71 // PCD_TOTAL_TOKEN_NUMBER is a auto-generated constant.\r
72 // It could be zero. EBC compiler is very choosy. It may\r
73 // report warning. So we add 1 in each size of the \r
74 // comparison.\r
75 //\r
76 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
77\r
78 ASSERT ((GetSize == DxePcdGetSize (TokenNumber + 1)) || (GetSize == 0));\r
79\r
80 // EBC compiler is very choosy. It may report warning about comparison\r
81 // between UINTN and 0 . So we add 1 in each size of the \r
82 // comparison.\r
83 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
84\r
85 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
86 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
87\r
88 TokenNumber = IsPeiDb ? TokenNumber :\r
89 TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
90\r
91 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
92 \r
93 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
94 if (GetSize == 0) {\r
95 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
96 } else {\r
97 MaxSize = GetSize;\r
98 }\r
99 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
100 }\r
101\r
102 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
103 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :\r
104 mPcdDatabase->DxeDb.Init.StringTable;\r
105 \r
106 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
107 \r
108 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
109 case PCD_TYPE_VPD:\r
110 VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);\r
111 RetPtr = (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);\r
112 break;\r
113 \r
114 case PCD_TYPE_HII:\r
115 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :\r
116 mPcdDatabase->DxeDb.Init.GuidTable;\r
117 \r
118 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
119 \r
120 Guid = &(GuidTable[VariableHead->GuidTableIndex]);\r
121 Name = &(StringTable[VariableHead->StringIndex]);\r
122 VaraiableDefaultBuffer = (UINT8 *) PcdDb + VariableHead->DefaultValueOffset;\r
123\r
124 Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
125 if (Status == EFI_SUCCESS) {\r
126 if (GetSize == 0) {\r
127 //\r
128 // It is a pointer type. So get the MaxSize reserved for\r
129 // this PCD entry.\r
130 //\r
131 GetPtrTypeSize (TmpTokenNumber, &GetSize);\r
132 }\r
133 CopyMem (VaraiableDefaultBuffer, Data + VariableHead->Offset, GetSize);\r
134 FreePool (Data);\r
135 }\r
136 //\r
137 // If the operation is successful, we copy the data\r
138 // to the default value buffer in the PCD Database.\r
139 // So that we can free the Data allocated in GetHiiVariable.\r
140 //\r
141 //\r
142 // If the operation is not successful, \r
143 // Return 1) either the default value specified by Platform Integrator \r
144 // 2) Or the value Set by a PCD set operation.\r
145 //\r
146 RetPtr = (VOID *) VaraiableDefaultBuffer;\r
147 break;\r
148\r
149 case PCD_TYPE_STRING:\r
150 StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);\r
151 RetPtr = (VOID *) &StringTable[StringTableIdx];\r
152 break;\r
153\r
154 case PCD_TYPE_DATA:\r
155 RetPtr = (VOID *) ((UINT8 *) PcdDb + Offset);\r
156 break;\r
157\r
158 default:\r
159 ASSERT (FALSE);\r
160 break;\r
161 \r
162 }\r
163\r
164 EfiReleaseLock (&mPcdDatabaseLock);\r
165 \r
166 return RetPtr;\r
167 \r
168}\r
169\r
170\r
171\r
172EFI_STATUS\r
173DxeRegisterCallBackWorker (\r
174 IN UINTN TokenNumber,\r
175 IN CONST GUID *Guid, OPTIONAL\r
176 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
177)\r
178{\r
179 CALLBACK_FN_ENTRY *FnTableEntry;\r
180 LIST_ENTRY *ListHead;\r
181 LIST_ENTRY *ListNode;\r
182\r
183 if (Guid != NULL) {\r
184 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
185 }\r
186\r
187 //\r
188 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
189 // We have to decrement TokenNumber by 1 to make it usable\r
190 // as the array index.\r
191 //\r
192 TokenNumber--;\r
193\r
194 ListHead = &mCallbackFnTable[TokenNumber];\r
195 ListNode = GetFirstNode (ListHead);\r
196\r
197 while (ListNode != ListHead) {\r
198 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
199\r
200 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
201 //\r
202 // We only allow a Callback function to be register once\r
203 // for a TokenNumber. So just return EFI_SUCCESS\r
204 //\r
205 return EFI_SUCCESS;\r
206 }\r
207 ListNode = GetNextNode (ListHead, ListNode);\r
208 }\r
209\r
210 FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));\r
211 ASSERT (FnTableEntry != NULL);\r
212\r
213 FnTableEntry->CallbackFn = CallBackFunction;\r
214 InsertTailList (ListHead, &FnTableEntry->Node);\r
215 \r
216 return EFI_SUCCESS;\r
217}\r
218\r
219\r
220\r
221\r
222EFI_STATUS\r
223DxeUnRegisterCallBackWorker (\r
224 IN UINTN TokenNumber,\r
225 IN CONST GUID *Guid, OPTIONAL\r
226 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
227)\r
228{\r
229 CALLBACK_FN_ENTRY *FnTableEntry;\r
230 LIST_ENTRY *ListHead;\r
231 LIST_ENTRY *ListNode;\r
232\r
233 if (Guid != NULL) {\r
234 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) TokenNumber);\r
235 }\r
236\r
237 //\r
238 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
239 // We have to decrement TokenNumber by 1 to make it usable\r
240 // as the array index.\r
241 //\r
242 TokenNumber--;\r
243\r
244 ListHead = &mCallbackFnTable[TokenNumber];\r
245 ListNode = GetFirstNode (ListHead);\r
246\r
247 while (ListNode != ListHead) {\r
248 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
249\r
250 if (FnTableEntry->CallbackFn == CallBackFunction) {\r
251 //\r
252 // We only allow a Callback function to be register once\r
253 // for a TokenNumber. So we can safely remove the Node from\r
254 // the Link List and return EFI_SUCCESS.\r
255 //\r
256 RemoveEntryList (ListNode);\r
257 FreePool (FnTableEntry);\r
258 \r
259 return EFI_SUCCESS;\r
260 }\r
261 ListNode = GetNextNode (ListHead, ListNode);\r
262 }\r
263\r
264 return EFI_INVALID_PARAMETER;\r
265}\r
266\r
267\r
268\r
269EFI_STATUS\r
270ExGetNextTokeNumber (\r
271 IN CONST EFI_GUID *Guid,\r
272 IN OUT UINTN *TokenNumber,\r
273 IN EFI_GUID *GuidTable,\r
274 IN UINTN SizeOfGuidTable,\r
275 IN DYNAMICEX_MAPPING *ExMapTable,\r
276 IN UINTN SizeOfExMapTable\r
277 )\r
278{\r
279 EFI_GUID *MatchGuid;\r
280 UINTN Idx;\r
281 UINTN GuidTableIdx;\r
282 BOOLEAN Found;\r
283\r
284 MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);\r
285 if (MatchGuid == NULL) {\r
286 return EFI_NOT_FOUND;\r
287 }\r
288\r
289 Found = FALSE;\r
290 GuidTableIdx = MatchGuid - GuidTable;\r
291 for (Idx = 0; Idx < SizeOfExMapTable; Idx++) {\r
292 if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {\r
293 Found = TRUE;\r
294 break;\r
295 }\r
296 }\r
297\r
298 if (Found) {\r
299 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
300 *TokenNumber = ExMapTable[Idx].ExTokenNumber;\r
301 return EFI_SUCCESS;\r
302 }\r
303\r
304 for ( ; Idx < SizeOfExMapTable; Idx++) {\r
305 if (ExMapTable[Idx].ExTokenNumber == *TokenNumber) {\r
306 Idx++;\r
307 if (Idx == SizeOfExMapTable) {\r
308 //\r
309 // Exceed the length of ExMap Table\r
310 //\r
311 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
312 return EFI_SUCCESS;\r
313 } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {\r
314 //\r
315 // Found the next match\r
316 //\r
317 *TokenNumber = ExMapTable[Idx].ExTokenNumber;\r
318 return EFI_SUCCESS;\r
319 } else {\r
320 //\r
321 // Guid has been changed. It is the next Token Space Guid.\r
322 // We should flag no more TokenNumber.\r
323 //\r
324 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;\r
325 return EFI_SUCCESS;\r
326 }\r
327 }\r
328 }\r
329 }\r
330 \r
331 return EFI_NOT_FOUND;\r
332}\r
333 \r
334\r
335\r
336\r
337VOID\r
338BuildPcdDxeDataBase (\r
339 VOID\r
340 )\r
341{\r
342 PEI_PCD_DATABASE *PeiDatabase;\r
343 EFI_HOB_GUID_TYPE *GuidHob;\r
344 UINTN Idx;\r
345\r
346 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));\r
347 ASSERT (mPcdDatabase != NULL);\r
348\r
349 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
350 if (GuidHob != NULL) {\r
351\r
352 //\r
353 // We will copy over the PEI phase's PCD Database.\r
354 // \r
355 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
356 // should not be included at all. So the GuidHob could\r
357 // be NULL. If it is NULL, we just copy over the DXE Default\r
358 // Value to PCD Database.\r
359 //\r
360 \r
361 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
362 //\r
363 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE\r
364 //\r
365 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));\r
366 }\r
367\r
368 //\r
369 // Copy PCD Entries with default value to PCD DATABASE\r
370 //\r
371 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));\r
372\r
373\r
374 //\r
375 // Initialized the Callback Function Table\r
376 //\r
377\r
378 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));\r
379 \r
380 // EBC compiler is very choosy. It may report warning about comparison\r
381 // between UINTN and 0 . So we add 1 in each size of the \r
382 // comparison.\r
383 for (Idx = 0; Idx + 1 < PCD_TOTAL_TOKEN_NUMBER + 1; Idx++) {\r
384 InitializeListHead (&mCallbackFnTable[Idx]);\r
385 }\r
386 \r
387 return;\r
388}\r
389\r
390\r
391\r
392EFI_STATUS\r
393GetHiiVariable (\r
394 IN EFI_GUID *VariableGuid,\r
395 IN UINT16 *VariableName,\r
396 OUT UINT8 **VariableData,\r
397 OUT UINTN *VariableSize\r
398 )\r
399{\r
400 UINTN Size;\r
401 EFI_STATUS Status;\r
402 UINT8 *Buffer;\r
403\r
404 Size = 0;\r
405 Buffer = NULL;\r
406 \r
407 Status = gRT->GetVariable (\r
408 (UINT16 *)VariableName,\r
409 VariableGuid,\r
410 NULL,\r
411 &Size,\r
412 Buffer\r
413 );\r
414 \r
415 if (Status == EFI_BUFFER_TOO_SMALL) {\r
416 Buffer = (UINT8 *) AllocatePool (Size);\r
417\r
418 ASSERT (Buffer != NULL);\r
419\r
420 Status = gRT->GetVariable (\r
421 VariableName,\r
422 VariableGuid,\r
423 NULL,\r
424 &Size,\r
425 Buffer\r
426 );\r
427\r
428 ASSERT (Status == EFI_SUCCESS);\r
429 *VariableData = Buffer;\r
430 *VariableSize = Size;\r
431 }\r
432\r
433 return Status;\r
434}\r
435\r
436\r
437UINT32\r
438GetSkuEnabledTokenNumber (\r
439 UINT32 LocalTokenNumber,\r
440 UINTN Size,\r
441 BOOLEAN IsPeiDb\r
442 ) \r
443{\r
444 SKU_HEAD *SkuHead;\r
445 SKU_ID *SkuIdTable;\r
446 INTN i;\r
447 UINT8 *Value;\r
448 SKU_ID *PhaseSkuIdTable;\r
449 UINT8 *PcdDb;\r
450\r
451 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
452\r
453 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
454\r
455 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
456 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
457\r
458 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
459 mPcdDatabase->DxeDb.Init.SkuIdTable;\r
460 \r
461 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
462 \r
463 for (i = 0; i < SkuIdTable[0]; i++) {\r
464 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {\r
465 break;\r
466 }\r
467 }\r
468 ASSERT (i < SkuIdTable[0]);\r
469\r
470 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
471 case PCD_TYPE_VPD:\r
472 Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);\r
473 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);\r
474\r
475 case PCD_TYPE_HII:\r
476 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);\r
477 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);\r
478\r
479 case PCD_TYPE_STRING:\r
480 Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);\r
481 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);\r
482 \r
483 case PCD_TYPE_DATA:\r
484 Value += Size * i;\r
485 return (UINT32) (Value - PcdDb);\r
486\r
487 default:\r
488 ASSERT (FALSE);\r
489 }\r
490\r
491 ASSERT (FALSE);\r
492\r
493 return 0;\r
494 \r
495}\r
496\r
497\r
498\r
499\r
500STATIC\r
501VOID\r
502InvokeCallbackOnSet (\r
503 UINT32 ExTokenNumber,\r
504 CONST EFI_GUID *Guid, OPTIONAL\r
505 UINTN TokenNumber,\r
506 VOID *Data,\r
507 UINTN Size\r
508 )\r
509{\r
510 CALLBACK_FN_ENTRY *FnTableEntry;\r
511 LIST_ENTRY *ListHead;\r
512 LIST_ENTRY *ListNode;\r
513\r
514 //\r
515 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
516 // We have to decrement TokenNumber by 1 to make it usable\r
517 // as the array index.\r
518 //\r
519 TokenNumber--;\r
520 \r
521 ListHead = &mCallbackFnTable[TokenNumber];\r
522 ListNode = GetFirstNode (ListHead);\r
523\r
524 while (ListNode != ListHead) {\r
525 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
526\r
527 FnTableEntry->CallbackFn(Guid, \r
528 (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
529 Data,\r
530 Size);\r
531 \r
532 ListNode = GetNextNode (ListHead, ListNode);\r
533 }\r
534 \r
535 return;\r
536}\r
537\r
538\r
539EFI_STATUS\r
540SetValueWorker (\r
541 IN UINTN TokenNumber,\r
542 IN VOID *Data,\r
543 IN UINTN Size\r
544 )\r
545{\r
546 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
547}\r
548\r
549\r
550EFI_STATUS\r
551SetWorker (\r
552 IN UINTN TokenNumber,\r
553 IN VOID *Data,\r
554 IN OUT UINTN *Size,\r
555 IN BOOLEAN PtrType\r
556 )\r
557{\r
558 UINT32 *LocalTokenNumberTable;\r
559 BOOLEAN IsPeiDb;\r
560 UINT32 LocalTokenNumber;\r
561 EFI_GUID *GuidTable;\r
562 UINT16 *StringTable;\r
563 EFI_GUID *Guid;\r
564 UINT16 *Name;\r
565 UINTN VariableOffset;\r
566 VOID *InternalData;\r
567 VARIABLE_HEAD *VariableHead;\r
568 UINTN Offset;\r
569 UINT8 *PcdDb;\r
570 EFI_STATUS Status;\r
571 UINTN MaxSize;\r
572 UINTN TmpTokenNumber;\r
573\r
574 //\r
575 // Aquire lock to prevent reentrance from TPL_CALLBACK level\r
576 //\r
577 EfiAcquireLock (&mPcdDatabaseLock);\r
578\r
579 //\r
580 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
581 // We have to decrement TokenNumber by 1 to make it usable\r
582 // as the array index.\r
583 //\r
584 TokenNumber--;\r
585\r
586 TmpTokenNumber = TokenNumber;\r
587 \r
588 // EBC compiler is very choosy. It may report warning about comparison\r
589 // between UINTN and 0 . So we add 1 in each size of the \r
590 // comparison.\r
591\r
592 ASSERT (TokenNumber + 1 < PCD_TOTAL_TOKEN_NUMBER + 1);\r
593\r
594 if (!PtrType) {\r
595 ASSERT (*Size == DxePcdGetSize (TokenNumber + 1));\r
596 }\r
597 \r
598 // EBC compiler is very choosy. It may report warning about comparison\r
599 // between UINTN and 0 . So we add 1 in each size of the \r
600 // comparison.\r
601 IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1) ? TRUE : FALSE);\r
602\r
603 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
604 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
605\r
606 // EBC compiler is very choosy. It may report warning about comparison\r
607 // between UINTN and 0 . So we add 1 in each size of the \r
608 // comparison.\r
609 if ((TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) ||\r
610 (TokenNumber + 1 >= PEI_LOCAL_TOKEN_NUMBER + 1 || TokenNumber + 1 < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER + 1))) {\r
611 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
612 }\r
613\r
614 TokenNumber = IsPeiDb ? TokenNumber\r
615 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
616\r
617 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
618 \r
619 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
620 if (PtrType) {\r
621 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
622 } else {\r
623 MaxSize = *Size;\r
624 }\r
625 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
626 }\r
627\r
628 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
629\r
630 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
631\r
632 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :\r
633 mPcdDatabase->DxeDb.Init.StringTable;\r
634 \r
635 InternalData = PcdDb + Offset;\r
636\r
637 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
638 case PCD_TYPE_VPD:\r
639 ASSERT (FALSE);\r
640 Status = EFI_INVALID_PARAMETER;\r
641 break;\r
642 \r
643 case PCD_TYPE_STRING:\r
644 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
645 CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, *Size);\r
646 Status = EFI_SUCCESS;\r
647 } else {\r
648 Status = EFI_INVALID_PARAMETER;\r
649 }\r
650 break;\r
651\r
652 case PCD_TYPE_HII:\r
653 if (PtrType) {\r
654 if (!SetPtrTypeSize (TmpTokenNumber, Size)) {\r
655 Status = EFI_INVALID_PARAMETER;\r
656 break;\r
657 }\r
658 }\r
659 \r
660 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :\r
661 mPcdDatabase->DxeDb.Init.GuidTable;\r
662 \r
663 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
664 \r
665 Guid = &(GuidTable[VariableHead->GuidTableIndex]);\r
666 Name = &(StringTable[VariableHead->StringIndex]);\r
667 VariableOffset = VariableHead->Offset;\r
668\r
669 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
670\r
671 if (EFI_NOT_FOUND == Status) {\r
672 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
673 Status = EFI_SUCCESS;\r
674 } \r
675 break;\r
676 \r
677 case PCD_TYPE_DATA:\r
678 if (PtrType) {\r
679 if (SetPtrTypeSize (TmpTokenNumber, Size)) {\r
680 CopyMem (InternalData, Data, *Size);\r
681 Status = EFI_SUCCESS;\r
682 } else {\r
683 Status = EFI_INVALID_PARAMETER;\r
684 }\r
685 break;\r
686 }\r
687\r
688 Status = EFI_SUCCESS;\r
689 switch (*Size) {\r
690 case sizeof(UINT8):\r
691 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
692 break;\r
693\r
694 case sizeof(UINT16):\r
695 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
696 break;\r
697\r
698 case sizeof(UINT32):\r
699 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
700 break;\r
701\r
702 case sizeof(UINT64):\r
703 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
704 break;\r
705\r
706 default:\r
707 ASSERT (FALSE);\r
708 Status = EFI_NOT_FOUND;\r
709 break;\r
710 }\r
711 break;\r
712\r
713 default:\r
714 ASSERT (FALSE);\r
715 Status = EFI_NOT_FOUND;\r
716 break;\r
717 }\r
718\r
719 EfiReleaseLock (&mPcdDatabaseLock);\r
720 \r
721 return Status;\r
722}\r
723\r
724\r
725\r
726\r
727\r
728VOID *\r
729ExGetWorker (\r
730 IN CONST EFI_GUID *Guid,\r
731 IN UINTN ExTokenNumber,\r
732 IN UINTN GetSize\r
733 ) \r
734{\r
735 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
736}\r
737\r
738\r
739\r
740\r
741EFI_STATUS\r
742ExSetValueWorker (\r
743 IN UINTN ExTokenNumber,\r
744 IN CONST EFI_GUID *Guid,\r
745 IN VOID *Data,\r
746 IN UINTN SetSize\r
747 )\r
748{\r
749 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
750}\r
751\r
752\r
753EFI_STATUS\r
754ExSetWorker (\r
755 IN UINTN ExTokenNumber,\r
756 IN CONST EFI_GUID *Guid,\r
757 IN VOID *Data,\r
758 IN OUT UINTN *SetSize,\r
759 IN BOOLEAN PtrType\r
760 )\r
761{\r
762 UINTN TokenNumber;\r
763 \r
764 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
765\r
766 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
767\r
768 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
769\r
770}\r
771\r
772\r
773\r
774\r
775EFI_STATUS\r
776SetHiiVariable (\r
777 IN EFI_GUID *VariableGuid,\r
778 IN UINT16 *VariableName,\r
779 IN CONST VOID *Data,\r
780 IN UINTN DataSize,\r
781 IN UINTN Offset\r
782 )\r
783{\r
784 UINTN Size;\r
785 VOID *Buffer;\r
786 EFI_STATUS Status;\r
787 UINT32 Attribute;\r
788\r
789 Size = 0;\r
790\r
791 Status = gRT->GetVariable (\r
792 (UINT16 *)VariableName,\r
793 VariableGuid,\r
794 NULL,\r
795 &Size,\r
796 NULL\r
797 );\r
798\r
799 if (Status == EFI_BUFFER_TOO_SMALL) {\r
800\r
801 Buffer = AllocatePool (Size);\r
802\r
803 ASSERT (Buffer != NULL);\r
804\r
805 Status = gRT->GetVariable (\r
806 VariableName,\r
807 VariableGuid,\r
808 &Attribute,\r
809 &Size,\r
810 Buffer\r
811 );\r
812 \r
813 ASSERT_EFI_ERROR (Status);\r
814\r
815 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
816\r
817 Status = gRT->SetVariable (\r
818 VariableName,\r
819 VariableGuid,\r
820 Attribute,\r
821 Size,\r
822 Buffer\r
823 );\r
824\r
825 FreePool (Buffer);\r
826 return Status;\r
827\r
828 } \r
829 \r
830 //\r
831 // If we drop to here, we don't have a Variable entry in\r
832 // the variable service yet. So, we will save the data\r
833 // in the PCD Database's volatile area.\r
834 //\r
835 return Status;\r
836}\r
837\r
838\r
839\r
840\r
841\r
842UINTN \r
843GetExPcdTokenNumber (\r
844 IN CONST EFI_GUID *Guid,\r
845 IN UINT32 ExTokenNumber\r
846 )\r
847{\r
848 UINT32 i;\r
849 DYNAMICEX_MAPPING *ExMap;\r
850 EFI_GUID *GuidTable;\r
851 EFI_GUID *MatchGuid;\r
852 UINTN MatchGuidIdx;\r
853\r
854 if (!PEI_DATABASE_EMPTY) {\r
855 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;\r
856 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;\r
857 \r
858 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
859 \r
860 if (MatchGuid != NULL) {\r
861\r
862 MatchGuidIdx = MatchGuid - GuidTable;\r
863 \r
864 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
865 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
866 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
867 return ExMap[i].LocalTokenNumber;\r
868\r
869 }\r
870 }\r
871 }\r
872 }\r
873 \r
874 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;\r
875 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;\r
876\r
877 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
878 //\r
879 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
880 // error in the BUILD system.\r
881 //\r
882 ASSERT (MatchGuid != NULL);\r
883\r
884 MatchGuidIdx = MatchGuid - GuidTable;\r
885 \r
886 for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {\r
887 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
888 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
889 return ExMap[i].LocalTokenNumber;\r
890 }\r
891 }\r
892\r
893 ASSERT (FALSE);\r
894\r
895 return 0;\r
896}\r
897\r
898\r
899STATIC\r
900SKU_ID *\r
901GetSkuIdArray (\r
902 IN UINTN LocalTokenNumberTableIdx,\r
903 IN BOOLEAN IsPeiPcd\r
904 )\r
905{\r
906 SKU_HEAD *SkuHead;\r
907 UINTN LocalTokenNumber;\r
908 UINT8 *Database;\r
909\r
910 if (IsPeiPcd) {\r
911 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
912 Database = (UINT8 *) &mPcdDatabase->PeiDb;\r
913 } else {\r
914 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];\r
915 Database = (UINT8 *) &mPcdDatabase->DxeDb;\r
916 }\r
917\r
918 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
919\r
920 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
921\r
922 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
923 \r
924}\r
925\r
926\r
927STATIC\r
928UINTN\r
929GetSizeTableIndexA (\r
930 IN UINTN LocalTokenNumberTableIdx,\r
931 IN UINT32 *LocalTokenNumberTable,\r
932 IN BOOLEAN IsPeiDb\r
933 )\r
934{\r
935 UINTN i;\r
936 UINTN SizeTableIdx;\r
937 UINTN LocalTokenNumber;\r
938 SKU_ID *SkuIdTable;\r
939 \r
940 SizeTableIdx = 0;\r
941\r
942 for (i=0; i<LocalTokenNumberTableIdx; i++) {\r
943 LocalTokenNumber = LocalTokenNumberTable[i];\r
944\r
945 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
946 //\r
947 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
948 // PCD entry.\r
949 //\r
950 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
951 //\r
952 // We have only one entry for VPD enabled PCD entry:\r
953 // 1) MAX Size.\r
954 // We consider current size is equal to MAX size.\r
955 //\r
956 SizeTableIdx++;\r
957 } else {\r
958 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
959 //\r
960 // We have only two entry for Non-Sku enabled PCD entry:\r
961 // 1) MAX SIZE\r
962 // 2) Current Size\r
963 //\r
964 SizeTableIdx += 2;\r
965 } else {\r
966 //\r
967 // We have these entry for SKU enabled PCD entry\r
968 // 1) MAX SIZE\r
969 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
970 //\r
971 SkuIdTable = GetSkuIdArray (i, IsPeiDb);\r
972 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
973 }\r
974 }\r
975 }\r
976\r
977 }\r
978\r
979 return SizeTableIdx;\r
980}\r
981\r
982\r
983\r
984STATIC\r
985UINTN\r
986GetSizeTableIndex (\r
987 IN UINTN LocalTokenNumberTableIdx,\r
988 IN BOOLEAN IsPeiDb\r
989 )\r
990{\r
991 UINT32 *LocalTokenNumberTable;\r
992 \r
993 if (IsPeiDb) {\r
994 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
995 } else {\r
996 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
997 }\r
998 return GetSizeTableIndexA (LocalTokenNumberTableIdx, \r
999 LocalTokenNumberTable,\r
1000 IsPeiDb);\r
1001}\r
1002\r
1003\r
1004\r
1005UINTN\r
1006GetPtrTypeSize (\r
1007 IN UINTN LocalTokenNumberTableIdx,\r
1008 OUT UINTN *MaxSize\r
1009 )\r
1010{\r
1011 INTN SizeTableIdx;\r
1012 UINTN LocalTokenNumber;\r
1013 SKU_ID *SkuIdTable;\r
1014 SIZE_INFO *SizeTable;\r
1015 UINTN i;\r
1016 BOOLEAN IsPeiDb;\r
1017 UINT32 *LocalTokenNumberTable;\r
1018\r
1019 // EBC compiler is very choosy. It may report warning about comparison\r
1020 // between UINTN and 0 . So we add 1 in each size of the \r
1021 // comparison.\r
1022 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1023\r
1024\r
1025 if (IsPeiDb) {\r
1026 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1027 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1028 } else {\r
1029 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1030 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1031 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1032 }\r
1033\r
1034 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1035\r
1036 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1037 \r
1038 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1039\r
1040 *MaxSize = SizeTable[SizeTableIdx];\r
1041 //\r
1042 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1043 // PCD entry.\r
1044 //\r
1045 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
1046 //\r
1047 // We have only one entry for VPD enabled PCD entry:\r
1048 // 1) MAX Size.\r
1049 // We consider current size is equal to MAX size.\r
1050 //\r
1051 return *MaxSize;\r
1052 } else {\r
1053 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1054 //\r
1055 // We have only two entry for Non-Sku enabled PCD entry:\r
1056 // 1) MAX SIZE\r
1057 // 2) Current Size\r
1058 //\r
1059 return SizeTable[SizeTableIdx + 1];\r
1060 } else {\r
1061 //\r
1062 // We have these entry for SKU enabled PCD entry\r
1063 // 1) MAX SIZE\r
1064 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1065 //\r
1066 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
1067 for (i = 0; i < SkuIdTable[0]; i++) {\r
1068 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1069 return SizeTable[SizeTableIdx + 1 + i];\r
1070 }\r
1071 }\r
1072 return SizeTable[SizeTableIdx + 1];\r
1073 }\r
1074 }\r
1075}\r
1076\r
1077\r
1078\r
1079BOOLEAN\r
1080SetPtrTypeSize (\r
1081 IN UINTN LocalTokenNumberTableIdx,\r
1082 IN OUT UINTN *CurrentSize\r
1083 )\r
1084{\r
1085 INTN SizeTableIdx;\r
1086 UINTN LocalTokenNumber;\r
1087 SKU_ID *SkuIdTable;\r
1088 SIZE_INFO *SizeTable;\r
1089 UINTN i;\r
1090 UINTN MaxSize;\r
1091 BOOLEAN IsPeiDb;\r
1092 UINT32 *LocalTokenNumberTable;\r
1093\r
1094 // EBC compiler is very choosy. It may report warning about comparison\r
1095 // between UINTN and 0 . So we add 1 in each size of the \r
1096 // comparison.\r
1097 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1098\r
1099 if (IsPeiDb) {\r
1100 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1101 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1102 } else {\r
1103 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1104 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1105 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1106 }\r
1107\r
1108 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1109\r
1110 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1111 \r
1112 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1113\r
1114 MaxSize = SizeTable[SizeTableIdx];\r
1115 //\r
1116 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1117 // PCD entry.\r
1118 //\r
1119 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
1120 //\r
1121 // We shouldn't come here as we don't support SET for VPD\r
1122 //\r
1123 ASSERT (FALSE);\r
1124 return FALSE;\r
1125 } else {\r
1126 if ((*CurrentSize > MaxSize) ||\r
1127 (*CurrentSize == MAX_ADDRESS)) {\r
1128 *CurrentSize = MaxSize;\r
1129 return FALSE;\r
1130 } \r
1131 \r
1132 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1133 //\r
1134 // We have only two entry for Non-Sku enabled PCD entry:\r
1135 // 1) MAX SIZE\r
1136 // 2) Current Size\r
1137 //\r
1138 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1139 return TRUE;\r
1140 } else {\r
1141 //\r
1142 // We have these entry for SKU enabled PCD entry\r
1143 // 1) MAX SIZE\r
1144 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1145 //\r
1146 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
1147 for (i = 0; i < SkuIdTable[0]; i++) {\r
1148 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1149 SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;\r
1150 return TRUE;\r
1151 }\r
1152 }\r
1153 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1154 return TRUE;\r
1155 }\r
1156 }\r
1157}\r
1158\r