]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EdkModulePkg/Universal/PCD/Dxe/Service.c
In AsciiStrncmp(), if length=0, should return 0
[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 (TokenNumber, &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 (TokenNumber, 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 (TokenNumber, 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 //\r
666 // Bug Bug: Please implement this\r
667 //\r
668\r
669 case PCD_TYPE_DATA:\r
670 if (PtrType) {\r
671 if (SetPtrTypeSize (TokenNumber, Size)) {\r
672 CopyMem (InternalData, Data, *Size);\r
673 return EFI_SUCCESS;\r
674 } else {\r
675 return EFI_INVALID_PARAMETER;\r
676 }\r
677 }\r
678\r
679 switch (*Size) {\r
680 case sizeof(UINT8):\r
681 *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
682 return EFI_SUCCESS;\r
683\r
684 case sizeof(UINT16):\r
685 *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
686 return EFI_SUCCESS;\r
687\r
688 case sizeof(UINT32):\r
689 *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
690 return EFI_SUCCESS;\r
691\r
692 case sizeof(UINT64):\r
693 *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
694 return EFI_SUCCESS;\r
695\r
696 default:\r
697 ASSERT (FALSE);\r
698 return EFI_NOT_FOUND;\r
699 }\r
700\r
701 default:\r
702 ASSERT (FALSE);\r
703 break;\r
704 }\r
705 \r
706 ASSERT (FALSE);\r
707 return EFI_NOT_FOUND;\r
708}\r
709\r
710\r
711\r
712\r
713\r
714VOID *\r
715ExGetWorker (\r
716 IN CONST EFI_GUID *Guid,\r
717 IN UINTN ExTokenNumber,\r
718 IN UINTN GetSize\r
719 ) \r
720{\r
721 return GetWorker(GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber), GetSize);\r
722}\r
723\r
724\r
725\r
726\r
727EFI_STATUS\r
728ExSetValueWorker (\r
729 IN UINTN ExTokenNumber,\r
730 IN CONST EFI_GUID *Guid,\r
731 IN VOID *Data,\r
732 IN UINTN SetSize\r
733 )\r
734{\r
735 return ExSetWorker (ExTokenNumber, Guid, Data, &SetSize, FALSE);\r
736}\r
737\r
738\r
739EFI_STATUS\r
740ExSetWorker (\r
741 IN UINTN ExTokenNumber,\r
742 IN CONST EFI_GUID *Guid,\r
743 IN VOID *Data,\r
744 IN OUT UINTN *SetSize,\r
745 IN BOOLEAN PtrType\r
746 )\r
747{\r
748 UINTN TokenNumber;\r
749 \r
750 TokenNumber = GetExPcdTokenNumber (Guid, (UINT32) ExTokenNumber);\r
751\r
752 InvokeCallbackOnSet ((UINT32) ExTokenNumber, Guid, TokenNumber, Data, *SetSize);\r
753\r
754 return SetWorker (TokenNumber, Data, SetSize, PtrType);\r
755\r
756}\r
757\r
758\r
759\r
760\r
761EFI_STATUS\r
762SetHiiVariable (\r
763 IN EFI_GUID *VariableGuid,\r
764 IN UINT16 *VariableName,\r
765 IN CONST VOID *Data,\r
766 IN UINTN DataSize,\r
767 IN UINTN Offset\r
768 )\r
769{\r
770 UINTN Size;\r
771 VOID *Buffer;\r
772 EFI_STATUS Status;\r
773 UINT32 Attribute;\r
774\r
775 Size = 0;\r
776\r
777 Status = gRT->GetVariable (\r
778 (UINT16 *)VariableName,\r
779 VariableGuid,\r
780 &Attribute,\r
781 &Size,\r
782 NULL\r
783 );\r
784\r
785 if (Status == EFI_BUFFER_TOO_SMALL) {\r
786\r
787 Buffer = AllocatePool (Size);\r
788\r
789 ASSERT (Buffer != NULL);\r
790\r
791 Status = gRT->GetVariable (\r
792 VariableName,\r
793 VariableGuid,\r
794 &Attribute,\r
795 &Size,\r
796 Buffer\r
797 );\r
798 \r
799 ASSERT_EFI_ERROR (Status);\r
800\r
801 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
802\r
803 Status = gRT->SetVariable (\r
804 VariableName,\r
805 VariableGuid,\r
806 Attribute,\r
807 Size,\r
808 Buffer\r
809 );\r
810\r
811 FreePool (Buffer);\r
812 return Status;\r
813\r
814 } \r
815 \r
816 //\r
817 // If we drop to here, we don't have a Variable entry in\r
818 // the variable service yet. So, we will save the data\r
819 // in the PCD Database's volatile area.\r
820 //\r
821 return Status;\r
822}\r
823\r
824\r
825\r
826\r
827\r
828UINTN \r
829GetExPcdTokenNumber (\r
830 IN CONST EFI_GUID *Guid,\r
831 IN UINT32 ExTokenNumber\r
832 )\r
833{\r
834 UINT32 i;\r
835 DYNAMICEX_MAPPING *ExMap;\r
836 EFI_GUID *GuidTable;\r
837 EFI_GUID *MatchGuid;\r
838 UINTN MatchGuidIdx;\r
839\r
840 if (!PEI_DATABASE_EMPTY) {\r
841 ExMap = mPcdDatabase->PeiDb.Init.ExMapTable;\r
842 GuidTable = mPcdDatabase->PeiDb.Init.GuidTable;\r
843 \r
844 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
845 \r
846 if (MatchGuid != NULL) {\r
847\r
848 MatchGuidIdx = MatchGuid - GuidTable;\r
849 \r
850 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
851 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
852 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
853 return ExMap[i].LocalTokenNumber;\r
854\r
855 }\r
856 }\r
857 }\r
858 }\r
859 \r
860 ExMap = mPcdDatabase->DxeDb.Init.ExMapTable;\r
861 GuidTable = mPcdDatabase->DxeDb.Init.GuidTable;\r
862\r
863 MatchGuid = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
864 //\r
865 // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
866 // error in the BUILD system.\r
867 //\r
868 ASSERT (MatchGuid != NULL);\r
869\r
870 MatchGuidIdx = MatchGuid - GuidTable;\r
871 \r
872 for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {\r
873 if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
874 (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
875 return ExMap[i].LocalTokenNumber;\r
876 }\r
877 }\r
878\r
879 ASSERT (FALSE);\r
880\r
881 return 0;\r
882}\r
883\r
884\r
885\r
886SKU_ID *\r
887GetSkuIdArray (\r
888 IN UINTN LocalTokenNumberTableIdx,\r
889 IN BOOLEAN IsPeiPcd\r
890 )\r
891{\r
892 SKU_HEAD *SkuHead;\r
893 UINTN LocalTokenNumber;\r
894 UINT8 *Database;\r
895\r
896 if (IsPeiPcd) {\r
897 LocalTokenNumber = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
898 Database = (UINT8 *) &mPcdDatabase->PeiDb;\r
899 } else {\r
900 LocalTokenNumber = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable[LocalTokenNumberTableIdx - PEI_LOCAL_TOKEN_NUMBER];\r
901 Database = (UINT8 *) &mPcdDatabase->DxeDb;\r
902 }\r
903\r
904 ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
905\r
906 SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
907\r
908 return (SKU_ID *) (Database + SkuHead->SkuIdTableOffset);\r
909 \r
910}\r
911\r
912\r
913\r
914UINTN\r
915GetSizeTableIndexA (\r
916 IN UINTN LocalTokenNumberTableIdx,\r
917 IN UINT32 *LocalTokenNumberTable,\r
918 IN BOOLEAN IsPeiDb\r
919 )\r
920{\r
921 UINTN i;\r
922 UINTN SizeTableIdx;\r
923 UINTN LocalTokenNumber;\r
924 SKU_ID *SkuIdTable;\r
925 \r
926 SizeTableIdx = 0;\r
927\r
928 for (i=0; i<LocalTokenNumberTableIdx; i++) {\r
929 LocalTokenNumber = LocalTokenNumberTable[i];\r
930\r
931 if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
932 //\r
933 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
934 // PCD entry.\r
935 //\r
936 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
937 //\r
938 // We have only one entry for VPD enabled PCD entry:\r
939 // 1) MAX Size.\r
940 // We consider current size is equal to MAX size.\r
941 //\r
942 SizeTableIdx++;\r
943 } else {\r
944 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
945 //\r
946 // We have only two entry for Non-Sku enabled PCD entry:\r
947 // 1) MAX SIZE\r
948 // 2) Current Size\r
949 //\r
950 SizeTableIdx += 2;\r
951 } else {\r
952 //\r
953 // We have these entry for SKU enabled PCD entry\r
954 // 1) MAX SIZE\r
955 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
956 //\r
957 SkuIdTable = GetSkuIdArray (i, IsPeiDb);\r
958 SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
959 }\r
960 }\r
961 }\r
962\r
963 }\r
964\r
965 return SizeTableIdx;\r
966}\r
967\r
968\r
969\r
970\r
971UINTN\r
972GetSizeTableIndex (\r
973 IN UINTN LocalTokenNumberTableIdx,\r
974 IN BOOLEAN IsPeiDb\r
975 )\r
976{\r
977 UINT32 *LocalTokenNumberTable;\r
978 \r
979 if (IsPeiDb) {\r
980 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
981 } else {\r
982 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
983 }\r
984 return GetSizeTableIndexA (LocalTokenNumberTableIdx, \r
985 LocalTokenNumberTable,\r
986 IsPeiDb);\r
987}\r
988\r
989\r
990\r
991UINTN\r
992GetPtrTypeSize (\r
993 IN UINTN LocalTokenNumberTableIdx,\r
994 OUT UINTN *MaxSize\r
995 )\r
996{\r
997 INTN SizeTableIdx;\r
998 UINTN LocalTokenNumber;\r
999 SKU_ID *SkuIdTable;\r
1000 SIZE_INFO *SizeTable;\r
1001 UINTN i;\r
1002 BOOLEAN IsPeiDb;\r
1003 UINT32 *LocalTokenNumberTable;\r
1004\r
1005 // EBC compiler is very choosy. It may report warning about comparison\r
1006 // between UINTN and 0 . So we add 1 in each size of the \r
1007 // comparison.\r
1008 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1009\r
1010\r
1011 if (IsPeiDb) {\r
1012 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1013 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1014 } else {\r
1015 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1016 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1017 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1018 }\r
1019\r
1020 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1021\r
1022 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1023 \r
1024 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1025\r
1026 *MaxSize = SizeTable[SizeTableIdx];\r
1027 //\r
1028 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1029 // PCD entry.\r
1030 //\r
1031 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
1032 //\r
1033 // We have only one entry for VPD enabled PCD entry:\r
1034 // 1) MAX Size.\r
1035 // We consider current size is equal to MAX size.\r
1036 //\r
1037 return *MaxSize;\r
1038 } else {\r
1039 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1040 //\r
1041 // We have only two entry for Non-Sku enabled PCD entry:\r
1042 // 1) MAX SIZE\r
1043 // 2) Current Size\r
1044 //\r
1045 return SizeTable[SizeTableIdx + 1];\r
1046 } else {\r
1047 //\r
1048 // We have these entry for SKU enabled PCD entry\r
1049 // 1) MAX SIZE\r
1050 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1051 //\r
1052 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
1053 for (i = 0; i < SkuIdTable[0]; i++) {\r
1054 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1055 return SizeTable[SizeTableIdx + 1 + i];\r
1056 }\r
1057 }\r
1058 return SizeTable[SizeTableIdx + 1];\r
1059 }\r
1060 }\r
1061}\r
1062\r
1063\r
1064\r
1065BOOLEAN\r
1066SetPtrTypeSize (\r
1067 IN UINTN LocalTokenNumberTableIdx,\r
1068 IN OUT UINTN *CurrentSize\r
1069 )\r
1070{\r
1071 INTN SizeTableIdx;\r
1072 UINTN LocalTokenNumber;\r
1073 SKU_ID *SkuIdTable;\r
1074 SIZE_INFO *SizeTable;\r
1075 UINTN i;\r
1076 UINTN MaxSize;\r
1077 BOOLEAN IsPeiDb;\r
1078 UINT32 *LocalTokenNumberTable;\r
1079\r
1080 // EBC compiler is very choosy. It may report warning about comparison\r
1081 // between UINTN and 0 . So we add 1 in each size of the \r
1082 // comparison.\r
1083 IsPeiDb = (BOOLEAN) (LocalTokenNumberTableIdx + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
1084\r
1085 if (IsPeiDb) {\r
1086 LocalTokenNumberTable = mPcdDatabase->PeiDb.Init.LocalTokenNumberTable;\r
1087 SizeTable = mPcdDatabase->PeiDb.Init.SizeTable;\r
1088 } else {\r
1089 LocalTokenNumberTableIdx -= PEI_LOCAL_TOKEN_NUMBER;\r
1090 LocalTokenNumberTable = mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
1091 SizeTable = mPcdDatabase->DxeDb.Init.SizeTable;\r
1092 }\r
1093\r
1094 LocalTokenNumber = LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
1095\r
1096 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);\r
1097 \r
1098 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, IsPeiDb);\r
1099\r
1100 MaxSize = SizeTable[SizeTableIdx];\r
1101 //\r
1102 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
1103 // PCD entry.\r
1104 //\r
1105 if (LocalTokenNumber & PCD_TYPE_VPD) {\r
1106 //\r
1107 // We shouldn't come here as we don't support SET for VPD\r
1108 //\r
1109 ASSERT (FALSE);\r
1110 return FALSE;\r
1111 } else {\r
1112 if ((*CurrentSize > MaxSize) ||\r
1113 (*CurrentSize == MAX_ADDRESS)) {\r
1114 *CurrentSize = MaxSize;\r
1115 return FALSE;\r
1116 } \r
1117 \r
1118 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
1119 //\r
1120 // We have only two entry for Non-Sku enabled PCD entry:\r
1121 // 1) MAX SIZE\r
1122 // 2) Current Size\r
1123 //\r
1124 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1125 return TRUE;\r
1126 } else {\r
1127 //\r
1128 // We have these entry for SKU enabled PCD entry\r
1129 // 1) MAX SIZE\r
1130 // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
1131 //\r
1132 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, IsPeiDb);\r
1133 for (i = 0; i < SkuIdTable[0]; i++) {\r
1134 if (SkuIdTable[1 + i] == mPcdDatabase->PeiDb.Init.SystemSkuId) {\r
1135 SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;\r
1136 return TRUE;\r
1137 }\r
1138 }\r
1139 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
1140 return TRUE;\r
1141 }\r
1142 }\r
1143}\r
1144\r