Import PCD dxe and PCD pei modules.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / PCD / Pei / Service.c
1 /** @file\r
2 Private functions used by PCD PEIM.\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 //\r
18 // Include common header file for this module.\r
19 //\r
20 #include "CommonHeader.h"\r
21 \r
22 #include "Service.h"\r
23 \r
24 /**\r
25   The function registers the CallBackOnSet fucntion\r
26   according to TokenNumber and EFI_GUID space.\r
27 \r
28   @param  TokenNumber       The token number.\r
29   @param  Guid              The GUID space.\r
30   @param  CallBackFunction  The Callback function to be registered.\r
31   @param  Register          To register or unregister the callback function.\r
32 \r
33   @retval EFI_SUCCESS If the Callback function is registered.\r
34   @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.\r
35   @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free\r
36                                 slot left in the CallbackFnTable.\r
37 --*/\r
38 EFI_STATUS\r
39 PeiRegisterCallBackWorker (\r
40   IN  UINTN                       ExTokenNumber,\r
41   IN  CONST EFI_GUID              *Guid, OPTIONAL\r
42   IN  PCD_PPI_CALLBACK            CallBackFunction,\r
43   IN  BOOLEAN                     Register\r
44 )\r
45 {\r
46   EFI_HOB_GUID_TYPE       *GuidHob;\r
47   PCD_PPI_CALLBACK        *CallbackTable;\r
48   PCD_PPI_CALLBACK        Compare;\r
49   PCD_PPI_CALLBACK        Assign;\r
50   UINT32                  LocalTokenNumber;\r
51   UINTN                   TokenNumber;\r
52   UINTN                   Idx;\r
53 \r
54   if (Guid == NULL) {\r
55     TokenNumber = ExTokenNumber;\r
56 \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     ASSERT (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1);\r
64   } else {\r
65     TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
66 \r
67     //\r
68     // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
69     // We have to decrement TokenNumber by 1 to make it usable\r
70     // as the array index.\r
71     //\r
72     TokenNumber--;\r
73     // EBC compiler is very choosy. It may report warning about comparison\r
74     // between UINTN and 0 . So we add 1 in each size of the \r
75     // comparison.\r
76     ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
77   }\r
78 \r
79 \r
80   LocalTokenNumber = GetPcdDatabase()->Init.LocalTokenNumberTable[TokenNumber];\r
81 \r
82   //\r
83   // We don't support SET for HII and VPD type PCD entry in PEI phase.\r
84   // So we will assert if any register callback for such PCD entry.\r
85   //\r
86   ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);\r
87   ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);\r
88 \r
89   GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
90   ASSERT (GuidHob != NULL);\r
91   \r
92   CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
93   CallbackTable = CallbackTable + (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
94 \r
95   Compare = Register? NULL: CallBackFunction;\r
96   Assign  = Register? CallBackFunction: NULL;\r
97 \r
98 \r
99   for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
100     if (CallbackTable[Idx] == Compare) {\r
101       CallbackTable[Idx] = Assign;\r
102       return EFI_SUCCESS;\r
103     }\r
104   }\r
105 \r
106   return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND;\r
107 \r
108 }\r
109 \r
110 \r
111 \r
112 \r
113 /**\r
114   The function builds the PCD database.\r
115 \r
116   @param VOID\r
117 \r
118   @retval VOID\r
119 --*/\r
120 VOID\r
121 BuildPcdDatabase (\r
122   VOID\r
123   )\r
124 {\r
125   PEI_PCD_DATABASE  *Database;\r
126   VOID              *CallbackFnTable;\r
127   UINTN             SizeOfCallbackFnTable;\r
128   \r
129   Database = BuildGuidHob (&gPcdDataBaseHobGuid, sizeof (PEI_PCD_DATABASE));\r
130 \r
131   ZeroMem (Database, sizeof (PEI_PCD_DATABASE));\r
132 \r
133   //\r
134   // gPEIPcdDbInit is smaller than PEI_PCD_DATABASE\r
135   //\r
136   \r
137   CopyMem (&Database->Init, &gPEIPcdDbInit, sizeof (gPEIPcdDbInit));\r
138 \r
139   SizeOfCallbackFnTable = PEI_LOCAL_TOKEN_NUMBER * sizeof (PCD_PPI_CALLBACK) * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry);\r
140 \r
141   CallbackFnTable = BuildGuidHob (&gPcdPeiCallbackFnTableHobGuid, SizeOfCallbackFnTable);\r
142   \r
143   ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
144   \r
145   return;\r
146 }\r
147 \r
148 \r
149 \r
150 /**\r
151   The function is provided by PCD PEIM and PCD DXE driver to\r
152   do the work of reading a HII variable from variable service.\r
153 \r
154   @param VariableGuid     The Variable GUID.\r
155   @param VariableName     The Variable Name.\r
156   @param VariableData    The output data.\r
157   @param VariableSize    The size of the variable.\r
158 \r
159   @retval EFI_SUCCESS         Operation successful.\r
160   @retval EFI_NOT_FOUND         Variablel not found.\r
161 --*/\r
162 STATIC\r
163 EFI_STATUS\r
164 GetHiiVariable (\r
165   IN  CONST EFI_GUID      *VariableGuid,\r
166   IN  UINT16              *VariableName,\r
167   OUT VOID                **VariableData,\r
168   OUT UINTN               *VariableSize\r
169   )\r
170 {\r
171   UINTN      Size;\r
172   EFI_STATUS Status;\r
173   VOID       *Buffer;\r
174   EFI_PEI_READ_ONLY_VARIABLE_PPI *VariablePpi;\r
175 \r
176   Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, (VOID **) &VariablePpi);\r
177   ASSERT_EFI_ERROR (Status);\r
178 \r
179   Size = 0;\r
180   Status = VariablePpi->PeiGetVariable (\r
181                           GetPeiServicesTablePointer (),\r
182                           VariableName,\r
183                           (EFI_GUID *) VariableGuid,\r
184                           NULL,\r
185                           &Size,\r
186                           NULL\r
187                             );\r
188   if (Status == EFI_BUFFER_TOO_SMALL) {\r
189 \r
190 \r
191     Status = PeiServicesAllocatePool (Size, &Buffer);\r
192     ASSERT_EFI_ERROR (Status);\r
193 \r
194     Status = VariablePpi->PeiGetVariable (\r
195                               GetPeiServicesTablePointer (),\r
196                               (UINT16 *) VariableName,\r
197                               (EFI_GUID *) VariableGuid,\r
198                               NULL,\r
199                               &Size,\r
200                               Buffer\r
201                               );\r
202     ASSERT_EFI_ERROR (Status);\r
203 \r
204     *VariableSize = Size;\r
205     *VariableData = Buffer;\r
206 \r
207     return EFI_SUCCESS;\r
208   } else {\r
209     return EFI_NOT_FOUND;\r
210   }\r
211 \r
212 }\r
213 \r
214 STATIC\r
215 UINT32\r
216 GetSkuEnabledTokenNumber (\r
217   UINT32 LocalTokenNumber,\r
218   UINTN  Size\r
219   ) \r
220 {\r
221   PEI_PCD_DATABASE      *PeiPcdDb;\r
222   SKU_HEAD              *SkuHead;\r
223   SKU_ID                *SkuIdTable;\r
224   INTN                  i;\r
225   UINT8                 *Value;\r
226 \r
227   PeiPcdDb = GetPcdDatabase ();\r
228 \r
229   ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0);\r
230 \r
231   SkuHead     = (SKU_HEAD *) ((UINT8 *)PeiPcdDb + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
232   Value       = (UINT8 *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuDataStartOffset));\r
233   SkuIdTable  = (SKU_ID *) ((UINT8 *)PeiPcdDb + (SkuHead->SkuIdTableOffset));\r
234         \r
235   for (i = 0; i < SkuIdTable[0]; i++) {\r
236     if (PeiPcdDb->Init.SystemSkuId == SkuIdTable[i + 1]) {\r
237       break;\r
238     }\r
239   }\r
240 \r
241   switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
242     case PCD_TYPE_VPD:\r
243       Value = (UINT8 *) &(((VPD_HEAD *) Value)[i]);\r
244       return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_VPD);\r
245 \r
246     case PCD_TYPE_HII:\r
247       Value = (UINT8 *) &(((VARIABLE_HEAD *) Value)[i]);\r
248       return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_HII);\r
249       \r
250     case PCD_TYPE_STRING:\r
251       Value = (UINT8 *) &(((STRING_HEAD *) Value)[i]);\r
252       return (UINT32) ((Value - (UINT8 *) PeiPcdDb) | PCD_TYPE_STRING);\r
253 \r
254     case PCD_TYPE_DATA:\r
255       Value += Size * i;\r
256       return (UINT32) (Value - (UINT8 *) PeiPcdDb);\r
257 \r
258     default:\r
259       ASSERT (FALSE);\r
260   }\r
261 \r
262   ASSERT (FALSE);\r
263 \r
264   return 0;\r
265   \r
266 }\r
267 \r
268 \r
269 \r
270 STATIC\r
271 VOID\r
272 InvokeCallbackOnSet (\r
273   UINTN             ExTokenNumber,\r
274   CONST EFI_GUID    *Guid, OPTIONAL\r
275   UINTN             TokenNumber,\r
276   VOID              *Data,\r
277   UINTN             Size\r
278   )\r
279 {\r
280   EFI_HOB_GUID_TYPE   *GuidHob;\r
281   PCD_PPI_CALLBACK    *CallbackTable;\r
282   UINTN               Idx;\r
283 \r
284   //\r
285   // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
286   // We have to decrement TokenNumber by 1 to make it usable\r
287   // as the array index.\r
288   //\r
289   TokenNumber--;\r
290   \r
291   if (Guid == NULL) {\r
292     // EBC compiler is very choosy. It may report warning about comparison\r
293     // between UINTN and 0 . So we add 1 in each size of the \r
294     // comparison.\r
295     ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
296   }\r
297 \r
298   GuidHob = GetFirstGuidHob (&gPcdPeiCallbackFnTableHobGuid);\r
299   ASSERT (GuidHob != NULL);\r
300   \r
301   CallbackTable = GET_GUID_HOB_DATA (GuidHob);\r
302 \r
303   CallbackTable += (TokenNumber * FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry));\r
304 \r
305   for (Idx = 0; Idx < FixedPcdGet32(PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {\r
306     if (CallbackTable[Idx] != NULL) {\r
307       CallbackTable[Idx] (Guid,\r
308                           (Guid == NULL)? TokenNumber: ExTokenNumber,\r
309                           Data,\r
310                           Size\r
311                           );\r
312     }\r
313   }\r
314   \r
315 }\r
316 \r
317 \r
318 \r
319 EFI_STATUS\r
320 SetValueWorker (\r
321   IN          UINTN              TokenNumber,\r
322   IN          VOID               *Data,\r
323   IN          UINTN              Size\r
324   )\r
325 {\r
326   return SetWorker (TokenNumber, Data, &Size, FALSE);\r
327 }\r
328 \r
329 \r
330 \r
331 EFI_STATUS\r
332 SetWorker (\r
333   IN          UINTN               TokenNumber,\r
334   IN OUT      VOID                *Data,\r
335   IN OUT      UINTN               *Size,\r
336   IN          BOOLEAN             PtrType\r
337   )\r
338 {\r
339   UINT32              LocalTokenNumber;\r
340   PEI_PCD_DATABASE    *PeiPcdDb;\r
341   UINT16              StringTableIdx;\r
342   UINTN               Offset;\r
343   VOID                *InternalData;\r
344   UINTN               MaxSize;\r
345 \r
346   if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {\r
347     return EFI_UNSUPPORTED;\r
348   }\r
349   \r
350   //\r
351   // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
352   // We have to decrement TokenNumber by 1 to make it usable\r
353   // as the array index.\r
354   //\r
355   TokenNumber--;\r
356 \r
357   // EBC compiler is very choosy. It may report warning about comparison\r
358   // between UINTN and 0 . So we add 1 in each size of the \r
359   // comparison.\r
360   ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
361     \r
362   PeiPcdDb = GetPcdDatabase ();\r
363 \r
364   LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];\r
365 \r
366   if (!PtrType) {\r
367     ASSERT (PeiPcdGetSize(TokenNumber + 1) == *Size);\r
368   }\r
369 \r
370   //\r
371   // We only invoke the callback function for Dynamic Type PCD Entry.\r
372   // For Dynamic EX PCD entry, we have invoked the callback function for Dynamic EX\r
373   // type PCD entry in ExSetWorker.\r
374   //\r
375   if (TokenNumber + 1 < PEI_NEX_TOKEN_NUMBER + 1) {\r
376     InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
377   }\r
378 \r
379   if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
380     if (PtrType) {\r
381       MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
382     } else {\r
383       MaxSize = *Size;\r
384     }\r
385     LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
386   }\r
387 \r
388   Offset          = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
389   InternalData    = (VOID *) ((UINT8 *) PeiPcdDb + Offset);\r
390   \r
391   switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
392     case PCD_TYPE_VPD:\r
393     case PCD_TYPE_HII:\r
394     {\r
395       ASSERT (FALSE);\r
396       return EFI_INVALID_PARAMETER;\r
397     }\r
398 \r
399     case PCD_TYPE_STRING:\r
400       if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
401         StringTableIdx = *((UINT16 *)InternalData);\r
402         CopyMem (&PeiPcdDb->Init.StringTable[StringTableIdx], Data, *Size);\r
403         return EFI_SUCCESS;\r
404       } else {\r
405         return EFI_INVALID_PARAMETER;\r
406       }\r
407 \r
408     case PCD_TYPE_DATA:\r
409     {\r
410       if (PtrType) {\r
411         if (SetPtrTypeSize (TokenNumber, Size, PeiPcdDb)) {\r
412           CopyMem (InternalData, Data, *Size);\r
413           return EFI_SUCCESS;\r
414         } else {\r
415           return EFI_INVALID_PARAMETER;\r
416         }\r
417       }\r
418 \r
419       switch (*Size) {\r
420         case sizeof(UINT8):\r
421           *((UINT8 *) InternalData) = *((UINT8 *) Data);\r
422           return EFI_SUCCESS;\r
423 \r
424         case sizeof(UINT16):\r
425           *((UINT16 *) InternalData) = *((UINT16 *) Data);\r
426           return EFI_SUCCESS;\r
427 \r
428         case sizeof(UINT32):\r
429           *((UINT32 *) InternalData) = *((UINT32 *) Data);\r
430           return EFI_SUCCESS;\r
431 \r
432         case sizeof(UINT64):\r
433           *((UINT64 *) InternalData) = *((UINT64 *) Data);\r
434           return EFI_SUCCESS;\r
435 \r
436         default:\r
437           ASSERT (FALSE);\r
438           return EFI_NOT_FOUND;\r
439       }\r
440     }\r
441       \r
442   }\r
443 \r
444   ASSERT (FALSE);\r
445   return EFI_NOT_FOUND;\r
446 \r
447 }\r
448 \r
449 \r
450 \r
451 EFI_STATUS\r
452 ExSetValueWorker (\r
453   IN          UINTN                ExTokenNumber,\r
454   IN          CONST EFI_GUID       *Guid,\r
455   IN          VOID                 *Data,\r
456   IN          UINTN                Size\r
457   )\r
458 {\r
459   return ExSetWorker (ExTokenNumber, Guid, Data, &Size, FALSE);\r
460 }\r
461 \r
462 \r
463 \r
464 EFI_STATUS\r
465 ExSetWorker (\r
466   IN            UINTN                ExTokenNumber,\r
467   IN            CONST EFI_GUID       *Guid,\r
468   IN            VOID                 *Data,\r
469   IN OUT        UINTN                *Size,\r
470   IN            BOOLEAN              PtrType\r
471   )\r
472 {\r
473   UINTN                     TokenNumber;\r
474 \r
475   if (!FeaturePcdGet(PcdPeiPcdDatabaseSetEnabled)) {\r
476     return EFI_UNSUPPORTED;\r
477   }\r
478 \r
479   TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);\r
480 \r
481   InvokeCallbackOnSet (ExTokenNumber, Guid, TokenNumber, Data, *Size);\r
482 \r
483   return SetWorker (TokenNumber, Data, Size, PtrType);\r
484 \r
485 }\r
486 \r
487 \r
488 \r
489 \r
490 VOID *\r
491 ExGetWorker (\r
492   IN CONST  EFI_GUID  *Guid,\r
493   IN UINTN            ExTokenNumber,\r
494   IN UINTN            GetSize\r
495   )\r
496 {\r
497   if (!FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {\r
498     ASSERT (FALSE);\r
499     return 0;\r
500   }\r
501   \r
502   return GetWorker (GetExPcdTokenNumber (Guid, ExTokenNumber), GetSize);\r
503 }\r
504 \r
505 \r
506 \r
507 \r
508 VOID *\r
509 GetWorker (\r
510   UINTN               TokenNumber,\r
511   UINTN               GetSize\r
512   )\r
513 {\r
514   UINT32              Offset;\r
515   EFI_GUID            *Guid;\r
516   UINT16              *Name;\r
517   VARIABLE_HEAD       *VariableHead;\r
518   EFI_STATUS          Status;\r
519   UINTN               DataSize;\r
520   VOID                *Data;\r
521   UINT16              *StringTable;\r
522   UINT16              StringTableIdx;\r
523   PEI_PCD_DATABASE    *PeiPcdDb;\r
524   UINT32              LocalTokenNumber;\r
525   UINTN               MaxSize;\r
526 \r
527   //\r
528   // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
529   // We have to decrement TokenNumber by 1 to make it usable\r
530   // as the array index.\r
531   //\r
532   TokenNumber--;\r
533 \r
534   // EBC compiler is very choosy. It may report warning about comparison\r
535   // between UINTN and 0 . So we add 1 in each size of the \r
536   // comparison.\r
537   ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);\r
538 \r
539   ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));\r
540 \r
541   PeiPcdDb        = GetPcdDatabase ();\r
542 \r
543   LocalTokenNumber = PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber];\r
544 \r
545   if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
546     if (GetSize == 0) {\r
547       MaxSize = GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
548     } else {\r
549       MaxSize = GetSize;\r
550     }\r
551     LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
552   }\r
553 \r
554   Offset      = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
555   StringTable = PeiPcdDb->Init.StringTable;\r
556   \r
557   switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {\r
558     case PCD_TYPE_VPD:\r
559     {\r
560       VPD_HEAD *VpdHead;\r
561       VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
562       return (VOID *) (UINTN) (FixedPcdGet32(PcdVpdBaseAddress) + VpdHead->Offset);\r
563     }\r
564       \r
565     case PCD_TYPE_HII:\r
566     {\r
567       VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);\r
568       \r
569       Guid = &(PeiPcdDb->Init.GuidTable[VariableHead->GuidTableIndex]);\r
570       Name = &StringTable[VariableHead->StringIndex];\r
571 \r
572       Status = GetHiiVariable (Guid, Name, &Data, &DataSize);\r
573 \r
574       if (Status == EFI_SUCCESS) {\r
575         return (VOID *) ((UINT8 *) Data + VariableHead->Offset);\r
576       } else {\r
577         //\r
578         // Return the default value specified by Platform Integrator \r
579         //\r
580         return (VOID *) ((UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset);\r
581       }\r
582     }\r
583 \r
584     case PCD_TYPE_DATA:\r
585       return (VOID *) ((UINT8 *)PeiPcdDb + Offset);\r
586 \r
587     case PCD_TYPE_STRING:\r
588       StringTableIdx = (UINT16) *((UINT8 *) PeiPcdDb + Offset);\r
589       return (VOID *) (&StringTable[StringTableIdx]);\r
590 \r
591     default:\r
592       ASSERT (FALSE);\r
593       break;\r
594       \r
595   }\r
596 \r
597   ASSERT (FALSE);\r
598       \r
599   return NULL;\r
600   \r
601 }\r
602 \r
603 \r
604 \r
605 UINTN           \r
606 GetExPcdTokenNumber (\r
607   IN CONST EFI_GUID             *Guid,\r
608   IN UINTN                      ExTokenNumber\r
609   )\r
610 {\r
611   UINT32              i;\r
612   DYNAMICEX_MAPPING   *ExMap;\r
613   EFI_GUID            *GuidTable;\r
614   EFI_GUID            *MatchGuid;\r
615   UINTN               MatchGuidIdx;\r
616   PEI_PCD_DATABASE    *PeiPcdDb;\r
617 \r
618   PeiPcdDb    = GetPcdDatabase();\r
619   \r
620   ExMap       = PeiPcdDb->Init.ExMapTable;\r
621   GuidTable   = PeiPcdDb->Init.GuidTable;\r
622 \r
623   MatchGuid = ScanGuid (GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);\r
624   //\r
625   // We need to ASSERT here. If GUID can't be found in GuidTable, this is a\r
626   // error in the BUILD system.\r
627   //\r
628   ASSERT (MatchGuid != NULL);\r
629   \r
630   MatchGuidIdx = MatchGuid - GuidTable;\r
631   \r
632   for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {\r
633     if ((ExTokenNumber == ExMap[i].ExTokenNumber) && \r
634         (MatchGuidIdx == ExMap[i].ExGuidIndex)) {\r
635       return ExMap[i].LocalTokenNumber;\r
636     }\r
637   }\r
638   \r
639   ASSERT (FALSE);\r
640   \r
641   return 0;\r
642 }\r
643 \r
644 \r
645 \r
646 PEI_PCD_DATABASE *\r
647 GetPcdDatabase (\r
648   VOID\r
649   )\r
650 {\r
651   EFI_HOB_GUID_TYPE *GuidHob;\r
652 \r
653   GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
654   ASSERT (GuidHob != NULL);\r
655   \r
656   return (PEI_PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
657 }\r
658 \r
659 \r
660 \r
661 SKU_ID *\r
662 GetSkuIdArray (\r
663   IN    UINTN             LocalTokenNumberTableIdx,\r
664   IN    PEI_PCD_DATABASE  *Database\r
665   )\r
666 {\r
667   SKU_HEAD *SkuHead;\r
668   UINTN     LocalTokenNumber;\r
669 \r
670   LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];\r
671 \r
672   ASSERT ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) != 0);\r
673 \r
674   SkuHead = (SKU_HEAD *) ((UINT8 *)Database + (LocalTokenNumber & PCD_DATABASE_OFFSET_MASK));\r
675 \r
676   return (SKU_ID *) ((UINT8 *)Database + SkuHead->SkuIdTableOffset);\r
677   \r
678 }\r
679 \r
680 \r
681 \r
682 UINTN\r
683 GetSizeTableIndex (\r
684   IN    UINTN             LocalTokenNumberTableIdx,\r
685   IN    PEI_PCD_DATABASE  *Database\r
686   )\r
687 {\r
688   UINTN       i;\r
689   UINTN        SizeTableIdx;\r
690   UINTN       LocalTokenNumber;\r
691   SKU_ID      *SkuIdTable;\r
692   \r
693   SizeTableIdx = 0;\r
694 \r
695   for (i=0; i<LocalTokenNumberTableIdx; i++) {\r
696     LocalTokenNumber = Database->Init.LocalTokenNumberTable[i];\r
697 \r
698     if ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER) {\r
699       //\r
700       // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type \r
701       // PCD entry.\r
702       //\r
703       if (LocalTokenNumber & PCD_TYPE_VPD) {\r
704           //\r
705           // We have only one entry for VPD enabled PCD entry:\r
706           // 1) MAX Size.\r
707           // We consider current size is equal to MAX size.\r
708           //\r
709           SizeTableIdx++;\r
710       } else {\r
711         if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
712           //\r
713           // We have only two entry for Non-Sku enabled PCD entry:\r
714           // 1) MAX SIZE\r
715           // 2) Current Size\r
716           //\r
717           SizeTableIdx += 2;\r
718         } else {\r
719           //\r
720           // We have these entry for SKU enabled PCD entry\r
721           // 1) MAX SIZE\r
722           // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
723           //\r
724           SkuIdTable = GetSkuIdArray (i, Database);\r
725           SizeTableIdx += (UINTN)*SkuIdTable + 1;\r
726         }\r
727       }\r
728     }\r
729 \r
730   }\r
731 \r
732   return SizeTableIdx;\r
733 }\r