bccd0a600add0835167fa97e99b252cde748d060
[people/mcb30/edk2.git] / edk2 / EdkModulePkg / Universal / PCD / Dxe / Service.c
1 /** @file\r
2 Private functions used by PCD DXE driver.s\r
3 \r
4 Copyright (c) 2006, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution.  The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 \r
14 Module 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
25 PCD_DATABASE * mPcdDatabase;\r
26 \r
27 LIST_ENTRY mCallbackFnTable[PCD_TOTAL_TOKEN_NUMBER];\r
28 \r
29 VOID *\r
30 GetWorker (\r
31   PCD_TOKEN_NUMBER  TokenNumber,\r
32   UINTN             GetSize\r
33   )\r
34 {\r
35   UINT32              *LocalTokenNumberTable;\r
36   UINT16              *SizeTable;\r
37   BOOLEAN             IsPeiDb;\r
38   UINTN               Size;\r
39   UINT32              Offset;\r
40   EFI_GUID            *GuidTable;\r
41   UINT16              *StringTable;\r
42   EFI_GUID            *Guid;\r
43   UINT16              *Name;\r
44   VARIABLE_HEAD       *VariableHead;\r
45   EFI_STATUS          Status;\r
46   UINTN               DataSize;\r
47   VOID                *Data;\r
48   VPD_HEAD            *VpdHead;\r
49   UINT8               *PcdDb;\r
50   UINT16              StringTableIdx;      \r
51   UINT32              LocalTokenNumber;\r
52 \r
53 \r
54   ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER);\r
55 \r
56   Size = DxePcdGetSize (TokenNumber);\r
57   ASSERT (GetSize == Size || GetSize == 0);\r
58 \r
59   \r
60   IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE;\r
61 \r
62   LocalTokenNumberTable  = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
63                                      mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
64 \r
65   SizeTable              = IsPeiDb ? mPcdDatabase->PeiDb.Init.SizeTable: \r
66                                      mPcdDatabase->DxeDb.Init.SizeTable;\r
67 \r
68   TokenNumber            = IsPeiDb ? TokenNumber :\r
69                                      TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
70 \r
71   LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
72   \r
73   if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
74     LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb);\r
75   }\r
76 \r
77   PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
78   StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :\r
79                           mPcdDatabase->DxeDb.Init.StringTable;\r
80   \r
81   Offset     = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
82   \r
83   switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
84     case PCD_TYPE_VPD:\r
85       VpdHead = (VPD_HEAD *) ((UINT8 *) PcdDb + Offset);\r
86       return (VOID *) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);\r
87       \r
88     case PCD_TYPE_HII:\r
89       GuidTable   = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :\r
90                               mPcdDatabase->DxeDb.Init.GuidTable;\r
91                               \r
92       VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
93       \r
94       Guid = &(GuidTable[VariableHead->GuidTableIndex]);\r
95       Name = &(StringTable[VariableHead->StringIndex]);\r
96 \r
97       Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
98       ASSERT_EFI_ERROR (Status);\r
99       ASSERT (DataSize >= (UINTN) (VariableHead->Offset + Size));\r
100 \r
101       return (UINT8 *) Data + VariableHead->Offset;\r
102 \r
103     case PCD_TYPE_STRING:\r
104       StringTableIdx = (UINT16) *((UINT8 *) PcdDb + Offset);\r
105       return (VOID *) &StringTable[StringTableIdx];\r
106 \r
107     case PCD_TYPE_DATA:\r
108       return (VOID *) ((UINT8 *) PcdDb + Offset);\r
109       break;\r
110 \r
111     default:\r
112       ASSERT (FALSE);\r
113       break;\r
114       \r
115   }\r
116 \r
117   ASSERT (FALSE);\r
118       \r
119   return NULL;\r
120   \r
121 }\r
122 \r
123 \r
124 \r
125 EFI_STATUS\r
126 DxeRegisterCallBackWorker (\r
127   IN  PCD_TOKEN_NUMBER        TokenNumber,\r
128   IN  CONST GUID              *Guid, OPTIONAL\r
129   IN  PCD_PROTOCOL_CALLBACK   CallBackFunction\r
130 )\r
131 {\r
132   CALLBACK_FN_ENTRY       *FnTableEntry;\r
133   LIST_ENTRY              *ListHead;\r
134   LIST_ENTRY              *ListNode;\r
135 \r
136   if (Guid != NULL) {\r
137     TokenNumber = GetExPcdTokenNumber (Guid, TokenNumber);\r
138   }\r
139 \r
140   ListHead = &mCallbackFnTable[TokenNumber];\r
141   ListNode = GetFirstNode (ListHead);\r
142 \r
143   while (ListNode != ListHead) {\r
144     FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
145 \r
146     if (FnTableEntry->CallbackFn == CallBackFunction) {\r
147       //\r
148       // We only allow a Callback function to be register once\r
149       // for a TokenNumber. So just return EFI_SUCCESS\r
150       //\r
151       return EFI_SUCCESS;\r
152     }\r
153     ListNode = GetNextNode (ListHead, ListNode);\r
154   }\r
155 \r
156   FnTableEntry = AllocatePool (sizeof(CALLBACK_FN_ENTRY));\r
157   ASSERT (FnTableEntry != NULL);\r
158 \r
159   FnTableEntry->CallbackFn = CallBackFunction;\r
160   InsertTailList (ListHead, &FnTableEntry->Node);\r
161   \r
162   return EFI_SUCCESS;\r
163 }\r
164 \r
165 \r
166 \r
167 \r
168 EFI_STATUS\r
169 DxeUnRegisterCallBackWorker (\r
170   IN  PCD_TOKEN_NUMBER        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, TokenNumber);\r
181   }\r
182 \r
183   ListHead = &mCallbackFnTable[TokenNumber];\r
184   ListNode = GetFirstNode (ListHead);\r
185 \r
186   while (ListNode != ListHead) {\r
187     FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
188 \r
189     if (FnTableEntry->CallbackFn == CallBackFunction) {\r
190       //\r
191       // We only allow a Callback function to be register once\r
192       // for a TokenNumber. So we can safely remove the Node from\r
193       // the Link List and return EFI_SUCCESS.\r
194       //\r
195       RemoveEntryList (ListNode);\r
196       FreePool (FnTableEntry);\r
197       \r
198       return EFI_SUCCESS;\r
199     }\r
200     ListNode = GetNextNode (ListHead, ListNode);\r
201   }\r
202 \r
203   return EFI_INVALID_PARAMETER;\r
204 }\r
205 \r
206 \r
207 \r
208 PCD_TOKEN_NUMBER\r
209 ExGetNextTokeNumber (\r
210   IN CONST EFI_GUID         *Guid,\r
211   IN PCD_TOKEN_NUMBER       TokenNumber,\r
212   IN EFI_GUID               *GuidTable,\r
213   IN UINTN                  SizeOfGuidTable,\r
214   IN DYNAMICEX_MAPPING      *ExMapTable,\r
215   IN UINTN                  SizeOfExMapTable\r
216   )\r
217 {\r
218   EFI_GUID         *MatchGuid;\r
219   UINTN            Idx;\r
220   UINTN            GuidTableIdx;\r
221   BOOLEAN          Found;\r
222 \r
223   MatchGuid = ScanGuid (GuidTable, SizeOfGuidTable, Guid);\r
224   if (MatchGuid == NULL) {\r
225     return PCD_INVALID_TOKEN_NUMBER;\r
226   }\r
227 \r
228   Found = FALSE;\r
229   GuidTableIdx = MatchGuid - GuidTable;\r
230   for (Idx = 0; Idx < SizeOfExMapTable; Idx++) {\r
231     if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {\r
232       Found = TRUE;\r
233       break;\r
234     }\r
235   }\r
236 \r
237   if (Found) {\r
238     if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
239       return ExMapTable[Idx].ExTokenNumber;\r
240     }\r
241     \r
242     for ( ; Idx < SizeOfExMapTable; Idx++) {\r
243       if (ExMapTable[Idx].ExTokenNumber == TokenNumber) {\r
244         Idx++;\r
245         if (Idx == SizeOfExMapTable) {\r
246           //\r
247           // Exceed the length of ExMap Table\r
248           //\r
249           return PCD_INVALID_TOKEN_NUMBER;\r
250         } else if (ExMapTable[Idx].ExGuidIndex == GuidTableIdx) {\r
251           //\r
252           // Found the next match\r
253           //\r
254           return ExMapTable[Idx].ExTokenNumber;\r
255         } else {\r
256           //\r
257           // Guid has been changed. It is the next Token Space Guid.\r
258           // We should flag no more TokenNumber.\r
259           //\r
260           return PCD_INVALID_TOKEN_NUMBER;\r
261         }\r
262       }\r
263     }\r
264   }\r
265   \r
266   return PCD_INVALID_TOKEN_NUMBER;\r
267 }\r
268   \r
269 \r
270 \r
271 \r
272 VOID\r
273 BuildPcdDxeDataBase (\r
274   VOID\r
275 )\r
276 {\r
277   PEI_PCD_DATABASE    *PeiDatabase;\r
278   EFI_HOB_GUID_TYPE   *GuidHob;\r
279   UINTN               Idx;\r
280 \r
281   mPcdDatabase = AllocateZeroPool (sizeof(PCD_DATABASE));\r
282   ASSERT (mPcdDatabase != NULL);\r
283 \r
284   GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
285 \r
286   if (GuidHob != NULL) {\r
287 \r
288     //\r
289     // We will copy over the PEI phase's PCD Database.\r
290     // \r
291     // If no PEIMs use dynamic Pcd Entry, the Pcd Service PEIM\r
292     // should not be included at all. So the GuidHob could\r
293     // be NULL. If it is NULL, we just copy over the DXE Default\r
294     // Value to PCD Database.\r
295     //\r
296     \r
297     PeiDatabase = (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
298     //\r
299     // Copy PCD Entries refereneced in PEI phase to PCD DATABASE\r
300     //\r
301     CopyMem (&mPcdDatabase->PeiDb, PeiDatabase, sizeof (PEI_PCD_DATABASE));\r
302   }\r
303 \r
304   //\r
305   // Copy PCD Entries with default value to PCD DATABASE\r
306   //\r
307   CopyMem (&mPcdDatabase->DxeDb.Init, &gDXEPcdDbInit, sizeof(DXE_PCD_DATABASE_INIT));\r
308 \r
309 \r
310   //\r
311   // Initialized the Callback Function Table\r
312   //\r
313   for (Idx = 0; Idx < PCD_TOTAL_TOKEN_NUMBER; Idx++) {\r
314     InitializeListHead (&mCallbackFnTable[Idx]);\r
315   }\r
316     \r
317   return;\r
318 }\r
319 \r
320 \r
321 \r
322 EFI_STATUS\r
323 GetHiiVariable (\r
324   IN  EFI_GUID      *VariableGuid,\r
325   IN  UINT16        *VariableName,\r
326   OUT VOID          ** VariableData,\r
327   OUT UINTN         *VariableSize\r
328   )\r
329 {\r
330   UINTN      Size;\r
331   EFI_STATUS Status;\r
332   VOID       *Buffer;\r
333 \r
334   Status = EfiGetVariable (\r
335     (UINT16 *)VariableName,\r
336     VariableGuid,\r
337     NULL,\r
338     &Size,\r
339     NULL\r
340     );\r
341   ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
342 \r
343   Buffer = AllocatePool (Size);\r
344 \r
345   ASSERT (Buffer != NULL);\r
346 \r
347   Status = EfiGetVariable (\r
348     VariableName,\r
349     VariableGuid,\r
350     NULL,\r
351     &Size,\r
352     Buffer\r
353     );\r
354 \r
355   return Status;\r
356 \r
357 }\r
358 \r
359 \r
360 UINT32\r
361 GetSkuEnabledTokenNumber (\r
362   UINT32    LocalTokenNumber,\r
363   UINTN     Size,\r
364   BOOLEAN   IsPeiDb\r
365   ) \r
366 {\r
367   SKU_HEAD              *SkuHead;\r
368   SKU_ID                *SkuIdTable;\r
369   INTN                  i;\r
370   UINT8                 *Value;\r
371   SKU_ID                *PhaseSkuIdTable;\r
372   UINT8                 *PcdDb;\r
373 \r
374   ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
375 \r
376   PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
377 \r
378   SkuHead     = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
379   Value       = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
380 \r
381   PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
382                               mPcdDatabase->DxeDb.Init.SkuIdTable;\r
383                               \r
384   SkuIdTable  = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
385         \r
386   for (i = 0; i < SkuIdTable[0]; i++) {\r
387     if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {\r
388       break;\r
389     }\r
390   }\r
391   ASSERT (i < SkuIdTable[0]);\r
392 \r
393   switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
394     case PCD_TYPE_VPD:\r
395       Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);\r
396       return ((Value - PcdDb) | PCD_TYPE_VPD);\r
397 \r
398     case PCD_TYPE_HII:\r
399       Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);\r
400       return ((Value - PcdDb) | PCD_TYPE_HII);\r
401       \r
402     case PCD_TYPE_DATA:\r
403       Value += Size * i;\r
404       return (Value - PcdDb);\r
405       \r
406     default:\r
407       ASSERT (FALSE);\r
408   }\r
409 \r
410   ASSERT (FALSE);\r
411 \r
412   return 0;\r
413   \r
414 }\r
415 \r
416 \r
417 \r
418 \r
419 \r
420 VOID\r
421 InvokeCallbackOnSet (\r
422   UINT32            ExTokenNumber,\r
423   CONST EFI_GUID    *Guid, OPTIONAL\r
424   UINTN             TokenNumber,\r
425   VOID              *Data,\r
426   UINTN             Size\r
427   )\r
428 {\r
429   CALLBACK_FN_ENTRY       *FnTableEntry;\r
430   LIST_ENTRY              *ListHead;\r
431   LIST_ENTRY              *ListNode;\r
432 \r
433   ListHead = &mCallbackFnTable[TokenNumber];\r
434   ListNode = GetFirstNode (ListHead);\r
435 \r
436   while (ListNode != ListHead) {\r
437     FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
438 \r
439     FnTableEntry->CallbackFn(Guid, \r
440                     (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
441                     Data,\r
442                     Size);\r
443     \r
444     ListNode = GetNextNode (ListHead, ListNode);\r
445   }\r
446   \r
447   return;\r
448 }\r
449 \r
450 \r
451 \r
452 \r
453 EFI_STATUS\r
454 SetWorker (\r
455   PCD_TOKEN_NUMBER        TokenNumber,\r
456   VOID                    *Data,\r
457   UINTN                   Size,\r
458   BOOLEAN                 PtrType\r
459   )\r
460 {\r
461   UINT32              *LocalTokenNumberTable;\r
462   BOOLEAN             IsPeiDb;\r
463   UINT32              LocalTokenNumber;\r
464   EFI_GUID            *GuidTable;\r
465   UINT16              *StringTable;\r
466   EFI_GUID            *Guid;\r
467   UINT16              *Name;\r
468   VOID                *InternalData;\r
469   VARIABLE_HEAD       *VariableHead;\r
470   UINTN               Offset;\r
471   UINT8               *PcdDb;\r
472 \r
473 \r
474   ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER);\r
475 \r
476   if (PtrType) {\r
477     ASSERT (Size <= DxePcdGetSize (TokenNumber));\r
478   } else {\r
479     ASSERT (Size == DxePcdGetSize (TokenNumber));\r
480   }\r
481   \r
482   IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE;\r
483 \r
484   LocalTokenNumberTable  = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
485                                      mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
486 \r
487   if ((TokenNumber < PEI_NEX_TOKEN_NUMBER) ||\r
488       (TokenNumber >= PEI_LOCAL_TOKEN_NUMBER || TokenNumber < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER))) {\r
489     InvokeCallbackOnSet (0, NULL, TokenNumber, Data, Size);\r
490   }\r
491 \r
492   TokenNumber = IsPeiDb ? TokenNumber\r
493                         : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
494 \r
495   LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
496   \r
497   if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
498     LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb);\r
499   }\r
500 \r
501   Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
502 \r
503   PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
504 \r
505   StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :\r
506                           mPcdDatabase->DxeDb.Init.StringTable;\r
507   \r
508   InternalData = PcdDb + Offset;\r
509 \r
510   switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
511     case PCD_TYPE_VPD:\r
512       ASSERT (FALSE);\r
513       return EFI_INVALID_PARAMETER;\r
514     \r
515     case PCD_TYPE_STRING:\r
516       CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, Size);\r
517       break;\r
518 \r
519     case PCD_TYPE_HII:\r
520       //\r
521       // Bug Bug: Please implement this\r
522       //\r
523       GuidTable   = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :\r
524                               mPcdDatabase->DxeDb.Init.GuidTable;\r
525                               \r
526       VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
527       \r
528       Guid = &(GuidTable[VariableHead->GuidTableIndex]);\r
529       Name = &(StringTable[VariableHead->StringIndex]);\r
530 \r
531       return EFI_SUCCESS;\r
532 \r
533     case PCD_TYPE_DATA:\r
534       if (PtrType) {\r
535         CopyMem (InternalData, Data, Size);\r
536         return EFI_SUCCESS;\r
537       }\r
538 \r
539       switch (Size) {\r
540         case sizeof(UINT8):\r
541           *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
542           return EFI_SUCCESS;\r
543 \r
544         case sizeof(UINT16):\r
545           *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
546           return EFI_SUCCESS;\r
547 \r
548         case sizeof(UINT32):\r
549           *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
550           return EFI_SUCCESS;\r
551 \r
552         case sizeof(UINT64):\r
553           *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
554           return EFI_SUCCESS;\r
555 \r
556         default:\r
557           ASSERT (FALSE);\r
558           return EFI_NOT_FOUND;\r
559       }\r
560 \r
561     default:\r
562       ASSERT (FALSE);\r
563       break;\r
564     }\r
565       \r
566   ASSERT (FALSE);\r
567   return EFI_NOT_FOUND;\r
568 }\r
569 \r
570 \r
571 \r
572 \r
573 \r
574 VOID *\r
575 ExGetWorker (\r
576   IN CONST EFI_GUID         *Guid,\r
577   IN UINTN                  ExTokenNumber,\r
578   IN UINTN                  GetSize\r
579   ) \r
580 {\r
581   return GetWorker(GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);\r
582 }\r
583 \r
584 \r
585 \r
586 \r
587 \r
588 EFI_STATUS\r
589 ExSetWorker (\r
590   IN PCD_TOKEN_NUMBER     ExTokenNumber,\r
591   IN CONST EFI_GUID       *Guid,\r
592   VOID                    *Data,\r
593   UINTN                   SetSize,\r
594   BOOLEAN                 PtrType\r
595   )\r
596 {\r
597   PCD_TOKEN_NUMBER        TokenNumber;\r
598   \r
599   TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
600 \r
601   InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, SetSize);\r
602 \r
603   SetWorker (TokenNumber, Data, SetSize, PtrType);\r
604 \r
605   return EFI_SUCCESS;\r
606   \r
607 }\r
608 \r
609 \r
610 \r
611 \r
612 EFI_STATUS\r
613 SetHiiVariable (\r
614   IN  EFI_GUID     *VariableGuid,\r
615   IN  UINT16       *VariableName,\r
616   IN  CONST VOID   *Data,\r
617   IN  UINTN        DataSize,\r
618   IN  UINTN        Offset\r
619   )\r
620 {\r
621   UINTN       Size;\r
622   VOID        *Buffer;\r
623   EFI_STATUS  Status;\r
624   UINT32      Attribute;\r
625 \r
626   Size = 0;\r
627 \r
628   Status = EfiGetVariable (\r
629     (UINT16 *)VariableName,\r
630     VariableGuid,\r
631     &Attribute,\r
632     &Size,\r
633     NULL\r
634     );\r
635 \r
636   ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
637 \r
638   Buffer = AllocatePool (Size);\r
639 \r
640   ASSERT (Buffer != NULL);\r
641 \r
642   Status = EfiGetVariable (\r
643     VariableName,\r
644     VariableGuid,\r
645     &Attribute,\r
646     &Size,\r
647     Buffer\r
648     );\r
649 \r
650 \r
651   CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
652 \r
653   return EfiSetVariable (\r
654     VariableName,\r
655     VariableGuid,\r
656     Attribute,\r
657     Size,\r
658     Buffer\r
659     );\r
660 \r
661 }\r
662 \r
663 \r
664 \r
665 \r
666 \r
667 PCD_TOKEN_NUMBER\r
668 GetExPcdTokenNumber (\r
669   IN CONST EFI_GUID             *Guid,\r
670   IN PCD_TOKEN_NUMBER           ExTokenNumber\r
671   )\r
672 {\r
673   UINT32              i;\r
674   DYNAMICEX_MAPPING   *ExMap;\r
675   EFI_GUID            *GuidTable;\r
676   EFI_GUID            *MatchGuid;\r
677   UINTN               MatchGuidIdx;\r
678 \r
679   ExMap       = mPcdDatabase->PeiDb.Init.ExMapTable;\r
680   GuidTable   = mPcdDatabase->PeiDb.Init.GuidTable;\r
681   \r
682   MatchGuid   = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
683   ASSERT (MatchGuid != NULL);\r
684 \r
685   MatchGuidIdx = MatchGuid - GuidTable;\r
686   \r
687   for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
688     if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
689         (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
690         return ExMap[i].LocalTokenNumber;\r
691 \r
692     }\r
693   }\r
694   \r
695   ExMap       = mPcdDatabase->DxeDb.Init.ExMapTable;\r
696   GuidTable   = mPcdDatabase->DxeDb.Init.GuidTable;\r
697 \r
698   MatchGuid   = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
699   ASSERT (MatchGuid != NULL);\r
700 \r
701   MatchGuidIdx = MatchGuid - GuidTable;\r
702   \r
703   for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {\r
704     if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
705          (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
706         return ExMap[i].LocalTokenNumber + PEI_LOCAL_TOKEN_NUMBER;\r
707     }\r
708   }\r
709 \r
710   ASSERT (FALSE);\r
711 \r
712   return 0;\r
713 }\r
714 \r