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