]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EdkModulePkg/Universal/PCD/Dxe/Service.c
Add in support for MaxSize and CurrentSize for PCD entry.
[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
255UINTN \r
256ExGetNextTokeNumber (\r
257 IN CONST EFI_GUID *Guid,\r
258 IN 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 PCD_INVALID_TOKEN_NUMBER;\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 return ExMapTable[Idx].ExTokenNumber;\r
287 }\r
288\r
289 for ( ; Idx < SizeOfExMapTable; Idx++) {\r
290 if (ExMapTable[Idx].ExTokenNumber == TokenNumber) {\r
291 Idx++;\r
292 if (Idx == SizeOfExMapTable) {\r
293 //\r
294 // Exceed the length of ExMap Table\r
295 //\r
296 return PCD_INVALID_TOKEN_NUMBER;\r
297 } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {\r
298 //\r
299 // Found the next match\r
300 //\r
301 return ExMapTable[Idx].ExTokenNumber;\r
302 } else {\r
303 //\r
304 // Guid has been changed. It is the next Token Space Guid.\r
305 // We should flag no more TokenNumber.\r
306 //\r
307 return PCD_INVALID_TOKEN_NUMBER;\r
308 }\r
309 }\r
310 }\r
311 }\r
312 \r
313 return PCD_INVALID_TOKEN_NUMBER;\r
314}\r
315 \r
316\r
317\r
318\r
319VOID\r
320BuildPcdDxeDataBase (\r
321 VOID\r
322 )\r
323{\r
324 PEI_PCD_DATABASE *PeiDatabase;\r
325 EFI_HOB_GUID_TYPE *GuidHob;\r
326 UINTN Idx;\r
327\r
328 mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));\r
329 ASSERT (mPcdDatabase != NULL);\r
330\r
331 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
332\r
333 if (GuidHob != NULL) {\r
334\r
335 //\r
336 // We will copy over the PEI phase's PCD Database.\r
337 // \r
338 // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
339 // should not be included at all. So the GuidHob could\r
340 // be NULL. If it is NULL, we just copy over the DXE Default\r
341 // Value to PCD Database.\r
342 //\r
343 \r
344 PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
345 //\r
346 // Copy PCD Entries refereneced in PEI phase to PCD DATABASE\r
347 //\r
348 CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));\r
349 }\r
350\r
351 //\r
352 // Copy PCD Entries with default value to PCD DATABASE\r
353 //\r
354 CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));\r
355\r
356\r
357 //\r
358 // Initialized the Callback Function Table\r
359 //\r
360\r
361 if (PCD_TOTAL_TOKEN_NUMBER != 0) {\r
362 mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER * sizeof (LIST_ENTRY));\r
363 }\r
364 \r
365 for (Idx = 0; Idx < PCD_TOTAL_TOKEN_NUMBER; Idx++) {\r
366 InitializeListHead (&mCallbackFnTable[Idx]);\r
367 }\r
368 \r
369 return;\r
370}\r
371\r
372\r
373\r
374EFI_STATUS\r
375GetHiiVariable (\r
376 IN EFI_GUID *VariableGuid,\r
377 IN UINT16 *VariableName,\r
378 OUT VOID **VariableData,\r
379 OUT UINTN *VariableSize\r
380 )\r
381{\r
382 UINTN Size;\r
383 EFI_STATUS Status;\r
384 VOID *Buffer;\r
385\r
386 Size = 0;\r
387 Buffer = NULL;\r
388 \r
389 Status = EfiGetVariable (\r
390 (UINT16 *)VariableName,\r
391 VariableGuid,\r
392 NULL,\r
393 &Size,\r
394 Buffer\r
395 );\r
396 \r
397 if (Status == EFI_BUFFER_TOO_SMALL) {\r
398 Buffer = AllocatePool (Size);\r
399\r
400 ASSERT (Buffer != NULL);\r
401\r
402 Status = EfiGetVariable (\r
403 VariableName,\r
404 VariableGuid,\r
405 NULL,\r
406 &Size,\r
407 Buffer\r
408 );\r
409\r
410 ASSERT (Status == EFI_SUCCESS);\r
411 *VariableData = Buffer;\r
412 *VariableSize = Size;\r
413 }\r
414\r
415 return Status;\r
416}\r
417\r
418\r
419UINT32\r
420GetSkuEnabledTokenNumber (\r
421 UINT32 LocalTokenNumber,\r
422 UINTN Size,\r
423 BOOLEAN IsPeiDb\r
424 ) \r
425{\r
426 SKU_HEAD *SkuHead;\r
427 SKU_ID *SkuIdTable;\r
428 INTN i;\r
429 UINT8 *Value;\r
430 SKU_ID *PhaseSkuIdTable;\r
431 UINT8 *PcdDb;\r
432\r
433 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
434\r
435 PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
436\r
437 SkuHead = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
438 Value = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
439\r
440 PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
441 mPcdDatabase->DxeDb.Init.SkuIdTable;\r
442 \r
443 SkuIdTable = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
444 \r
445 for (i = 0; i < SkuIdTable[0]; i++) {\r
446 if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {\r
447 break;\r
448 }\r
449 }\r
450 ASSERT (i < SkuIdTable[0]);\r
451\r
452 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
453 case PCD_TYPE_VPD:\r
454 Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);\r
455 return (UINT32) ((Value - PcdDb) | PCD_TYPE_VPD);\r
456\r
457 case PCD_TYPE_HII:\r
458 Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);\r
459 return (UINT32) ((Value - PcdDb) | PCD_TYPE_HII);\r
460\r
461 case PCD_TYPE_STRING:\r
462 Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);\r
463 return (UINT32) ((Value - PcdDb) | PCD_TYPE_STRING);\r
464 \r
465 case PCD_TYPE_DATA:\r
466 Value += Size * i;\r
467 return (UINT32) (Value - PcdDb);\r
468\r
469 default:\r
470 ASSERT (FALSE);\r
471 }\r
472\r
473 ASSERT (FALSE);\r
474\r
475 return 0;\r
476 \r
477}\r
478\r
479\r
480\r
481\r
482\r
483VOID\r
484InvokeCallbackOnSet (\r
485 UINT32 ExTokenNumber,\r
486 CONST EFI_GUID *Guid, OPTIONAL\r
487 UINTN TokenNumber,\r
488 VOID *Data,\r
489 UINTN Size\r
490 )\r
491{\r
492 CALLBACK_FN_ENTRY *FnTableEntry;\r
493 LIST_ENTRY *ListHead;\r
494 LIST_ENTRY *ListNode;\r
495\r
496 //\r
497 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
498 // We have to decrement TokenNumber by 1 to make it usable\r
499 // as the array index.\r
500 //\r
501 TokenNumber--;\r
502 \r
503 ListHead = &mCallbackFnTable[TokenNumber];\r
504 ListNode = GetFirstNode (ListHead);\r
505\r
506 while (ListNode != ListHead) {\r
507 FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
508\r
509 FnTableEntry->CallbackFn(Guid, \r
510 (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
511 Data,\r
512 Size);\r
513 \r
514 ListNode = GetNextNode (ListHead, ListNode);\r
515 }\r
516 \r
517 return;\r
518}\r
519\r
520\r
521EFI_STATUS\r
522SetValueWorker (\r
523 IN UINTN TokenNumber,\r
524 IN VOID *Data,\r
525 IN UINTN Size\r
526 )\r
527{\r
528 return SetWorker (TokenNumber, Data, &Size, FALSE);\r
529}\r
530\r
531\r
532EFI_STATUS\r
533SetWorker (\r
534 IN UINTN TokenNumber,\r
535 IN VOID *Data,\r
536 IN OUT UINTN *Size,\r
537 IN BOOLEAN PtrType\r
538 )\r
539{\r
540 UINT32 *LocalTokenNumberTable;\r
541 BOOLEAN IsPeiDb;\r
542 UINT32 LocalTokenNumber;\r
543 EFI_GUID *GuidTable;\r
544 UINT16 *StringTable;\r
545 EFI_GUID *Guid;\r
546 UINT16 *Name;\r
547 UINTN VariableOffset;\r
548 VOID *InternalData;\r
549 VARIABLE_HEAD *VariableHead;\r
550 UINTN Offset;\r
551 UINT8 *PcdDb;\r
552 EFI_STATUS Status;\r
553 UINTN MaxSize;\r
554 UINTN TmpTokenNumber;\r
555\r
556 //\r
557 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
558 // We have to decrement TokenNumber by 1 to make it usable\r
559 // as the array index.\r
560 //\r
561 TokenNumber--;\r
562\r
563 TmpTokenNumber = TokenNumber;\r
564 \r
565 ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER);\r
566\r
567 if (!PtrType) {\r
568 ASSERT (*Size == DxePcdGetSize (TokenNumber + 1));\r
569 }\r
570 \r
571 IsPeiDb = (TokenNumber < PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE;\r
572\r
573 LocalTokenNumberTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
574 mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
575\r
576 if ((TokenNumber < PEI_NEX_TOKEN_NUMBER) ||\r
577 (TokenNumber >= PEI_LOCAL_TOKEN_NUMBER || TokenNumber < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER))) {\r
578 InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
579 }\r
580\r
581 TokenNumber = IsPeiDb ? TokenNumber\r
582 : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
583\r
584 LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
585 \r
586 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
587 if (PtrType) {\r
588 GetPtrTypeSize (TmpTokenNumber, &MaxSize);\r
589 } else {\r
590 MaxSize = *Size;\r
591 }\r
592 LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize, IsPeiDb);\r
593 }\r
594\r
595 Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
596\r
597 PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
598\r
599 StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :\r
600 mPcdDatabase->DxeDb.Init.StringTable;\r
601 \r
602 InternalData = PcdDb + Offset;\r
603\r
604 switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
605 case PCD_TYPE_VPD:\r
606 ASSERT (FALSE);\r
607 return EFI_INVALID_PARAMETER;\r
608 \r
609 case PCD_TYPE_STRING:\r
610 if (SetPtrTypeSize (TokenNumber, Size)) {\r
611 CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, *Size);\r
612 return EFI_SUCCESS;\r
613 } else {\r
614 return EFI_INVALID_PARAMETER;\r
615 }\r
616\r
617 case PCD_TYPE_HII:\r
618 if (PtrType) {\r
619 if (!SetPtrTypeSize (TokenNumber, Size)) {\r
620 return EFI_INVALID_PARAMETER;\r
621 }\r
622 }\r
623 \r
624 GuidTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :\r
625 mPcdDatabase->DxeDb.Init.GuidTable;\r
626 \r
627 VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
628 \r
629 Guid = &(GuidTable[VariableHead->GuidTableIndex]);\r
630 Name = &(StringTable[VariableHead->StringIndex]);\r
631 VariableOffset = VariableHead->Offset;\r
632\r
633 Status = SetHiiVariable (Guid, Name, Data, *Size, VariableOffset);\r
634\r
635 if (EFI_NOT_FOUND == Status) {\r
636 CopyMem (PcdDb + VariableHead->DefaultValueOffset, Data, *Size);\r
637 return EFI_SUCCESS;\r
638 } else {\r
639 return Status;\r
640 }\r
641 \r
642 //\r
643 // Bug Bug: Please implement this\r
644 //\r
645\r
646 case PCD_TYPE_DATA:\r
647 if (PtrType) {\r
648 if (SetPtrTypeSize (TokenNumber, Size)) {\r
649 CopyMem (InternalData, Data, *Size);\r
650 return EFI_SUCCESS;\r
651 } else {\r
652 return EFI_INVALID_PARAMETER;\r
653 }\r
654 }\r
655\r
656 switch (*Size) {\r
657 case sizeof(UINT8):\r
658 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
659 return EFI_SUCCESS;\r
660\r
661 case sizeof(UINT16):\r
662 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
663 return EFI_SUCCESS;\r
664\r
665 case sizeof(UINT32):\r
666 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
667 return EFI_SUCCESS;\r
668\r
669 case sizeof(UINT64):\r
670 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
671 return EFI_SUCCESS;\r
672\r
673 default:\r
674 ASSERT (FALSE);\r
675 return EFI_NOT_FOUND;\r
676 }\r
677\r
678 default:\r
679 ASSERT (FALSE);\r
680 break;\r
681 }\r
682 \r
683 ASSERT (FALSE);\r
684 return EFI_NOT_FOUND;\r
685}\r
686\r
687\r
688\r
689\r
690\r
691VOID *\r
692ExGetWorker (\r
693 IN CONST EFI_GUID *Guid,\r
694 IN UINTN ExTokenNumber,\r
695 IN UINTN GetSize\r
696 ) \r
697{\r
698 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
699}\r
700\r
701\r
702\r
703\r
704EFI_STATUS\r
705ExSetValueWorker (\r
706 IN UINTN ExTokenNumber,\r
707 IN CONST EFI_GUID *Guid,\r
708 IN VOID *Data,\r
709 IN UINTN SetSize\r
710 )\r
711{\r
712 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
713}\r
714\r
715\r
716EFI_STATUS\r
717ExSetWorker (\r
718 IN UINTN ExTokenNumber,\r
719 IN CONST EFI_GUID *Guid,\r
720 IN VOID *Data,\r
721 IN OUT UINTN *SetSize,\r
722 IN BOOLEAN PtrType\r
723 )\r
724{\r
725 UINTN TokenNumber;\r
726 \r
727 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
728\r
729 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
730\r
731 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
732\r
733}\r
734\r
735\r
736\r
737\r
738EFI_STATUS\r
739SetHiiVariable (\r
740 IN EFI_GUID *VariableGuid,\r
741 IN UINT16 *VariableName,\r
742 IN CONST VOID *Data,\r
743 IN UINTN DataSize,\r
744 IN UINTN Offset\r
745 )\r
746{\r
747 UINTN Size;\r
748 VOID *Buffer;\r
749 EFI_STATUS Status;\r
750 UINT32 Attribute;\r
751\r
752 Size = 0;\r
753\r
754 Status = EfiGetVariable (\r
755 (UINT16 *)VariableName,\r
756 VariableGuid,\r
757 &Attribute,\r
758 &Size,\r
759 NULL\r
760 );\r
761\r
762 if (Status == EFI_BUFFER_TOO_SMALL) {\r
763\r
764 Buffer = AllocatePool (Size);\r
765\r
766 ASSERT (Buffer != NULL);\r
767\r
768 Status = EfiGetVariable (\r
769 VariableName,\r
770 VariableGuid,\r
771 &Attribute,\r
772 &Size,\r
773 Buffer\r
774 );\r
775 \r
776 ASSERT_EFI_ERROR (Status);\r
777\r
778 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
779\r
780 Status = EfiSetVariable (\r
781 VariableName,\r
782 VariableGuid,\r
783 Attribute,\r
784 Size,\r
785 Buffer\r
786 );\r
787\r
788 FreePool (Buffer);\r
789 return Status;\r
790\r
791 } \r
792 \r
793 //\r
794 // If we drop to here, we don't have a Variable entry in\r
795 // the variable service yet. So, we will save the data\r
796 // in the PCD Database's volatile area.\r
797 //\r
798 return Status;\r
799}\r
800\r
801\r
802\r
803\r
804\r
805UINTN \r
806GetExPcdTokenNumber (\r
807 IN CONST EFI_GUID *Guid,\r
808 IN UINT32 ExTokenNumber\r
809 )\r
810{\r
811 UINT32 i;\r
812 DYNAMICEX_MAPPING *ExMap;\r
813 EFI_GUID *GuidTable;\r
814 EFI_GUID *MatchGuid;\r
815 UINTN MatchGuidIdx;\r
816\r
817 if (!PEI_DATABASE_EMPTY) {\r
818 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;\r
819 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;\r
820 \r
821 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
822 \r
823 if (MatchGuid != NULL) {\r
824\r
825 MatchGuidIdx = MatchGuid - GuidTable;\r
826 \r
827 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
828 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
829 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
830 return ExMap[i].LocalTokenNumber;\r
831\r
832 }\r
833 }\r
834 }\r
835 }\r
836 \r
837 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;\r
838 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;\r
839\r
840 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
841 //\r
842 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
843 // error in the BUILD system.\r
844 //\r
845 ASSERT (MatchGuid != NULL);\r
846\r
847 MatchGuidIdx = MatchGuid - GuidTable;\r
848 \r
849 for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {\r
850 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
851 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
852 return ExMap[i].LocalTokenNumber;\r
853 }\r
854 }\r
855\r
856 ASSERT (FALSE);\r
857\r
858 return 0;\r
859}\r
860\r
861\r
862\r
863SKU_ID *\r
864GetSkuIdArray (\r
865 IN UINTN LocalTokenNumberTableIdx,\r
866 IN BOOLEAN IsPeiPcd\r
867 )\r
868{\r
869 SKU_HEAD *SkuHead;\r
870 UINTN LocalTokenNumber;\r
871 UINT8 *Database;\r
872\r
873 if (IsPeiPcd) {\r
874 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
875 Database = (UINT8 *) &mPcdDatabase->PeiDb;\r
876 } else {\r
877 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];\r
878 Database = (UINT8 *) &mPcdDatabase->DxeDb;\r
879 }\r
880\r
881 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
882\r
883 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
884\r
885 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
886 \r
887}\r
888\r
889\r
890\r
891UINTN\r
892GetSizeTableIndexA (\r
893 IN UINTN LocalTokenNumberTableIdx,\r
894 IN UINT32 *LocalTokenNumberTable,\r
895 IN BOOLEAN IsPeiDb\r
896 )\r
897{\r
898 UINTN i;\r
899 UINTN SizeTableIdx;\r
900 UINTN LocalTokenNumber;\r
901 SKU_ID *SkuIdTable;\r
902 \r
903 SizeTableIdx = 0;\r
904\r
905 for (i=0; i<LocalTokenNumberTableIdx; i++) {\r
906 LocalTokenNumber = LocalTokenNumberTable[i];\r
907\r
908 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
909 //\r
910 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
911 // PCD entry.\r
912 //\r
913 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
914 //\r
915 // We have only one entry for VPD enabled PCD entry:\r
916 // 1) MAX Size.\r
917 // We consider current size is equal to MAX size.\r
918 //\r
919 SizeTableIdx++;\r
920 } else {\r
921 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
922 //\r
923 // We have only two entry for Non-Sku enabled PCD entry:\r
924 // 1) MAX SIZE\r
925 // 2) Current Size\r
926 //\r
927 SizeTableIdx += 2;\r
928 } else {\r
929 //\r
930 // We have these entry for SKU enabled PCD entry\r
931 // 1) MAX SIZE\r
932 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
933 //\r
934 SkuIdTable = GetSkuIdArray (i, IsPeiDb);\r
935 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
936 }\r
937 }\r
938 }\r
939\r
940 }\r
941\r
942 return SizeTableIdx;\r
943}\r
944\r
945\r
946\r
947\r
948UINTN\r
949GetSizeTableIndex (\r
950 IN UINTN LocalTokenNumberTableIdx,\r
951 IN BOOLEAN IsPeiDb\r
952 )\r
953{\r
954 UINT32 *LocalTokenNumberTable;\r
955 \r
956 if (IsPeiDb) {\r
957 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
958 } else {\r
959 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
960 }\r
961 return GetSizeTableIndexA (LocalTokenNumberTableIdx, \r
962 LocalTokenNumberTable,\r
963 IsPeiDb);\r
964}\r
965\r
966\r
967\r
968UINTN\r
969GetPtrTypeSize (\r
970 IN UINTN LocalTokenNumberTableIdx,\r
971 OUT UINTN *MaxSize\r
972 )\r
973{\r
974 INTN SizeTableIdx;\r
975 UINTN LocalTokenNumber;\r
976 SKU_ID *SkuIdTable;\r
977 SIZE_INFO *SizeTable;\r
978 UINTN i;\r
979 BOOLEAN IsPeiDb;\r
980 UINT32 *LocalTokenNumberTable;\r
981\r
982 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx < PEI_LOCAL_TOKEN_NUMBER);\r
983\r
984\r
985 if (IsPeiDb) {\r
986 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
987 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
988 } else {\r
989 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
990 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
991 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
992 }\r
993\r
994 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
995\r
996 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
997 \r
998 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
999\r
1000 *MaxSize = SizeTable[SizeTableIdx];\r
1001 //\r
1002 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1003 // PCD entry.\r
1004 //\r
1005 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
1006 //\r
1007 // We have only one entry for VPD enabled PCD entry:\r
1008 // 1) MAX Size.\r
1009 // We consider current size is equal to MAX size.\r
1010 //\r
1011 return *MaxSize;\r
1012 } else {\r
1013 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1014 //\r
1015 // We have only two entry for Non-Sku enabled PCD entry:\r
1016 // 1) MAX SIZE\r
1017 // 2) Current Size\r
1018 //\r
1019 return SizeTable[SizeTableIdx + 1];\r
1020 } else {\r
1021 //\r
1022 // We have these entry for SKU enabled PCD entry\r
1023 // 1) MAX SIZE\r
1024 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1025 //\r
1026 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
1027 for (i = 0; i < SkuIdTable[0]; i++) {\r
1028 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1029 return SizeTable[SizeTableIdx + 1 + i];\r
1030 }\r
1031 }\r
1032 return SizeTable[SizeTableIdx + 1];\r
1033 }\r
1034 }\r
1035}\r
1036\r
1037\r
1038\r
1039BOOLEAN\r
1040SetPtrTypeSize (\r
1041 IN UINTN LocalTokenNumberTableIdx,\r
1042 IN OUT UINTN *CurrentSize\r
1043 )\r
1044{\r
1045 INTN SizeTableIdx;\r
1046 UINTN LocalTokenNumber;\r
1047 SKU_ID *SkuIdTable;\r
1048 SIZE_INFO *SizeTable;\r
1049 UINTN i;\r
1050 UINTN MaxSize;\r
1051 BOOLEAN IsPeiDb;\r
1052 UINT32 *LocalTokenNumberTable;\r
1053\r
1054 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx < PEI_LOCAL_TOKEN_NUMBER);\r
1055\r
1056 if (IsPeiDb) {\r
1057 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1058 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1059 } else {\r
1060 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1061 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1062 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1063 }\r
1064\r
1065 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1066\r
1067 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1068 \r
1069 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1070\r
1071 MaxSize = SizeTable[SizeTableIdx];\r
1072 //\r
1073 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1074 // PCD entry.\r
1075 //\r
1076 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
1077 //\r
1078 // We shouldn't come here as we don't support SET for VPD\r
1079 //\r
1080 ASSERT (FALSE);\r
1081 return FALSE;\r
1082 } else {\r
1083 if ((*CurrentSize > MaxSize) ||\r
1084 (*CurrentSize == MAX_ADDRESS)) {\r
1085 *CurrentSize = MaxSize;\r
1086 return FALSE;\r
1087 } \r
1088 \r
1089 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1090 //\r
1091 // We have only two entry for Non-Sku enabled PCD entry:\r
1092 // 1) MAX SIZE\r
1093 // 2) Current Size\r
1094 //\r
1095 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1096 return TRUE;\r
1097 } else {\r
1098 //\r
1099 // We have these entry for SKU enabled PCD entry\r
1100 // 1) MAX SIZE\r
1101 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1102 //\r
1103 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
1104 for (i = 0; i < SkuIdTable[0]; i++) {\r
1105 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1106 SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;\r
1107 return TRUE;\r
1108 }\r
1109 }\r
1110 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1111 return TRUE;\r
1112 }\r
1113 }\r
1114}\r
1115\r