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