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