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