Make the EdkMoudlePkg build by allocate mCallbackFnTable at runtime as PCD_TOTAL_TOKE...
[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;\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 \r
314   if (PCD_TOTAL_TOKEN_NUMBER != 0) {\r
315     mCallbackFnTable = AllocateZeroPool (PCD_TOTAL_TOKEN_NUMBER);\r
316   }\r
317   \r
318   for (Idx = 0; Idx < PCD_TOTAL_TOKEN_NUMBER; Idx++) {\r
319     InitializeListHead (&mCallbackFnTable[Idx]);\r
320   }\r
321     \r
322   return;\r
323 }\r
324 \r
325 \r
326 \r
327 EFI_STATUS\r
328 GetHiiVariable (\r
329   IN  EFI_GUID      *VariableGuid,\r
330   IN  UINT16        *VariableName,\r
331   OUT VOID          ** VariableData,\r
332   OUT UINTN         *VariableSize\r
333   )\r
334 {\r
335   UINTN      Size;\r
336   EFI_STATUS Status;\r
337   VOID       *Buffer;\r
338 \r
339   Status = EfiGetVariable (\r
340     (UINT16 *)VariableName,\r
341     VariableGuid,\r
342     NULL,\r
343     &Size,\r
344     NULL\r
345     );\r
346   ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
347 \r
348   Buffer = AllocatePool (Size);\r
349 \r
350   ASSERT (Buffer != NULL);\r
351 \r
352   Status = EfiGetVariable (\r
353     VariableName,\r
354     VariableGuid,\r
355     NULL,\r
356     &Size,\r
357     Buffer\r
358     );\r
359 \r
360   return Status;\r
361 \r
362 }\r
363 \r
364 \r
365 UINT32\r
366 GetSkuEnabledTokenNumber (\r
367   UINT32    LocalTokenNumber,\r
368   UINTN     Size,\r
369   BOOLEAN   IsPeiDb\r
370   ) \r
371 {\r
372   SKU_HEAD              *SkuHead;\r
373   SKU_ID                *SkuIdTable;\r
374   INTN                  i;\r
375   UINT8                 *Value;\r
376   SKU_ID                *PhaseSkuIdTable;\r
377   UINT8                 *PcdDb;\r
378 \r
379   ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
380 \r
381   PcdDb = IsPeiDb ? (UINT8 *) &mPcdDatabase->PeiDb : (UINT8 *) &mPcdDatabase->DxeDb;\r
382 \r
383   SkuHead     = (SKU_HEAD *) (PcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
384   Value       = (UINT8 *) (PcdDb + SkuHead->SkuDataStartOffset); \r
385 \r
386   PhaseSkuIdTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.SkuIdTable :\r
387                               mPcdDatabase->DxeDb.Init.SkuIdTable;\r
388                               \r
389   SkuIdTable  = &PhaseSkuIdTable[SkuHead->SkuIdTableOffset];\r
390         \r
391   for (i = 0; i < SkuIdTable[0]; i++) {\r
392     if (mPcdDatabase->PeiDb.Init.SystemSkuId == SkuIdTable[i + 1]) {\r
393       break;\r
394     }\r
395   }\r
396   ASSERT (i < SkuIdTable[0]);\r
397 \r
398   switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
399     case PCD_TYPE_VPD:\r
400       Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);\r
401       return ((Value - PcdDb) | PCD_TYPE_VPD);\r
402 \r
403     case PCD_TYPE_HII:\r
404       Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);\r
405       return ((Value - PcdDb) | PCD_TYPE_HII);\r
406       \r
407     case PCD_TYPE_DATA:\r
408       Value += Size * i;\r
409       return (Value - PcdDb);\r
410       \r
411     default:\r
412       ASSERT (FALSE);\r
413   }\r
414 \r
415   ASSERT (FALSE);\r
416 \r
417   return 0;\r
418   \r
419 }\r
420 \r
421 \r
422 \r
423 \r
424 \r
425 VOID\r
426 InvokeCallbackOnSet (\r
427   UINT32            ExTokenNumber,\r
428   CONST EFI_GUID    *Guid, OPTIONAL\r
429   UINTN             TokenNumber,\r
430   VOID              *Data,\r
431   UINTN             Size\r
432   )\r
433 {\r
434   CALLBACK_FN_ENTRY       *FnTableEntry;\r
435   LIST_ENTRY              *ListHead;\r
436   LIST_ENTRY              *ListNode;\r
437 \r
438   ListHead = &mCallbackFnTable[TokenNumber];\r
439   ListNode = GetFirstNode (ListHead);\r
440 \r
441   while (ListNode != ListHead) {\r
442     FnTableEntry = CR_FNENTRY_FROM_LISTNODE(ListNode, CALLBACK_FN_ENTRY, Node);\r
443 \r
444     FnTableEntry->CallbackFn(Guid, \r
445                     (Guid == NULL) ? TokenNumber : ExTokenNumber,\r
446                     Data,\r
447                     Size);\r
448     \r
449     ListNode = GetNextNode (ListHead, ListNode);\r
450   }\r
451   \r
452   return;\r
453 }\r
454 \r
455 \r
456 \r
457 \r
458 EFI_STATUS\r
459 SetWorker (\r
460   PCD_TOKEN_NUMBER        TokenNumber,\r
461   VOID                    *Data,\r
462   UINTN                   Size,\r
463   BOOLEAN                 PtrType\r
464   )\r
465 {\r
466   UINT32              *LocalTokenNumberTable;\r
467   BOOLEAN             IsPeiDb;\r
468   UINT32              LocalTokenNumber;\r
469   EFI_GUID            *GuidTable;\r
470   UINT16              *StringTable;\r
471   EFI_GUID            *Guid;\r
472   UINT16              *Name;\r
473   VOID                *InternalData;\r
474   VARIABLE_HEAD       *VariableHead;\r
475   UINTN               Offset;\r
476   UINT8               *PcdDb;\r
477 \r
478 \r
479   ASSERT (TokenNumber < PCD_TOTAL_TOKEN_NUMBER);\r
480 \r
481   if (PtrType) {\r
482     ASSERT (Size <= DxePcdGetSize (TokenNumber));\r
483   } else {\r
484     ASSERT (Size == DxePcdGetSize (TokenNumber));\r
485   }\r
486   \r
487   IsPeiDb = (TokenNumber <= PEI_LOCAL_TOKEN_NUMBER) ? TRUE : FALSE;\r
488 \r
489   LocalTokenNumberTable  = IsPeiDb ? mPcdDatabase->PeiDb.Init.LocalTokenNumberTable : \r
490                                      mPcdDatabase->DxeDb.Init.LocalTokenNumberTable;\r
491 \r
492   if ((TokenNumber < PEI_NEX_TOKEN_NUMBER) ||\r
493       (TokenNumber >= PEI_LOCAL_TOKEN_NUMBER || TokenNumber < (PEI_LOCAL_TOKEN_NUMBER + DXE_NEX_TOKEN_NUMBER))) {\r
494     InvokeCallbackOnSet (0, NULL, TokenNumber, Data, Size);\r
495   }\r
496 \r
497   TokenNumber = IsPeiDb ? TokenNumber\r
498                         : TokenNumber - PEI_LOCAL_TOKEN_NUMBER;\r
499 \r
500   LocalTokenNumber = LocalTokenNumberTable[TokenNumber];\r
501   \r
502   if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
503     LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, Size, IsPeiDb);\r
504   }\r
505 \r
506   Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
507 \r
508   PcdDb = IsPeiDb ? ((UINT8 *) &mPcdDatabase->PeiDb) : ((UINT8 *) &mPcdDatabase->DxeDb);\r
509 \r
510   StringTable = IsPeiDb ? mPcdDatabase->PeiDb.Init.StringTable :\r
511                           mPcdDatabase->DxeDb.Init.StringTable;\r
512   \r
513   InternalData = PcdDb + Offset;\r
514 \r
515   switch (LocalTokenNumber & ~PCD_DATABASE_OFFSET_MASK) {\r
516     case PCD_TYPE_VPD:\r
517       ASSERT (FALSE);\r
518       return EFI_INVALID_PARAMETER;\r
519     \r
520     case PCD_TYPE_STRING:\r
521       CopyMem (&StringTable[*((UINT16 *)InternalData)], Data, Size);\r
522       break;\r
523 \r
524     case PCD_TYPE_HII:\r
525       //\r
526       // Bug Bug: Please implement this\r
527       //\r
528       GuidTable   = IsPeiDb ? mPcdDatabase->PeiDb.Init.GuidTable :\r
529                               mPcdDatabase->DxeDb.Init.GuidTable;\r
530                               \r
531       VariableHead = (VARIABLE_HEAD *) (PcdDb + Offset);\r
532       \r
533       Guid = &(GuidTable[VariableHead->GuidTableIndex]);\r
534       Name = &(StringTable[VariableHead->StringIndex]);\r
535 \r
536       return EFI_SUCCESS;\r
537 \r
538     case PCD_TYPE_DATA:\r
539       if (PtrType) {\r
540         CopyMem (InternalData, Data, Size);\r
541         return EFI_SUCCESS;\r
542       }\r
543 \r
544       switch (Size) {\r
545         case sizeof(UINT8):\r
546           *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
547           return EFI_SUCCESS;\r
548 \r
549         case sizeof(UINT16):\r
550           *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
551           return EFI_SUCCESS;\r
552 \r
553         case sizeof(UINT32):\r
554           *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
555           return EFI_SUCCESS;\r
556 \r
557         case sizeof(UINT64):\r
558           *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
559           return EFI_SUCCESS;\r
560 \r
561         default:\r
562           ASSERT (FALSE);\r
563           return EFI_NOT_FOUND;\r
564       }\r
565 \r
566     default:\r
567       ASSERT (FALSE);\r
568       break;\r
569     }\r
570       \r
571   ASSERT (FALSE);\r
572   return EFI_NOT_FOUND;\r
573 }\r
574 \r
575 \r
576 \r
577 \r
578 \r
579 VOID *\r
580 ExGetWorker (\r
581   IN CONST EFI_GUID         *Guid,\r
582   IN UINTN                  ExTokenNumber,\r
583   IN UINTN                  GetSize\r
584   ) \r
585 {\r
586   return GetWorker(GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);\r
587 }\r
588 \r
589 \r
590 \r
591 \r
592 \r
593 EFI_STATUS\r
594 ExSetWorker (\r
595   IN PCD_TOKEN_NUMBER     ExTokenNumber,\r
596   IN CONST EFI_GUID       *Guid,\r
597   VOID                    *Data,\r
598   UINTN                   SetSize,\r
599   BOOLEAN                 PtrType\r
600   )\r
601 {\r
602   PCD_TOKEN_NUMBER        TokenNumber;\r
603   \r
604   TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
605 \r
606   InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, SetSize);\r
607 \r
608   SetWorker (TokenNumber, Data, SetSize, PtrType);\r
609 \r
610   return EFI_SUCCESS;\r
611   \r
612 }\r
613 \r
614 \r
615 \r
616 \r
617 EFI_STATUS\r
618 SetHiiVariable (\r
619   IN  EFI_GUID     *VariableGuid,\r
620   IN  UINT16       *VariableName,\r
621   IN  CONST VOID   *Data,\r
622   IN  UINTN        DataSize,\r
623   IN  UINTN        Offset\r
624   )\r
625 {\r
626   UINTN       Size;\r
627   VOID        *Buffer;\r
628   EFI_STATUS  Status;\r
629   UINT32      Attribute;\r
630 \r
631   Size = 0;\r
632 \r
633   Status = EfiGetVariable (\r
634     (UINT16 *)VariableName,\r
635     VariableGuid,\r
636     &Attribute,\r
637     &Size,\r
638     NULL\r
639     );\r
640 \r
641   ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
642 \r
643   Buffer = AllocatePool (Size);\r
644 \r
645   ASSERT (Buffer != NULL);\r
646 \r
647   Status = EfiGetVariable (\r
648     VariableName,\r
649     VariableGuid,\r
650     &Attribute,\r
651     &Size,\r
652     Buffer\r
653     );\r
654 \r
655 \r
656   CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
657 \r
658   return EfiSetVariable (\r
659     VariableName,\r
660     VariableGuid,\r
661     Attribute,\r
662     Size,\r
663     Buffer\r
664     );\r
665 \r
666 }\r
667 \r
668 \r
669 \r
670 \r
671 \r
672 PCD_TOKEN_NUMBER\r
673 GetExPcdTokenNumber (\r
674   IN CONST EFI_GUID             *Guid,\r
675   IN PCD_TOKEN_NUMBER           ExTokenNumber\r
676   )\r
677 {\r
678   UINT32              i;\r
679   DYNAMICEX_MAPPING   *ExMap;\r
680   EFI_GUID            *GuidTable;\r
681   EFI_GUID            *MatchGuid;\r
682   UINTN               MatchGuidIdx;\r
683 \r
684   ExMap       = mPcdDatabase->PeiDb.Init.ExMapTable;\r
685   GuidTable   = mPcdDatabase->PeiDb.Init.GuidTable;\r
686   \r
687   MatchGuid   = ScanGuid (GuidTable, sizeof(mPcdDatabase->PeiDb.Init.GuidTable), Guid);\r
688   ASSERT (MatchGuid != NULL);\r
689 \r
690   MatchGuidIdx = MatchGuid - GuidTable;\r
691   \r
692   for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
693     if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
694         (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
695         return ExMap[i].LocalTokenNumber;\r
696 \r
697     }\r
698   }\r
699   \r
700   ExMap       = mPcdDatabase->DxeDb.Init.ExMapTable;\r
701   GuidTable   = mPcdDatabase->DxeDb.Init.GuidTable;\r
702 \r
703   MatchGuid   = ScanGuid (GuidTable, sizeof(mPcdDatabase->DxeDb.Init.GuidTable), Guid);\r
704   ASSERT (MatchGuid != NULL);\r
705 \r
706   MatchGuidIdx = MatchGuid - GuidTable;\r
707   \r
708   for (i = 0; i < DXE_EXMAPPING_TABLE_SIZE; i++) {\r
709     if ((ExTokenNumber == ExMap[i].ExTokenNumber) &&\r
710          (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
711         return ExMap[i].LocalTokenNumber + PEI_LOCAL_TOKEN_NUMBER;\r
712     }\r
713   }\r
714 \r
715   ASSERT (FALSE);\r
716 \r
717   return 0;\r
718 }\r
719 \r