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