1## @file
2# Routines for generating Pcd Database
3#
4# Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
5# This program and the accompanying materials
6# are licensed and made available under the terms and conditions of the BSD License
7# which accompanies this distribution.  The full text of the license may be found at
8# http://opensource.org/licenses/bsd-license.php
9#
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12#
13from StringIO import StringIO
14from Common.Misc import *
15from Common.String import StringToArray
16from struct import pack
17from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER
18from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB
19from ValidCheckingInfoObject import VAR_VALID_OBJECT_FACTORY
20from Common.VariableAttributes import VariableAttributes
21
22DATABASE_VERSION = 5
23
24gPcdDatabaseAutoGenC = TemplateString("""
25//
26// External PCD database debug information
27//
28#if 0
29${PHASE}_PCD_DATABASE_INIT g${PHASE}PcdDbInit = {
30${BEGIN}  { ${INIT_VALUE_UINT64} }, /*  ${INIT_CNAME_DECL_UINT64}_${INIT_GUID_DECL_UINT64}[${INIT_NUMSKUS_DECL_UINT64}] */
31${END}
32${BEGIN}  ${VARDEF_VALUE_UINT64}, /* ${VARDEF_CNAME_UINT64}_${VARDEF_GUID_UINT64}_VariableDefault_${VARDEF_SKUID_UINT64} */
33${END}
34${BEGIN}  { ${INIT_VALUE_UINT32} }, /*  ${INIT_CNAME_DECL_UINT32}_${INIT_GUID_DECL_UINT32}[${INIT_NUMSKUS_DECL_UINT32}] */
35${END}
36${BEGIN}  ${VARDEF_VALUE_UINT32}, /* ${VARDEF_CNAME_UINT32}_${VARDEF_GUID_UINT32}_VariableDefault_${VARDEF_SKUID_UINT32} */
37${END}
38  /* VPD */
39${BEGIN}  { ${VPD_HEAD_VALUE} }, /* ${VPD_HEAD_CNAME_DECL}_${VPD_HEAD_GUID_DECL}[${VPD_HEAD_NUMSKUS_DECL}] */
40${END}
41  /* ExMapTable */
42  {
43${BEGIN}    { ${EXMAPPING_TABLE_EXTOKEN}, ${EXMAPPING_TABLE_LOCAL_TOKEN}, ${EXMAPPING_TABLE_GUID_INDEX} },
44${END}
45  },
46  /* LocalTokenNumberTable */
47  {
48${BEGIN}    offsetof(${PHASE}_PCD_DATABASE, ${TOKEN_INIT}.${TOKEN_CNAME}_${TOKEN_GUID}${VARDEF_HEADER}) | ${TOKEN_TYPE},
49${END}
50  },
51  /* GuidTable */
52  {
53${BEGIN}    ${GUID_STRUCTURE},
54${END}
55  },
56${BEGIN}  { ${STRING_HEAD_VALUE} }, /* ${STRING_HEAD_CNAME_DECL}_${STRING_HEAD_GUID_DECL}[${STRING_HEAD_NUMSKUS_DECL}] */
57${END}
58${BEGIN}  /* ${VARIABLE_HEAD_CNAME_DECL}_${VARIABLE_HEAD_GUID_DECL}_Variable_Header[${VARIABLE_HEAD_NUMSKUS_DECL}] */
59  {
60    ${VARIABLE_HEAD_VALUE}
61  },
62${END}
63/* SkuHead */
64  {
65  ${BEGIN} offsetof (${PHASE}_PCD_DATABASE, ${TOKEN_INIT}.${TOKEN_CNAME}_${TOKEN_GUID}${VARDEF_HEADER}) | ${TOKEN_TYPE}, /* */
66           offsetof (${PHASE}_PCD_DATABASE, ${TOKEN_INIT}.SkuHead)  /* */
67  ${END}
68  },
69 /* StringTable */
70${BEGIN}  ${STRING_TABLE_VALUE}, /* ${STRING_TABLE_CNAME}_${STRING_TABLE_GUID} */
71${END}
72  /* SizeTable */
73  {
74${BEGIN}    ${SIZE_TABLE_MAXIMUM_LENGTH}, ${SIZE_TABLE_CURRENT_LENGTH}, /* ${SIZE_TABLE_CNAME}_${SIZE_TABLE_GUID} */
75${END}
76  },
77${BEGIN}  { ${INIT_VALUE_UINT16} }, /*  ${INIT_CNAME_DECL_UINT16}_${INIT_GUID_DECL_UINT16}[${INIT_NUMSKUS_DECL_UINT16}] */
78${END}
79${BEGIN}  ${VARDEF_VALUE_UINT16}, /* ${VARDEF_CNAME_UINT16}_${VARDEF_GUID_UINT16}_VariableDefault_${VARDEF_SKUID_UINT16} */
80${END}
81${BEGIN}  { ${INIT_VALUE_UINT8} }, /*  ${INIT_CNAME_DECL_UINT8}_${INIT_GUID_DECL_UINT8}[${INIT_NUMSKUS_DECL_UINT8}] */
82${END}
83${BEGIN}  ${VARDEF_VALUE_UINT8}, /* ${VARDEF_CNAME_UINT8}_${VARDEF_GUID_UINT8}_VariableDefault_${VARDEF_SKUID_UINT8} */
84${END}
85${BEGIN}  { ${INIT_VALUE_BOOLEAN} }, /*  ${INIT_CNAME_DECL_BOOLEAN}_${INIT_GUID_DECL_BOOLEAN}[${INIT_NUMSKUS_DECL_BOOLEAN}] */
86${END}
87${BEGIN}  ${VARDEF_VALUE_BOOLEAN}, /* ${VARDEF_CNAME_BOOLEAN}_${VARDEF_GUID_BOOLEAN}_VariableDefault_${VARDEF_SKUID_BOOLEAN} */
88${END}
89  /* SkuIdTable */
90  { ${BEGIN}${SKUID_VALUE}, ${END} },
91  ${SYSTEM_SKU_ID_VALUE}
92};
93#endif
94""")
95
96## Mapping between PCD driver type and EFI phase
97gPcdPhaseMap = {
98    "PEI_PCD_DRIVER"    :   "PEI",
99    "DXE_PCD_DRIVER"    :   "DXE"
100}
101
102gPcdDatabaseAutoGenH = TemplateString("""
103#define PCD_${PHASE}_SERVICE_DRIVER_VERSION         ${SERVICE_DRIVER_VERSION}
104
105//
106// External PCD database debug information
107//
108#if 0
109#define ${PHASE}_GUID_TABLE_SIZE                ${GUID_TABLE_SIZE}
110#define ${PHASE}_STRING_TABLE_SIZE              ${STRING_TABLE_SIZE}
111#define ${PHASE}_SKUID_TABLE_SIZE               ${SKUID_TABLE_SIZE}
112#define ${PHASE}_LOCAL_TOKEN_NUMBER_TABLE_SIZE  ${LOCAL_TOKEN_NUMBER_TABLE_SIZE}
113#define ${PHASE}_LOCAL_TOKEN_NUMBER             ${LOCAL_TOKEN_NUMBER}
114#define ${PHASE}_EXMAPPING_TABLE_SIZE           ${EXMAPPING_TABLE_SIZE}
115#define ${PHASE}_EX_TOKEN_NUMBER                ${EX_TOKEN_NUMBER}
116#define ${PHASE}_SIZE_TABLE_SIZE                ${SIZE_TABLE_SIZE}
117#define ${PHASE}_SKU_HEAD_SIZE                  ${SKU_HEAD_SIZE}
118#define ${PHASE}_GUID_TABLE_EMPTY               ${GUID_TABLE_EMPTY}
119#define ${PHASE}_STRING_TABLE_EMPTY             ${STRING_TABLE_EMPTY}
120#define ${PHASE}_SKUID_TABLE_EMPTY              ${SKUID_TABLE_EMPTY}
121#define ${PHASE}_DATABASE_EMPTY                 ${DATABASE_EMPTY}
122#define ${PHASE}_EXMAP_TABLE_EMPTY              ${EXMAP_TABLE_EMPTY}
123
124typedef struct {
125${BEGIN}  UINT64             ${INIT_CNAME_DECL_UINT64}_${INIT_GUID_DECL_UINT64}[${INIT_NUMSKUS_DECL_UINT64}];
126${END}
127${BEGIN}  UINT64             ${VARDEF_CNAME_UINT64}_${VARDEF_GUID_UINT64}_VariableDefault_${VARDEF_SKUID_UINT64};
128${END}
129${BEGIN}  UINT32             ${INIT_CNAME_DECL_UINT32}_${INIT_GUID_DECL_UINT32}[${INIT_NUMSKUS_DECL_UINT32}];
130${END}
131${BEGIN}  UINT32             ${VARDEF_CNAME_UINT32}_${VARDEF_GUID_UINT32}_VariableDefault_${VARDEF_SKUID_UINT32};
132${END}
133${BEGIN}  VPD_HEAD           ${VPD_HEAD_CNAME_DECL}_${VPD_HEAD_GUID_DECL}[${VPD_HEAD_NUMSKUS_DECL}];
134${END}
135  DYNAMICEX_MAPPING  ExMapTable[${PHASE}_EXMAPPING_TABLE_SIZE];
136  UINT32             LocalTokenNumberTable[${PHASE}_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
137  GUID               GuidTable[${PHASE}_GUID_TABLE_SIZE];
138${BEGIN}  STRING_HEAD        ${STRING_HEAD_CNAME_DECL}_${STRING_HEAD_GUID_DECL}[${STRING_HEAD_NUMSKUS_DECL}];
139${END}
140${BEGIN}  VARIABLE_HEAD      ${VARIABLE_HEAD_CNAME_DECL}_${VARIABLE_HEAD_GUID_DECL}_Variable_Header[${VARIABLE_HEAD_NUMSKUS_DECL}];
141${END}
142${BEGIN}  SKU_HEAD           SkuHead[${PHASE}_SKU_HEAD_SIZE];
143${END}
144${BEGIN}  UINT8              StringTable${STRING_TABLE_INDEX}[${STRING_TABLE_LENGTH}]; /* ${STRING_TABLE_CNAME}_${STRING_TABLE_GUID} */
145${END}
146  SIZE_INFO          SizeTable[${PHASE}_SIZE_TABLE_SIZE];
147${BEGIN}  UINT16             ${INIT_CNAME_DECL_UINT16}_${INIT_GUID_DECL_UINT16}[${INIT_NUMSKUS_DECL_UINT16}];
148${END}
149${BEGIN}  UINT16             ${VARDEF_CNAME_UINT16}_${VARDEF_GUID_UINT16}_VariableDefault_${VARDEF_SKUID_UINT16};
150${END}
151${BEGIN}  UINT8              ${INIT_CNAME_DECL_UINT8}_${INIT_GUID_DECL_UINT8}[${INIT_NUMSKUS_DECL_UINT8}];
152${END}
153${BEGIN}  UINT8              ${VARDEF_CNAME_UINT8}_${VARDEF_GUID_UINT8}_VariableDefault_${VARDEF_SKUID_UINT8};
154${END}
155${BEGIN}  BOOLEAN            ${INIT_CNAME_DECL_BOOLEAN}_${INIT_GUID_DECL_BOOLEAN}[${INIT_NUMSKUS_DECL_BOOLEAN}];
156${END}
157${BEGIN}  BOOLEAN            ${VARDEF_CNAME_BOOLEAN}_${VARDEF_GUID_BOOLEAN}_VariableDefault_${VARDEF_SKUID_BOOLEAN};
158${END}
159  UINT8              SkuIdTable[${PHASE}_SKUID_TABLE_SIZE];
160${SYSTEM_SKU_ID}
161} ${PHASE}_PCD_DATABASE_INIT;
162
163typedef struct {
164${PCD_DATABASE_UNINIT_EMPTY}
165${BEGIN}  UINT64   ${UNINIT_CNAME_DECL_UINT64}_${UNINIT_GUID_DECL_UINT64}[${UNINIT_NUMSKUS_DECL_UINT64}];
166${END}
167${BEGIN}  UINT32   ${UNINIT_CNAME_DECL_UINT32}_${UNINIT_GUID_DECL_UINT32}[${UNINIT_NUMSKUS_DECL_UINT32}];
168${END}
169${BEGIN}  UINT16   ${UNINIT_CNAME_DECL_UINT16}_${UNINIT_GUID_DECL_UINT16}[${UNINIT_NUMSKUS_DECL_UINT16}];
170${END}
171${BEGIN}  UINT8    ${UNINIT_CNAME_DECL_UINT8}_${UNINIT_GUID_DECL_UINT8}[${UNINIT_NUMSKUS_DECL_UINT8}];
172${END}
173${BEGIN}  BOOLEAN  ${UNINIT_CNAME_DECL_BOOLEAN}_${UNINIT_GUID_DECL_BOOLEAN}[${UNINIT_NUMSKUS_DECL_BOOLEAN}];
174${END}
175} ${PHASE}_PCD_DATABASE_UNINIT;
176
177typedef struct {
178  //GUID                  Signature;  // PcdDataBaseGuid
179  //UINT32                Length;
180  //UINT32                UninitDataBaseSize;// Total size for PCD those default value with 0.
181  //TABLE_OFFSET          LocalTokenNumberTableOffset;
182  //TABLE_OFFSET          ExMapTableOffset;
183  //TABLE_OFFSET          GuidTableOffset;
184  //TABLE_OFFSET          StringTableOffset;
185  //TABLE_OFFSET          SizeTableOffset;
186  //TABLE_OFFSET          SkuIdTableOffset;
187  //UINT16                LocalTokenCount;  // LOCAL_TOKEN_NUMBER for all
188  //UINT16                ExTokenCount;     // EX_TOKEN_NUMBER for DynamicEx
189  //UINT16                GuidTableCount;   // The Number of Guid in GuidTable
190  //SKU_ID                SystemSkuId;      // Current SkuId value.
191  //UINT8                 Pad;
192  ${PHASE}_PCD_DATABASE_INIT    Init;
193  ${PHASE}_PCD_DATABASE_UNINIT  Uninit;
194} ${PHASE}_PCD_DATABASE;
195
196#define ${PHASE}_NEX_TOKEN_NUMBER (${PHASE}_LOCAL_TOKEN_NUMBER - ${PHASE}_EX_TOKEN_NUMBER)
197#endif
198""")
199
200
201gEmptyPcdDatabaseAutoGenC = TemplateString("""
202//
203// External PCD database debug information
204//
205#if 0
206${PHASE}_PCD_DATABASE_INIT g${PHASE}PcdDbInit = {
207  /* ExMapTable */
208  {
209    {0, 0, 0}
210  },
211  /* LocalTokenNumberTable */
212  {
213    0
214  },
215  /* GuidTable */
216  {
217    {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
218  },
219  /* StringTable */
220  { 0 },
221  /* SkuHead */
222  {
223    0, 0
224  },
225  /* SizeTable */
226  {
227    0, 0
228  },
229  /* SkuIdTable */
230  { 0 },
231  ${SYSTEM_SKU_ID_VALUE}
232};
233#endif
234""")
235
236## PackGuid
237#
238# Pack the GUID value in C structure format into data array
239#
240# @param GuidStructureValue:   The GUID value in C structure format
241#
242# @retval Buffer:  a data array contains the Guid
243#
244def PackGuid(GuidStructureValue):
245    GuidString = GuidStructureStringToGuidString(GuidStructureValue)
246    Guid = GuidString.split('-')
247    Buffer = pack('=LHHBBBBBBBB',
248                int(Guid[0], 16),
249                int(Guid[1], 16),
250                int(Guid[2], 16),
251                int(Guid[3][-4:-2], 16),
252                int(Guid[3][-2:], 16),
253                int(Guid[4][-12:-10], 16),
254                int(Guid[4][-10:-8], 16),
255                int(Guid[4][-8:-6], 16),
256                int(Guid[4][-6:-4], 16),
257                int(Guid[4][-4:-2], 16),
258                int(Guid[4][-2:], 16)
259                )
260    return Buffer
261
262def toHex(s):
263    lst = []
264    for ch in s:
265        hv = hex(ord(ch)).replace('0x', ' ')
266        if len(hv) == 1:
267            hv = '0'+hv
268        lst.append(hv)
269    if lst:
270        return reduce(lambda x,y:x+y, lst)
271    else:
272        return 'empty'
273## DbItemList
274#
275#  The class holds the Pcd database items. ItemSize if not zero should match the item datum type in the C structure.
276#  When the structure is changed, remember to check the ItemSize and the related  PackStr in PackData()
277#  RawDataList is the RawData that may need some kind of calculation or transformation,
278#  the DataList corresponds to the data that need to be written to database. If DataList is not present, then RawDataList
279#  will be written to the database.
280#
281class DbItemList:
282    def __init__(self, ItemSize, DataList=None, RawDataList=None):
283        if DataList is None:
284            DataList = []
285        if RawDataList is None:
286            RawDataList = []
287        self.ItemSize = ItemSize
288        self.DataList = DataList
289        self.RawDataList = RawDataList
290        self.ListSize = 0
291
292    def GetInterOffset(self, Index):
293        Offset = 0
294        if self.ItemSize == 0:
295            #
296            # Variable length, need to calculate one by one
297            #
298            assert(Index < len(self.RawDataList))
299            for ItemIndex in xrange(Index):
300                Offset += len(self.RawDataList[ItemIndex])
301        else:
302            for Datas in self.RawDataList:
303                Offset = self.ItemSize * Index
304
305        return Offset
306
307    def GetListSize(self):
308        if self.ListSize:
309            return self.ListSize
310        if len(self.RawDataList) == 0:
311            self.ListSize = 0
312            return self.ListSize
313        if self.ItemSize == 0:
314            self.ListSize = self.GetInterOffset(len(self.RawDataList) - 1) + len(self.RawDataList[len(self.RawDataList)-1])
315        else:
316            self.ListSize = self.ItemSize * len(self.RawDataList)
317        return self.ListSize
318
319    def PackData(self):
320        if self.ItemSize == 8:
321            PackStr = "=Q"
322        elif self.ItemSize == 4:
323            PackStr = "=L"
324        elif self.ItemSize == 2:
325            PackStr = "=H"
326        elif self.ItemSize == 1:
327            PackStr = "=B"
328        elif self.ItemSize == 0:
329            PackStr = "=B"
330        elif self.ItemSize == 16:
331            # pack Guid
332            PackStr = ''
333        else:
334            # should not reach here
335            assert(False)
336
337        Buffer = ''
338        for Datas in self.RawDataList:
339            if type(Datas) in (list, tuple):
340                for Data in Datas:
341                    if PackStr:
342                        Buffer += pack(PackStr, GetIntegerValue(Data))
343                    else:
344                        Buffer += PackGuid(Data)
345            else:
346                if PackStr:
347                    Buffer += pack(PackStr, GetIntegerValue(Datas))
348                else:
349                    Buffer += PackGuid(Datas)
350
351        return Buffer
352
353## DbExMapTblItemList
354#
355#  The class holds the ExMap table
356#
357class DbExMapTblItemList (DbItemList):
358    def __init__(self, ItemSize, DataList=None, RawDataList=None):
359        if DataList is None:
360            DataList = []
361        if RawDataList is None:
362            RawDataList = []
363        DbItemList.__init__(self, ItemSize, DataList, RawDataList)
364    def PackData(self):
365        Buffer = ''
366        PackStr = "=LHH"
367        for Datas in self.RawDataList:
368            Buffer += pack(PackStr,
369                           GetIntegerValue(Datas[0]),
370                           GetIntegerValue(Datas[1]),
371                           GetIntegerValue(Datas[2]))
372        return Buffer
373
374## DbComItemList
375#
376# The DbComItemList is a special kind of DbItemList in case that the size of the List can not be computed by the
377# ItemSize multiply the ItemCount.
378#
379class DbComItemList (DbItemList):
380    def __init__(self, ItemSize, DataList=None, RawDataList=None):
381        if DataList is None:
382            DataList = []
383        if RawDataList is None:
384            RawDataList = []
385        DbItemList.__init__(self, ItemSize, DataList, RawDataList)
386    def GetInterOffset(self, Index):
387        Offset = 0
388        if self.ItemSize == 0:
389            #
390            # Variable length, need to calculte one by one
391            # The only variable table is stringtable, it is not Composite item, should not reach here
392            #
393            assert(False)
394        else:
395            assert(Index < len(self.RawDataList))
396            for ItemIndex in xrange(Index):
397                Offset += len(self.RawDataList[ItemIndex]) * self.ItemSize
398
399        return Offset
400
401    def GetListSize(self):
402        if self.ListSize:
403            return self.ListSize
404        if self.ItemSize == 0:
405            assert(False)
406        else:
407            if len(self.RawDataList) == 0:
408                self.ListSize = 0
409            else:
410                self.ListSize = self.GetInterOffset(len(self.RawDataList) - 1) + len(self.RawDataList[len(self.RawDataList)-1]) * self.ItemSize
411
412        return self.ListSize
413
414    def PackData(self):
415        if self.ItemSize == 8:
416            PackStr = "=Q"
417        elif self.ItemSize == 4:
418            PackStr = "=L"
419        elif self.ItemSize == 2:
420            PackStr = "=H"
421        elif self.ItemSize == 1:
422            PackStr = "=B"
423        elif self.ItemSize == 0:
424            PackStr = "=B"
425        else:
426            assert(False)
427
428        Buffer = ''
429        for DataList in self.RawDataList:
430            for Data in DataList:
431                if type(Data) in (list, tuple):
432                    for SingleData in Data:
433                        Buffer += pack(PackStr, GetIntegerValue(SingleData))
434                else:
435                    Buffer += pack(PackStr, GetIntegerValue(Data))
436
437        return Buffer
438
439## DbVariableTableItemList
440#
441#  The class holds the Variable header value table
442#
443class DbVariableTableItemList (DbComItemList):
444    def __init__(self, ItemSize, DataList=None, RawDataList=None):
445        if DataList is None:
446            DataList = []
447        if RawDataList is None:
448            RawDataList = []
449        DbComItemList.__init__(self, ItemSize, DataList, RawDataList)
450    def PackData(self):
451        PackStr = "=LLHHLHH"
452        Buffer = ''
453        for DataList in self.RawDataList:
454            for Data in DataList:
455                Buffer += pack(PackStr,
456                               GetIntegerValue(Data[0]),
457                               GetIntegerValue(Data[1]),
458                               GetIntegerValue(Data[2]),
459                               GetIntegerValue(Data[3]),
460                               GetIntegerValue(Data[4]),
461                               GetIntegerValue(Data[5]),
462                               GetIntegerValue(0))
463        return Buffer
464
465class DbStringHeadTableItemList(DbItemList):
466    def __init__(self,ItemSize,DataList=None,RawDataList=None):
467        if DataList is None:
468            DataList = []
469        if RawDataList is None:
470            RawDataList = []
471        DbItemList.__init__(self, ItemSize, DataList, RawDataList)
472
473    def GetInterOffset(self, Index):
474        Offset = 0
475        if self.ItemSize == 0:
476            #
477            # Variable length, need to calculate one by one
478            #
479            assert(Index < len(self.RawDataList))
480            for ItemIndex in xrange(Index):
481                Offset += len(self.RawDataList[ItemIndex])
482        else:
483            for innerIndex in range(Index):
484                if type(self.RawDataList[innerIndex]) in (list, tuple):
485                    Offset += len(self.RawDataList[innerIndex]) * self.ItemSize
486                else:
487                    Offset += self.ItemSize
488
489        return Offset
490
491    def GetListSize(self):
492        if self.ListSize:
493            return self.ListSize
494        if len(self.RawDataList) == 0:
495            self.ListSize = 0
496            return self.ListSize
497        if self.ItemSize == 0:
498            self.ListSize = self.GetInterOffset(len(self.RawDataList) - 1) + len(self.RawDataList[len(self.RawDataList)-1])
499        else:
500            for Datas in self.RawDataList:
501                if type(Datas) in (list, tuple):
502                    self.ListSize += len(Datas) * self.ItemSize
503                else:
504                    self.ListSize += self.ItemSize
505        return self.ListSize
506
507## DbSkuHeadTableItemList
508#
509#  The class holds the Sku header value table
510#
511class DbSkuHeadTableItemList (DbItemList):
512    def __init__(self, ItemSize, DataList=None, RawDataList=None):
513        if DataList is None:
514            DataList = []
515        if RawDataList is None:
516            RawDataList = []
517        DbItemList.__init__(self, ItemSize, DataList, RawDataList)
518    def PackData(self):
519        PackStr = "=LL"
520        Buffer = ''
521        for Data in self.RawDataList:
522            Buffer += pack(PackStr,
523                           GetIntegerValue(Data[0]),
524                           GetIntegerValue(Data[1]))
525        return Buffer
526
527## DbSizeTableItemList
528#
529#  The class holds the size table
530#
531class DbSizeTableItemList (DbItemList):
532    def __init__(self, ItemSize, DataList=None, RawDataList=None):
533        if DataList is None:
534            DataList = []
535        if RawDataList is None:
536            RawDataList = []
537        DbItemList.__init__(self, ItemSize, DataList, RawDataList)
538    def GetListSize(self):
539        length = 0
540        for Data in self.RawDataList:
541            length += (1 + len(Data[1]))
542        return length * self.ItemSize
543    def PackData(self):
544        PackStr = "=H"
545        Buffer = ''
546        for Data in self.RawDataList:
547            Buffer += pack(PackStr,
548                           GetIntegerValue(Data[0]))
549            for subData in Data[1]:
550                Buffer += pack(PackStr,
551                           GetIntegerValue(subData))
552        return Buffer
553
554## DbStringItemList
555#
556#  The class holds the string table
557#
558class DbStringItemList (DbComItemList):
559    def __init__(self, ItemSize, DataList=None, RawDataList=None, LenList=None):
560        if DataList is None:
561            DataList = []
562        if RawDataList is None:
563            RawDataList = []
564        if LenList is None:
565            LenList = []
566
567        assert(len(RawDataList) == len(LenList))
568        DataList = []
569        # adjust DataList according to the LenList
570        for Index in xrange(len(RawDataList)):
571            Len = LenList[Index]
572            RawDatas = RawDataList[Index]
573            assert(Len >= len(RawDatas))
574            ActualDatas = []
575            for i in xrange(len(RawDatas)):
576                ActualDatas.append(RawDatas[i])
577            for i in xrange(len(RawDatas), Len):
578                ActualDatas.append(0)
579            DataList.append(ActualDatas)
580        self.LenList = LenList
581        DbComItemList.__init__(self, ItemSize, DataList, RawDataList)
582    def GetInterOffset(self, Index):
583        Offset = 0
584
585        assert(Index < len(self.LenList))
586        for ItemIndex in xrange(Index):
587            Offset += self.LenList[ItemIndex]
588
589        return Offset
590
591    def GetListSize(self):
592        if self.ListSize:
593            return self.ListSize
594
595        if len(self.LenList) == 0:
596            self.ListSize = 0
597        else:
598            self.ListSize = self.GetInterOffset(len(self.LenList) - 1) + self.LenList[len(self.LenList)-1]
599
600        return self.ListSize
601
602    def PackData(self):
603        self.RawDataList = self.DataList
604        return DbComItemList.PackData(self)
605
606
607
608##  Find the index in two list where the item matches the key separately
609#
610#   @param      Key1   The key used to search the List1
611#   @param      List1  The list that Key1 will be searched
612#   @param      Key2   The key used to search the List2
613#   @param      List2  The list that Key2 will be searched
614#
615#   @retval     Index  The position inside the list where list1[Index] == Key1 and list2[Index] == Key2
616#
617def GetMatchedIndex(Key1, List1, Key2, List2):
618    StartPos = 0
619    while StartPos < len(List1):
620        Index = List1.index(Key1, StartPos)
621        if List2[Index] == Key2:
622            return Index
623        else:
624            StartPos = Index + 1
625
626    return -1
627
628
629##  Get the integer value from string like "14U" or integer like 2
630#
631#   @param      Input   The object that may be either a integer value or a string
632#
633#   @retval     Value    The integer value that the input represents
634#
635def GetIntegerValue(Input):
636    if type(Input) in (int, long):
637        return Input
638    String = Input
639    if String.endswith("U"):
640        String = String[:-1]
641    if String.endswith("ULL"):
642        String = String[:-3]
643    if String.endswith("LL"):
644        String = String[:-2]
645
646    if String.startswith("0x") or String.startswith("0X"):
647        return int(String, 16)
648    elif String == '':
649        return 0
650    else:
651        return int(String)
652
653
654## convert StringArray like {0x36, 0x00, 0x34, 0x00, 0x21, 0x00, 0x36, 0x00, 0x34, 0x00, 0x00, 0x00}
655# to List like [0x36, 0x00, 0x34, 0x00, 0x21, 0x00, 0x36, 0x00, 0x34, 0x00, 0x00, 0x00]
656#
657#   @param      StringArray A string array like {0x36, 0x00, 0x34, 0x00, 0x21, 0x00, 0x36, 0x00, 0x34, 0x00, 0x00, 0x00}
658#
659#   @retval                 A list object of integer items
660#
661def StringArrayToList(StringArray):
662    StringArray = StringArray[1:-1]
663    StringArray = '[' + StringArray + ']'
664    return eval(StringArray)
665
666
667## Convert TokenType String like  "PCD_DATUM_TYPE_UINT32 | PCD_TYPE_HII" to TokenType value
668#
669#   @param      TokenType  A TokenType string like "PCD_DATUM_TYPE_UINT32 | PCD_TYPE_HII"
670#
671#   @retval                A integer representation of the TokenType
672#
673def GetTokenTypeValue(TokenType):
674    TokenTypeDict = {
675        "PCD_TYPE_SHIFT":28,
676        "PCD_TYPE_DATA":(0x0 << 28),
677        "PCD_TYPE_HII":(0x8 << 28),
678        "PCD_TYPE_VPD":(0x4 << 28),
679        "PCD_TYPE_SKU_ENABLED":(0x2 << 28),
680        "PCD_TYPE_STRING":(0x1 << 28),
681
682        "PCD_DATUM_TYPE_SHIFT":24,
683        "PCD_DATUM_TYPE_POINTER":(0x0 << 24),
684        "PCD_DATUM_TYPE_UINT8":(0x1 << 24),
685        "PCD_DATUM_TYPE_UINT16":(0x2 << 24),
686        "PCD_DATUM_TYPE_UINT32":(0x4 << 24),
687        "PCD_DATUM_TYPE_UINT64":(0x8 << 24),
688
689        "PCD_DATUM_TYPE_SHIFT2":20,
690        "PCD_DATUM_TYPE_UINT8_BOOLEAN":(0x1 << 20 | 0x1 << 24),
691        }
692    return eval(TokenType, TokenTypeDict)
693
694## construct the external Pcd database using data from Dict
695#
696#   @param      Dict  A dictionary contains Pcd related tables
697#
698#   @retval     Buffer A byte stream of the Pcd database
699#
700def BuildExDataBase(Dict):
701    # init Db items
702    InitValueUint64 = Dict['INIT_DB_VALUE_UINT64']
703    DbInitValueUint64 = DbComItemList(8, RawDataList = InitValueUint64)
704    VardefValueUint64 = Dict['VARDEF_DB_VALUE_UINT64']
705    DbVardefValueUint64 = DbItemList(8, RawDataList = VardefValueUint64)
706    InitValueUint32 = Dict['INIT_DB_VALUE_UINT32']
707    DbInitValueUint32 = DbComItemList(4, RawDataList = InitValueUint32)
708    VardefValueUint32 = Dict['VARDEF_DB_VALUE_UINT32']
709    DbVardefValueUint32 = DbItemList(4, RawDataList = VardefValueUint32)
710    VpdHeadValue = Dict['VPD_DB_VALUE']
711    DbVpdHeadValue = DbComItemList(4, RawDataList = VpdHeadValue)
712    ExMapTable = zip(Dict['EXMAPPING_TABLE_EXTOKEN'], Dict['EXMAPPING_TABLE_LOCAL_TOKEN'], Dict['EXMAPPING_TABLE_GUID_INDEX'])
713    DbExMapTable = DbExMapTblItemList(8, RawDataList = ExMapTable)
714    LocalTokenNumberTable = Dict['LOCAL_TOKEN_NUMBER_DB_VALUE']
715    DbLocalTokenNumberTable = DbItemList(4, RawDataList = LocalTokenNumberTable)
716    GuidTable = Dict['GUID_STRUCTURE']
717    DbGuidTable = DbItemList(16, RawDataList = GuidTable)
718    StringHeadValue = Dict['STRING_DB_VALUE']
719    # DbItemList to DbStringHeadTableItemList
720    DbStringHeadValue = DbStringHeadTableItemList(4, RawDataList = StringHeadValue)
721    VariableTable = Dict['VARIABLE_DB_VALUE']
722    DbVariableTable = DbVariableTableItemList(20, RawDataList = VariableTable)
723    NumberOfSkuEnabledPcd = GetIntegerValue(Dict['SKU_HEAD_SIZE'])
724    Dict['SKUHEAD_TABLE_VALUE'] = [(0,0) for i in xrange(NumberOfSkuEnabledPcd)]
725    SkuTable = Dict['SKUHEAD_TABLE_VALUE']  # Generated later
726    DbSkuTable = DbSkuHeadTableItemList(8, RawDataList = SkuTable)
727    Dict['STRING_TABLE_DB_VALUE'] = [StringArrayToList(x) for x in Dict['STRING_TABLE_VALUE']]
728
729    StringTableValue = Dict['STRING_TABLE_DB_VALUE']
730    # when calcute the offset, should use StringTableLen instead of StringTableValue, as string maxium len may be different with actual len
731    StringTableLen = Dict['STRING_TABLE_LENGTH']
732    DbStringTableLen = DbStringItemList(0, RawDataList = StringTableValue, LenList = StringTableLen)
733
734
735    PcdTokenTable = Dict['PCD_TOKENSPACE']
736    PcdTokenLen = Dict['PCD_TOKENSPACE_LENGTH']
737    PcdTokenTableValue = [StringArrayToList(x) for x in Dict['PCD_TOKENSPACE']]
738    DbPcdTokenTable = DbStringItemList(0, RawDataList = PcdTokenTableValue, LenList = PcdTokenLen)
739
740    PcdCNameTable = Dict['PCD_CNAME']
741    PcdCNameLen = Dict['PCD_CNAME_LENGTH']
742    PcdCNameTableValue = [StringArrayToList(x) for x in Dict['PCD_CNAME']]
743    DbPcdCNameTable = DbStringItemList(0, RawDataList = PcdCNameTableValue, LenList = PcdCNameLen)
744
745    PcdNameOffsetTable = Dict['PCD_NAME_OFFSET']
746    DbPcdNameOffsetTable = DbItemList(4,RawDataList = PcdNameOffsetTable)
747
748    SizeTableValue = zip(Dict['SIZE_TABLE_MAXIMUM_LENGTH'], Dict['SIZE_TABLE_CURRENT_LENGTH'])
749    DbSizeTableValue = DbSizeTableItemList(2, RawDataList = SizeTableValue)
750    InitValueUint16 = Dict['INIT_DB_VALUE_UINT16']
751    DbInitValueUint16 = DbComItemList(2, RawDataList = InitValueUint16)
752    VardefValueUint16 = Dict['VARDEF_DB_VALUE_UINT16']
753    DbVardefValueUint16 = DbItemList(2, RawDataList = VardefValueUint16)
754    InitValueUint8 = Dict['INIT_DB_VALUE_UINT8']
755    DbInitValueUint8 = DbComItemList(1, RawDataList = InitValueUint8)
756    VardefValueUint8 = Dict['VARDEF_DB_VALUE_UINT8']
757    DbVardefValueUint8 = DbItemList(1, RawDataList = VardefValueUint8)
758    InitValueBoolean = Dict['INIT_DB_VALUE_BOOLEAN']
759    DbInitValueBoolean = DbComItemList(1, RawDataList = InitValueBoolean)
760    VardefValueBoolean = Dict['VARDEF_DB_VALUE_BOOLEAN']
761    DbVardefValueBoolean = DbItemList(1, RawDataList = VardefValueBoolean)
762    SkuidValue = Dict['SKUID_VALUE']
763    DbSkuidValue = DbItemList(1, RawDataList = SkuidValue)
764    SkuIndexValue = Dict['SKU_INDEX_VALUE']
765    DbSkuIndexValue = DbItemList(0,RawDataList = SkuIndexValue)
766
767    # Unit Db Items
768    UnInitValueUint64 = Dict['UNINIT_GUID_DECL_UINT64']
769    DbUnInitValueUint64 = DbItemList(8, RawDataList = UnInitValueUint64)
770    UnInitValueUint32 = Dict['UNINIT_GUID_DECL_UINT32']
771    DbUnInitValueUint32 = DbItemList(4, RawDataList = UnInitValueUint32)
772    UnInitValueUint16 = Dict['UNINIT_GUID_DECL_UINT16']
773    DbUnInitValueUint16 = DbItemList(2, RawDataList = UnInitValueUint16)
774    UnInitValueUint8 = Dict['UNINIT_GUID_DECL_UINT8']
775    DbUnInitValueUint8 = DbItemList(1, RawDataList = UnInitValueUint8)
776    UnInitValueBoolean = Dict['UNINIT_GUID_DECL_BOOLEAN']
777    DbUnInitValueBoolean = DbItemList(1, RawDataList = UnInitValueBoolean)
778    PcdTokenNumberMap = Dict['PCD_ORDER_TOKEN_NUMBER_MAP']
779
780    DbNameTotle = ["InitValueUint64", "VardefValueUint64", "InitValueUint32", "VardefValueUint32", "VpdHeadValue", "ExMapTable",
781               "LocalTokenNumberTable", "GuidTable", "StringHeadValue",  "PcdNameOffsetTable","VariableTable","SkuTable", "StringTableLen", "PcdTokenTable", "PcdCNameTable",
782               "SizeTableValue", "InitValueUint16", "VardefValueUint16", "InitValueUint8", "VardefValueUint8", "InitValueBoolean",
783               "VardefValueBoolean", "SkuidValue", "SkuIndexValue","UnInitValueUint64", "UnInitValueUint32", "UnInitValueUint16", "UnInitValueUint8", "UnInitValueBoolean"]
784
785    DbTotal = [InitValueUint64, VardefValueUint64, InitValueUint32, VardefValueUint32, VpdHeadValue, ExMapTable,
786               LocalTokenNumberTable, GuidTable, StringHeadValue,  PcdNameOffsetTable,VariableTable,SkuTable, StringTableLen, PcdTokenTable,PcdCNameTable,
787               SizeTableValue, InitValueUint16, VardefValueUint16, InitValueUint8, VardefValueUint8, InitValueBoolean,
788               VardefValueBoolean, SkuidValue, SkuIndexValue, UnInitValueUint64, UnInitValueUint32, UnInitValueUint16, UnInitValueUint8, UnInitValueBoolean]
789    DbItemTotal = [DbInitValueUint64, DbVardefValueUint64, DbInitValueUint32, DbVardefValueUint32, DbVpdHeadValue, DbExMapTable,
790               DbLocalTokenNumberTable, DbGuidTable, DbStringHeadValue,  DbPcdNameOffsetTable,DbVariableTable,DbSkuTable, DbStringTableLen, DbPcdTokenTable, DbPcdCNameTable,
791               DbSizeTableValue, DbInitValueUint16, DbVardefValueUint16, DbInitValueUint8, DbVardefValueUint8, DbInitValueBoolean,
792               DbVardefValueBoolean, DbSkuidValue, DbSkuIndexValue, DbUnInitValueUint64, DbUnInitValueUint32, DbUnInitValueUint16, DbUnInitValueUint8, DbUnInitValueBoolean]
793
794    # SkuidValue is the last table in the init table items
795    InitTableNum = DbTotal.index(SkuidValue) + 1 + 1 # +1 is for SkuIndexValue table
796    # The FixedHeader length of the PCD_DATABASE_INIT, from Signature to Pad
797    FixedHeaderLen = 64
798
799    # Get offset of SkuId table in the database
800    SkuIdTableOffset = FixedHeaderLen
801    for DbIndex in xrange(len(DbTotal)):
802        if DbTotal[DbIndex] is SkuidValue:
803            break
804        SkuIdTableOffset += DbItemTotal[DbIndex].GetListSize()
805
806
807    # Get offset of SkuValue table in the database
808    SkuTableOffset = FixedHeaderLen
809    for DbIndex in xrange(len(DbTotal)):
810        if DbTotal[DbIndex] is SkuTable:
811            break
812        SkuTableOffset += DbItemTotal[DbIndex].GetListSize()
813    PcdTokenTableDbOffset = FixedHeaderLen
814    for DbIndex in xrange(len(DbTotal)):
815        if DbTotal[DbIndex] is PcdTokenTable:
816            break
817        PcdTokenTableDbOffset += DbItemTotal[DbIndex].GetListSize()
818
819    PcdCNameTableDbOffset = FixedHeaderLen
820    for DbIndex in xrange(len(DbTotal)):
821        if DbTotal[DbIndex] is PcdCNameTable:
822            break
823        PcdCNameTableDbOffset += DbItemTotal[DbIndex].GetListSize()
824    # Fix up the LocalTokenNumberTable, SkuHeader table
825    SkuHeaderIndex = 0
826    if len(Dict['SKU_INDEX_VALUE']) > 0:
827        SkuIndexIndexTable = [(0) for i in xrange(len(Dict['SKU_INDEX_VALUE']))]
828        SkuIndexIndexTable[0] = 0  #Dict['SKU_INDEX_VALUE'][0][0]
829        for i in range(1,len(Dict['SKU_INDEX_VALUE'])):
830            SkuIndexIndexTable[i] = SkuIndexIndexTable[i-1]+Dict['SKU_INDEX_VALUE'][i-1][0] + 1
831    for (LocalTokenNumberTableIndex, (Offset, Table)) in enumerate(LocalTokenNumberTable):
832        DbIndex = 0
833        DbOffset = FixedHeaderLen
834        for DbIndex in xrange(len(DbTotal)):
835            if DbTotal[DbIndex] is Table:
836                DbOffset += DbItemTotal[DbIndex].GetInterOffset(Offset)
837                break
838            DbOffset += DbItemTotal[DbIndex].GetListSize()
839            if DbIndex + 1 == InitTableNum:
840                if DbOffset % 8:
841                    DbOffset += (8 - DbOffset % 8)
842        else:
843            assert(False)
844
845        TokenTypeValue = Dict['TOKEN_TYPE'][LocalTokenNumberTableIndex]
846        TokenTypeValue = GetTokenTypeValue(TokenTypeValue)
847        LocalTokenNumberTable[LocalTokenNumberTableIndex] = DbOffset|int(TokenTypeValue)
848        # if PCD_TYPE_SKU_ENABLED, then we need to fix up the SkuTable
849
850        SkuIndexTabalOffset = SkuIdTableOffset + Dict['SKUID_VALUE'][0] + 1
851        if (TokenTypeValue & (0x2 << 28)):
852            SkuTable[SkuHeaderIndex] = (DbOffset|int(TokenTypeValue & ~(0x2<<28)), SkuIndexTabalOffset + SkuIndexIndexTable[PcdTokenNumberMap[LocalTokenNumberTableIndex]])
853            LocalTokenNumberTable[LocalTokenNumberTableIndex] = (SkuTableOffset + SkuHeaderIndex * 8) | int(TokenTypeValue)
854            SkuHeaderIndex += 1
855
856
857    if SkuHeaderIndex == 0:
858        SkuHeaderIndex = 1
859    assert(SkuHeaderIndex == NumberOfSkuEnabledPcd)
860
861    # resolve variable table offset
862    for VariableEntries in VariableTable:
863        skuindex = 0
864        for VariableEntryPerSku in VariableEntries:
865            (VariableHeadGuidIndex, VariableHeadStringIndex, SKUVariableOffset, VariableOffset, VariableRefTable, VariableAttribute) = VariableEntryPerSku[:]
866            DbIndex = 0
867            DbOffset = FixedHeaderLen
868            for DbIndex in xrange(len(DbTotal)):
869                if DbTotal[DbIndex] is VariableRefTable:
870                    DbOffset += DbItemTotal[DbIndex].GetInterOffset(VariableOffset)
871                    break
872                DbOffset += DbItemTotal[DbIndex].GetListSize()
873                if DbIndex + 1 == InitTableNum:
874                    if DbOffset % 8:
875                        DbOffset += (8 - DbOffset % 8)
876            else:
877                assert(False)
878            if isinstance(VariableRefTable[0],list):
879                DbOffset += skuindex * 4
880            skuindex += 1
881            if DbIndex >= InitTableNum:
882                assert(False)
883            VarAttr, VarProp = VariableAttributes.GetVarAttributes(VariableAttribute)
884            VariableEntryPerSku[:] = (VariableHeadStringIndex, DbOffset, VariableHeadGuidIndex, SKUVariableOffset, VarAttr, VarProp)
885
886    # calculate various table offset now
887    DbTotalLength = FixedHeaderLen
888    for DbIndex in xrange(len(DbItemTotal)):
889        if DbItemTotal[DbIndex] is DbLocalTokenNumberTable:
890            LocalTokenNumberTableOffset = DbTotalLength
891        elif DbItemTotal[DbIndex] is DbExMapTable:
892            ExMapTableOffset = DbTotalLength
893        elif DbItemTotal[DbIndex] is DbGuidTable:
894            GuidTableOffset = DbTotalLength
895        elif DbItemTotal[DbIndex] is DbStringTableLen:
896            StringTableOffset = DbTotalLength
897        elif DbItemTotal[DbIndex] is DbSizeTableValue:
898            SizeTableOffset = DbTotalLength
899        elif DbItemTotal[DbIndex] is DbSkuidValue:
900            SkuIdTableOffset = DbTotalLength
901        elif DbItemTotal[DbIndex] is DbPcdNameOffsetTable:
902            DbPcdNameOffset = DbTotalLength
903
904        DbTotalLength += DbItemTotal[DbIndex].GetListSize()
905    if not Dict['PCD_INFO_FLAG']:
906        DbPcdNameOffset  = 0
907    LocalTokenCount = GetIntegerValue(Dict['LOCAL_TOKEN_NUMBER'])
908    ExTokenCount = GetIntegerValue(Dict['EX_TOKEN_NUMBER'])
909    GuidTableCount = GetIntegerValue(Dict['GUID_TABLE_SIZE'])
910    SystemSkuId = GetIntegerValue(Dict['SYSTEM_SKU_ID_VALUE'])
911    Pad = 0xDA
912
913    UninitDataBaseSize  = 0
914    for Item in (DbUnInitValueUint64, DbUnInitValueUint32, DbUnInitValueUint16, DbUnInitValueUint8, DbUnInitValueBoolean):
915        UninitDataBaseSize += Item.GetListSize()
916
917    if (DbTotalLength - UninitDataBaseSize) % 8:
918        DbTotalLength += (8 - (DbTotalLength - UninitDataBaseSize) % 8)
919    # Construct the database buffer
920    Guid = "{0x3c7d193c, 0x682c, 0x4c14, 0xa6, 0x8f, 0x55, 0x2d, 0xea, 0x4f, 0x43, 0x7e}"
921    Guid = StringArrayToList(Guid)
922    Buffer = pack('=LHHBBBBBBBB',
923                Guid[0],
924                Guid[1],
925                Guid[2],
926                Guid[3],
927                Guid[4],
928                Guid[5],
929                Guid[6],
930                Guid[7],
931                Guid[8],
932                Guid[9],
933                Guid[10],
934                )
935
936    b = pack("=L", DATABASE_VERSION)
937    Buffer += b
938
939    b = pack('=L', DbTotalLength - UninitDataBaseSize)
940
941    Buffer += b
942    b = pack('=L', UninitDataBaseSize)
943
944    Buffer += b
945    b = pack('=L', LocalTokenNumberTableOffset)
946
947    Buffer += b
948    b = pack('=L', ExMapTableOffset)
949
950    Buffer += b
951    b = pack('=L', GuidTableOffset)
952
953    Buffer += b
954    b = pack('=L', StringTableOffset)
955
956    Buffer += b
957    b = pack('=L', SizeTableOffset)
958
959    Buffer += b
960    b = pack('=L', SkuIdTableOffset)
961
962    Buffer += b
963    b = pack('=L', DbPcdNameOffset)
964
965    Buffer += b
966    b = pack('=H', LocalTokenCount)
967
968    Buffer += b
969    b = pack('=H', ExTokenCount)
970
971    Buffer += b
972    b = pack('=H', GuidTableCount)
973
974    Buffer += b
975    b = pack('=B', SystemSkuId)
976
977    Buffer += b
978    b = pack('=B', Pad)
979
980    Buffer += b
981
982    Index = 0
983    for Item in DbItemTotal:
984        Index +=1
985        b = Item.PackData()
986        Buffer += b
987        if Index == InitTableNum:
988            if len(Buffer) % 8:
989                for num in range(8 - len(Buffer) % 8):
990                    b = pack('=B', Pad)
991                    Buffer += b
992            break
993    return Buffer
994
995## Create code for PCD database
996#
997#   @param      Info        The ModuleAutoGen object
998#   @param      AutoGenC    The TemplateString object for C code
999#   @param      AutoGenH    The TemplateString object for header file
1000#
1001def CreatePcdDatabaseCode (Info, AutoGenC, AutoGenH):
1002    if Info.PcdIsDriver == "":
1003        return
1004    if Info.PcdIsDriver not in gPcdPhaseMap:
1005        EdkLogger.error("build", AUTOGEN_ERROR, "Not supported PcdIsDriver type:%s" % Info.PcdIsDriver,
1006                        ExtraData="[%s]" % str(Info))
1007
1008    AdditionalAutoGenH, AdditionalAutoGenC, PcdDbBuffer = CreatePcdDatabasePhaseSpecificAutoGen (Info.PlatformInfo, 'PEI')
1009    AutoGenH.Append(AdditionalAutoGenH.String)
1010
1011    Phase = gPcdPhaseMap[Info.PcdIsDriver]
1012    if Phase == 'PEI':
1013        AutoGenC.Append(AdditionalAutoGenC.String)
1014
1015    if Phase == 'DXE':
1016        AdditionalAutoGenH, AdditionalAutoGenC, PcdDbBuffer = CreatePcdDatabasePhaseSpecificAutoGen (Info.PlatformInfo, Phase)
1017        AutoGenH.Append(AdditionalAutoGenH.String)
1018        AutoGenC.Append(AdditionalAutoGenC.String)
1019
1020    if Info.IsBinaryModule:
1021        DbFileName = os.path.join(Info.PlatformInfo.BuildDir, "FV", Phase + "PcdDataBase.raw")
1022    else:
1023        DbFileName = os.path.join(Info.OutputDir, Phase + "PcdDataBase.raw")
1024    DbFile = StringIO()
1025    DbFile.write(PcdDbBuffer)
1026    Changed = SaveFileOnChange(DbFileName, DbFile.getvalue(), True)
1027
1028## Create PCD database in DXE or PEI phase
1029#
1030#   @param      Platform    The platform object
1031#   @retval     tuple       Two TemplateString objects for C code and header file,
1032#                           respectively
1033#
1034def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
1035    AutoGenC = TemplateString()
1036    AutoGenH = TemplateString()
1037
1038    Dict = {
1039        'PHASE'                         : Phase,
1040        'SERVICE_DRIVER_VERSION'        : DATABASE_VERSION,
1041        'GUID_TABLE_SIZE'               : '1U',
1042        'STRING_TABLE_SIZE'             : '1U',
1043        'SKUID_TABLE_SIZE'              : '1U',
1044        'LOCAL_TOKEN_NUMBER_TABLE_SIZE' : '0U',
1045        'LOCAL_TOKEN_NUMBER'            : '0U',
1046        'EXMAPPING_TABLE_SIZE'          : '1U',
1047        'EX_TOKEN_NUMBER'               : '0U',
1048        'SIZE_TABLE_SIZE'               : '2U',
1049        'SKU_HEAD_SIZE'                 : '1U',
1050        'GUID_TABLE_EMPTY'              : 'TRUE',
1051        'STRING_TABLE_EMPTY'            : 'TRUE',
1052        'SKUID_TABLE_EMPTY'             : 'TRUE',
1053        'DATABASE_EMPTY'                : 'TRUE',
1054        'EXMAP_TABLE_EMPTY'             : 'TRUE',
1055        'PCD_DATABASE_UNINIT_EMPTY'     : '  UINT8  dummy; /* PCD_DATABASE_UNINIT is emptry */',
1056        'SYSTEM_SKU_ID'                 : '  SKU_ID             SystemSkuId;',
1057        'SYSTEM_SKU_ID_VALUE'           : '0U'
1058    }
1059
1060
1061    SkuObj = SkuClass(Platform.Platform.AvilableSkuIds, Platform.Platform.SkuIds)
1062    Dict['SYSTEM_SKU_ID_VALUE'] = Platform.Platform.SkuIds[SkuObj.SystemSkuId]
1063
1064    Dict['PCD_INFO_FLAG'] = Platform.Platform.PcdInfoFlag
1065
1066    for DatumType in ['UINT64','UINT32','UINT16','UINT8','BOOLEAN', "VOID*"]:
1067        Dict['VARDEF_CNAME_' + DatumType] = []
1068        Dict['VARDEF_GUID_' + DatumType]  = []
1069        Dict['VARDEF_SKUID_' + DatumType] = []
1070        Dict['VARDEF_VALUE_' + DatumType] = []
1071        Dict['VARDEF_DB_VALUE_' + DatumType] = []
1072        for Init in ['INIT','UNINIT']:
1073            Dict[Init+'_CNAME_DECL_' + DatumType]   = []
1074            Dict[Init+'_GUID_DECL_' + DatumType]    = []
1075            Dict[Init+'_NUMSKUS_DECL_' + DatumType] = []
1076            Dict[Init+'_VALUE_' + DatumType]        = []
1077            Dict[Init+'_DB_VALUE_'+DatumType] = []
1078
1079    for Type in ['STRING_HEAD','VPD_HEAD','VARIABLE_HEAD']:
1080        Dict[Type + '_CNAME_DECL']   = []
1081        Dict[Type + '_GUID_DECL']    = []
1082        Dict[Type + '_NUMSKUS_DECL'] = []
1083        Dict[Type + '_VALUE'] = []
1084
1085    Dict['STRING_DB_VALUE'] = []
1086    Dict['VPD_DB_VALUE'] = []
1087    Dict['VARIABLE_DB_VALUE'] = []
1088
1089    Dict['STRING_TABLE_INDEX'] = []
1090    Dict['STRING_TABLE_LENGTH']  = []
1091    Dict['STRING_TABLE_CNAME'] = []
1092    Dict['STRING_TABLE_GUID']  = []
1093    Dict['STRING_TABLE_VALUE'] = []
1094    Dict['STRING_TABLE_DB_VALUE'] = []
1095
1096    Dict['SIZE_TABLE_CNAME'] = []
1097    Dict['SIZE_TABLE_GUID']  = []
1098    Dict['SIZE_TABLE_CURRENT_LENGTH']  = []
1099    Dict['SIZE_TABLE_MAXIMUM_LENGTH']  = []
1100
1101    Dict['EXMAPPING_TABLE_EXTOKEN'] = []
1102    Dict['EXMAPPING_TABLE_LOCAL_TOKEN'] = []
1103    Dict['EXMAPPING_TABLE_GUID_INDEX'] = []
1104
1105    Dict['GUID_STRUCTURE'] = []
1106    Dict['SKUID_VALUE'] = [0] # init Dict length
1107    Dict['VARDEF_HEADER'] = []
1108
1109    Dict['LOCAL_TOKEN_NUMBER_DB_VALUE'] = []
1110    Dict['VARIABLE_DB_VALUE'] = []
1111    Dict['SKUHEAD_TABLE_VALUE'] = []
1112    Dict['SKU_INDEX_VALUE'] = []
1113
1114    Dict['PCD_TOKENSPACE'] = []
1115    Dict['PCD_CNAME'] = []
1116    Dict['PCD_TOKENSPACE_LENGTH'] = []
1117    Dict['PCD_CNAME_LENGTH'] = []
1118    Dict['PCD_TOKENSPACE_OFFSET'] = []
1119    Dict['PCD_CNAME_OFFSET'] = []
1120    Dict['PCD_TOKENSPACE_MAP'] = []
1121    Dict['PCD_NAME_OFFSET'] = []
1122
1123    Dict['PCD_ORDER_TOKEN_NUMBER_MAP'] = {}
1124    PCD_STRING_INDEX_MAP = {}
1125
1126    StringTableIndex = 0
1127    StringTableSize = 0
1128    NumberOfLocalTokens = 0
1129    NumberOfPeiLocalTokens = 0
1130    NumberOfDxeLocalTokens = 0
1131    NumberOfExTokens = 0
1132    NumberOfSizeItems = 0
1133    NumberOfSkuEnabledPcd = 0
1134    GuidList = []
1135    VarCheckTab = VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER()
1136    i = 0
1137    ReorderedDynPcdList = GetOrderedDynamicPcdList(Platform.DynamicPcdList, Platform.PcdTokenNumber)
1138    for Pcd in ReorderedDynPcdList:
1139        VoidStarTypeCurrSize = []
1140        i += 1
1141        CName = Pcd.TokenCName
1142        TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName
1143
1144        EdkLogger.debug(EdkLogger.DEBUG_3, "PCD: %s %s (%s : %s)" % (CName, TokenSpaceGuidCName, Pcd.Phase, Phase))
1145
1146        if Pcd.Phase == 'PEI':
1147            NumberOfPeiLocalTokens += 1
1148        if Pcd.Phase == 'DXE':
1149            NumberOfDxeLocalTokens += 1
1150        if Pcd.Phase != Phase:
1151            continue
1152
1153        #
1154        # TODO: need GetGuidValue() definition
1155        #
1156        TokenSpaceGuidStructure = Pcd.TokenSpaceGuidValue
1157        TokenSpaceGuid = GuidStructureStringToGuidValueName(TokenSpaceGuidStructure)
1158        if Pcd.Type in gDynamicExPcd:
1159            if TokenSpaceGuid not in GuidList:
1160                GuidList += [TokenSpaceGuid]
1161                Dict['GUID_STRUCTURE'].append(TokenSpaceGuidStructure)
1162            NumberOfExTokens += 1
1163
1164        ValueList = []
1165        DbValueList = []
1166        StringHeadOffsetList = []
1167        StringDbOffsetList = []
1168        VpdHeadOffsetList = []
1169        VpdDbOffsetList = []
1170        VariableHeadValueList = []
1171        VariableDbValueList = []
1172        Pcd.InitString = 'UNINIT'
1173
1174        if Pcd.DatumType == 'VOID*':
1175            if Pcd.Type not in ["DynamicVpd", "DynamicExVpd"]:
1176                Pcd.TokenTypeList = ['PCD_TYPE_STRING']
1177            else:
1178                Pcd.TokenTypeList = []
1179        elif Pcd.DatumType == 'BOOLEAN':
1180            Pcd.TokenTypeList = ['PCD_DATUM_TYPE_UINT8_BOOLEAN']
1181        else:
1182            Pcd.TokenTypeList = ['PCD_DATUM_TYPE_' + Pcd.DatumType]
1183
1184        if len(Pcd.SkuInfoList) > 1:
1185            Pcd.TokenTypeList += ['PCD_TYPE_SKU_ENABLED']
1186            NumberOfSkuEnabledPcd += 1
1187
1188        SkuIndexTableTmp = []
1189        SkuIndexTableTmp.append(0)
1190        SkuIdIndex = 1
1191        VariableHeadList = []
1192        for SkuName in Pcd.SkuInfoList:
1193            Sku = Pcd.SkuInfoList[SkuName]
1194            SkuId = Sku.SkuId
1195            if SkuId == None or SkuId == '':
1196                continue
1197
1198            if (SkuId + 'U') not in Dict['SKUID_VALUE']:
1199                Dict['SKUID_VALUE'].append(SkuId + 'U')
1200
1201            SkuIndexTableTmp.append(SkuId+'U')
1202            SkuIdIndex += 1
1203
1204            if len(Sku.VariableName) > 0:
1205                VariableGuidStructure = Sku.VariableGuidValue
1206                VariableGuid = GuidStructureStringToGuidValueName(VariableGuidStructure)
1207                if Platform.Platform.VarCheckFlag:
1208                    var_check_obj = VAR_CHECK_PCD_VARIABLE_TAB(VariableGuidStructure, StringToArray(Sku.VariableName))
1209                    try:
1210                        var_check_obj.push_back(VAR_VALID_OBJECT_FACTORY.Get_valid_object(Pcd, Sku.VariableOffset))
1211                        VarAttr, _ = VariableAttributes.GetVarAttributes(Sku.VariableAttribute)
1212                        var_check_obj.SetAttributes(VarAttr)
1213                        var_check_obj.UpdateSize()
1214                        VarCheckTab.push_back(var_check_obj)
1215                    except Exception:
1216                        ValidInfo = ''
1217                        if Pcd.validateranges:
1218                            ValidInfo = Pcd.validateranges[0]
1219                        if Pcd.validlists:
1220                            ValidInfo = Pcd.validlists[0]
1221                        if ValidInfo:
1222                            EdkLogger.error("build", PCD_VALIDATION_INFO_ERROR,
1223                                                "The PCD '%s.%s' Validation information defined in DEC file has incorrect format." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName),
1224                                                ExtraData = "[%s]" % str(ValidInfo))
1225                        else:
1226                            EdkLogger.error("build", PCD_VALIDATION_INFO_ERROR,
1227                                                "The PCD '%s.%s' Validation information defined in DEC file has incorrect format." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
1228                Pcd.TokenTypeList += ['PCD_TYPE_HII']
1229                Pcd.InitString = 'INIT'
1230                # Store all variable names of one HII PCD under different SKU to stringTable
1231                # and calculate the VariableHeadStringIndex
1232                if SkuIdIndex - 2 == 0:
1233                    for SkuName2 in Pcd.SkuInfoList:
1234                        SkuInfo = Pcd.SkuInfoList[SkuName2]
1235                        if SkuInfo.SkuId == None or SkuInfo.SkuId == '':
1236                            continue
1237                        VariableNameStructure = StringToArray(SkuInfo.VariableName)
1238                        if VariableNameStructure not in Dict['STRING_TABLE_VALUE']:
1239                            Dict['STRING_TABLE_CNAME'].append(CName)
1240                            Dict['STRING_TABLE_GUID'].append(TokenSpaceGuid)
1241                            if StringTableIndex == 0:
1242                                Dict['STRING_TABLE_INDEX'].append('')
1243                            else:
1244                                Dict['STRING_TABLE_INDEX'].append('_%d' % StringTableIndex)
1245                            VarNameSize = len(VariableNameStructure.replace(',',' ').split())
1246                            Dict['STRING_TABLE_LENGTH'].append(VarNameSize )
1247                            Dict['STRING_TABLE_VALUE'].append(VariableNameStructure)
1248                            StringHeadOffsetList.append(str(StringTableSize) + 'U')
1249                            VarStringDbOffsetList = []
1250                            VarStringDbOffsetList.append(StringTableSize)
1251                            Dict['STRING_DB_VALUE'].append(VarStringDbOffsetList)
1252                            StringTableIndex += 1
1253                            StringTableSize += len(VariableNameStructure.replace(',',' ').split())
1254                        VariableHeadStringIndex = 0
1255                        for Index in range(Dict['STRING_TABLE_VALUE'].index(VariableNameStructure)):
1256                            VariableHeadStringIndex += Dict['STRING_TABLE_LENGTH'][Index]
1257                        VariableHeadList.append(VariableHeadStringIndex)
1258
1259                VariableHeadStringIndex = VariableHeadList[SkuIdIndex - 2]
1260                # store VariableGuid to GuidTable and get the VariableHeadGuidIndex
1261
1262                if VariableGuid not in GuidList:
1263                    GuidList += [VariableGuid]
1264                    Dict['GUID_STRUCTURE'].append(VariableGuidStructure)
1265                VariableHeadGuidIndex = GuidList.index(VariableGuid)
1266
1267                if "PCD_TYPE_STRING" in Pcd.TokenTypeList:
1268                    VariableHeadValueList.append('%dU, offsetof(%s_PCD_DATABASE, Init.%s_%s), %dU, %sU' %
1269                                                 (VariableHeadStringIndex, Phase, CName, TokenSpaceGuid,
1270                                                 VariableHeadGuidIndex, Sku.VariableOffset))
1271                else:
1272                    VariableHeadValueList.append('%dU, offsetof(%s_PCD_DATABASE, Init.%s_%s_VariableDefault_%s), %dU, %sU' %
1273                                                 (VariableHeadStringIndex, Phase, CName, TokenSpaceGuid, SkuIdIndex,
1274                                                 VariableHeadGuidIndex, Sku.VariableOffset))
1275                Dict['VARDEF_CNAME_'+Pcd.DatumType].append(CName)
1276                Dict['VARDEF_GUID_'+Pcd.DatumType].append(TokenSpaceGuid)
1277                Dict['VARDEF_SKUID_'+Pcd.DatumType].append(SkuIdIndex)
1278                if "PCD_TYPE_STRING" in  Pcd.TokenTypeList:
1279                    Dict['VARDEF_VALUE_' + Pcd.DatumType].append("%s_%s[%d]" % (Pcd.TokenCName, TokenSpaceGuid, SkuIdIndex))
1280                else:
1281                    #
1282                    # ULL (for UINT64) or U(other integer type) should be append to avoid
1283                    # warning under linux building environment.
1284                    #
1285                    Dict['VARDEF_DB_VALUE_'+Pcd.DatumType].append(Sku.HiiDefaultValue)
1286
1287                    if Pcd.DatumType == "UINT64":
1288                        Dict['VARDEF_VALUE_'+Pcd.DatumType].append(Sku.HiiDefaultValue + "ULL")
1289                    elif Pcd.DatumType in ("UINT32", "UINT16", "UINT8"):
1290                        Dict['VARDEF_VALUE_'+Pcd.DatumType].append(Sku.HiiDefaultValue + "U")
1291                    elif Pcd.DatumType == "BOOLEAN":
1292                        if eval(Sku.HiiDefaultValue) in [1,0]:
1293                            Dict['VARDEF_VALUE_'+Pcd.DatumType].append(str(eval(Sku.HiiDefaultValue)) + "U")
1294                    else:
1295                        Dict['VARDEF_VALUE_'+Pcd.DatumType].append(Sku.HiiDefaultValue)
1296
1297                # construct the VariableHeader value
1298                if "PCD_TYPE_STRING" in Pcd.TokenTypeList:
1299                    VariableHeadValueList.append('%dU, %dU, %sU, offsetof(%s_PCD_DATABASE, Init.%s_%s)' %
1300                                                 (VariableHeadGuidIndex, VariableHeadStringIndex, Sku.VariableOffset,
1301                                                  Phase, CName, TokenSpaceGuid))
1302                    # the Pcd default value will be filled later on
1303                    VariableOffset = len(Dict['STRING_DB_VALUE'])
1304                    VariableRefTable = Dict['STRING_DB_VALUE']
1305                else:
1306                    VariableHeadValueList.append('%dU, %dU, %sU, offsetof(%s_PCD_DATABASE, Init.%s_%s_VariableDefault_%s)' %
1307                                                 (VariableHeadGuidIndex, VariableHeadStringIndex, Sku.VariableOffset,
1308                                                  Phase, CName, TokenSpaceGuid, SkuIdIndex))
1309                    # the Pcd default value was filled before
1310                    VariableOffset = len(Dict['VARDEF_DB_VALUE_' + Pcd.DatumType]) - 1
1311                    VariableRefTable = Dict['VARDEF_DB_VALUE_' + Pcd.DatumType]
1312                VariableDbValueList.append([VariableHeadGuidIndex, VariableHeadStringIndex, Sku.VariableOffset, VariableOffset, VariableRefTable, Sku.VariableAttribute])
1313
1314            elif Sku.VpdOffset != '':
1315                Pcd.TokenTypeList += ['PCD_TYPE_VPD']
1316                Pcd.InitString = 'INIT'
1317                VpdHeadOffsetList.append(str(Sku.VpdOffset) + 'U')
1318                VpdDbOffsetList.append(Sku.VpdOffset)
1319                # Also add the VOID* string of VPD PCD to SizeTable
1320                if Pcd.DatumType == 'VOID*':
1321                    NumberOfSizeItems += 1
1322                    # For VPD type of PCD, its current size is equal to its MAX size.
1323                    VoidStarTypeCurrSize = [str(Pcd.MaxDatumSize) + 'U']
1324                continue
1325
1326            if Pcd.DatumType == 'VOID*':
1327                Pcd.TokenTypeList += ['PCD_TYPE_STRING']
1328                Pcd.InitString = 'INIT'
1329                if Sku.HiiDefaultValue != '' and Sku.DefaultValue == '':
1330                    Sku.DefaultValue = Sku.HiiDefaultValue
1331                if Sku.DefaultValue != '':
1332                    NumberOfSizeItems += 1
1333                    Dict['STRING_TABLE_CNAME'].append(CName)
1334                    Dict['STRING_TABLE_GUID'].append(TokenSpaceGuid)
1335
1336                    if StringTableIndex == 0:
1337                        Dict['STRING_TABLE_INDEX'].append('')
1338                    else:
1339                        Dict['STRING_TABLE_INDEX'].append('_%d' % StringTableIndex)
1340                    if Sku.DefaultValue[0] == 'L':
1341                        DefaultValueBinStructure = StringToArray(Sku.DefaultValue)
1342                        Size = len(DefaultValueBinStructure.replace(',',' ').split())
1343                        Dict['STRING_TABLE_VALUE'].append(DefaultValueBinStructure)
1344                    elif Sku.DefaultValue[0] == '"':
1345                        DefaultValueBinStructure = StringToArray(Sku.DefaultValue)
1346                        Size = len(Sku.DefaultValue) - 2 + 1
1347                        Dict['STRING_TABLE_VALUE'].append(DefaultValueBinStructure)
1348                    elif Sku.DefaultValue[0] == '{':
1349                        DefaultValueBinStructure = StringToArray(Sku.DefaultValue)
1350                        Size = len(Sku.DefaultValue.split(","))
1351                        Dict['STRING_TABLE_VALUE'].append(DefaultValueBinStructure)
1352
1353                    StringHeadOffsetList.append(str(StringTableSize) + 'U')
1354                    StringDbOffsetList.append(StringTableSize)
1355                    if Pcd.MaxDatumSize != '':
1356                        MaxDatumSize = int(Pcd.MaxDatumSize, 0)
1357                        if MaxDatumSize < Size:
1358                            EdkLogger.error("build", AUTOGEN_ERROR,
1359                                            "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName),
1360                                            ExtraData="[%s]" % str(Platform))
1361                    else:
1362                        MaxDatumSize = Size
1363                    StringTabLen = MaxDatumSize
1364                    if StringTabLen % 2:
1365                        StringTabLen += 1
1366                    if Sku.VpdOffset == '':
1367                        VoidStarTypeCurrSize.append(str(Size) + 'U')
1368                    Dict['STRING_TABLE_LENGTH'].append(StringTabLen)
1369                    StringTableIndex += 1
1370                    StringTableSize += (StringTabLen)
1371            else:
1372                if "PCD_TYPE_HII" not in Pcd.TokenTypeList:
1373                    Pcd.TokenTypeList += ['PCD_TYPE_DATA']
1374                    if Sku.DefaultValue == 'TRUE':
1375                        Pcd.InitString = 'INIT'
1376                    else:
1377                        if int(Sku.DefaultValue, 0) != 0:
1378                            Pcd.InitString = 'INIT'
1379                #
1380                # For UNIT64 type PCD's value, ULL should be append to avoid
1381                # warning under linux building environment.
1382                #
1383                if Pcd.DatumType == "UINT64":
1384                    ValueList.append(Sku.DefaultValue + "ULL")
1385                elif Pcd.DatumType in ("UINT32", "UINT16", "UINT8"):
1386                    ValueList.append(Sku.DefaultValue + "U")
1387                elif Pcd.DatumType == "BOOLEAN":
1388                    if Sku.DefaultValue in ["1", "0"]:
1389                        ValueList.append(Sku.DefaultValue + "U")
1390                else:
1391                    ValueList.append(Sku.DefaultValue)
1392
1393                DbValueList.append(Sku.DefaultValue)
1394
1395        Pcd.TokenTypeList = list(set(Pcd.TokenTypeList))
1396        if Pcd.DatumType == 'VOID*':
1397            Dict['SIZE_TABLE_CNAME'].append(CName)
1398            Dict['SIZE_TABLE_GUID'].append(TokenSpaceGuid)
1399            Dict['SIZE_TABLE_MAXIMUM_LENGTH'].append(str(Pcd.MaxDatumSize) + 'U')
1400            Dict['SIZE_TABLE_CURRENT_LENGTH'].append(VoidStarTypeCurrSize)
1401
1402
1403        SkuIndexTableTmp[0] = len(SkuIndexTableTmp) - 1
1404        if len(Pcd.SkuInfoList) > 1:
1405            Dict['SKU_INDEX_VALUE'].append(SkuIndexTableTmp)
1406
1407        if 'PCD_TYPE_HII' in Pcd.TokenTypeList:
1408            Dict['VARIABLE_HEAD_CNAME_DECL'].append(CName)
1409            Dict['VARIABLE_HEAD_GUID_DECL'].append(TokenSpaceGuid)
1410            Dict['VARIABLE_HEAD_NUMSKUS_DECL'].append(len(Pcd.SkuInfoList))
1411            Dict['VARIABLE_HEAD_VALUE'].append('{ %s }\n' % ' },\n    { '.join(VariableHeadValueList))
1412            Dict['VARDEF_HEADER'].append('_Variable_Header')
1413            Dict['VARIABLE_DB_VALUE'].append(VariableDbValueList)
1414        else:
1415            Dict['VARDEF_HEADER'].append('')
1416        if 'PCD_TYPE_VPD' in Pcd.TokenTypeList:
1417            Dict['VPD_HEAD_CNAME_DECL'].append(CName)
1418            Dict['VPD_HEAD_GUID_DECL'].append(TokenSpaceGuid)
1419            Dict['VPD_HEAD_NUMSKUS_DECL'].append(len(Pcd.SkuInfoList))
1420            Dict['VPD_HEAD_VALUE'].append('{ %s }' % ' }, { '.join(VpdHeadOffsetList))
1421            Dict['VPD_DB_VALUE'].append(VpdDbOffsetList)
1422        if 'PCD_TYPE_STRING' in Pcd.TokenTypeList:
1423            Dict['STRING_HEAD_CNAME_DECL'].append(CName)
1424            Dict['STRING_HEAD_GUID_DECL'].append(TokenSpaceGuid)
1425            Dict['STRING_HEAD_NUMSKUS_DECL'].append(len(Pcd.SkuInfoList))
1426            Dict['STRING_HEAD_VALUE'].append(', '.join(StringHeadOffsetList))
1427            Dict['STRING_DB_VALUE'].append(StringDbOffsetList)
1428            PCD_STRING_INDEX_MAP[len(Dict['STRING_HEAD_CNAME_DECL']) -1 ] = len(Dict['STRING_DB_VALUE']) -1
1429        if 'PCD_TYPE_DATA' in Pcd.TokenTypeList:
1430            Dict[Pcd.InitString+'_CNAME_DECL_'+Pcd.DatumType].append(CName)
1431            Dict[Pcd.InitString+'_GUID_DECL_'+Pcd.DatumType].append(TokenSpaceGuid)
1432            Dict[Pcd.InitString+'_NUMSKUS_DECL_'+Pcd.DatumType].append(len(Pcd.SkuInfoList))
1433            if Pcd.InitString == 'UNINIT':
1434                Dict['PCD_DATABASE_UNINIT_EMPTY'] = ''
1435            else:
1436                Dict[Pcd.InitString+'_VALUE_'+Pcd.DatumType].append(', '.join(ValueList))
1437                Dict[Pcd.InitString+'_DB_VALUE_'+Pcd.DatumType].append(DbValueList)
1438
1439    if Phase == 'PEI':
1440        NumberOfLocalTokens = NumberOfPeiLocalTokens
1441    if Phase == 'DXE':
1442        NumberOfLocalTokens = NumberOfDxeLocalTokens
1443
1444    Dict['TOKEN_INIT']       = ['' for x in range(NumberOfLocalTokens)]
1445    Dict['TOKEN_CNAME']      = ['' for x in range(NumberOfLocalTokens)]
1446    Dict['TOKEN_GUID']       = ['' for x in range(NumberOfLocalTokens)]
1447    Dict['TOKEN_TYPE']       = ['' for x in range(NumberOfLocalTokens)]
1448    Dict['LOCAL_TOKEN_NUMBER_DB_VALUE'] = ['' for x in range(NumberOfLocalTokens)]
1449    Dict['PCD_CNAME']        = ['' for x in range(NumberOfLocalTokens)]
1450    Dict['PCD_TOKENSPACE_MAP'] = ['' for x in range(NumberOfLocalTokens)]
1451    Dict['PCD_CNAME_LENGTH'] = [0 for x in range(NumberOfLocalTokens)]
1452    SkuEnablePcdIndex = 0
1453    for Pcd in ReorderedDynPcdList:
1454        CName = Pcd.TokenCName
1455        TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName
1456        if Pcd.Phase != Phase:
1457            continue
1458
1459        TokenSpaceGuid = GuidStructureStringToGuidValueName(Pcd.TokenSpaceGuidValue) #(Platform.PackageList, TokenSpaceGuidCName))
1460        GeneratedTokenNumber = Platform.PcdTokenNumber[CName, TokenSpaceGuidCName] - 1
1461        if Phase == 'DXE':
1462            GeneratedTokenNumber -= NumberOfPeiLocalTokens
1463
1464        if len(Pcd.SkuInfoList) > 1:
1465            Dict['PCD_ORDER_TOKEN_NUMBER_MAP'][GeneratedTokenNumber] = SkuEnablePcdIndex
1466            SkuEnablePcdIndex += 1
1467        EdkLogger.debug(EdkLogger.DEBUG_1, "PCD = %s.%s" % (CName, TokenSpaceGuidCName))
1468        EdkLogger.debug(EdkLogger.DEBUG_1, "phase = %s" % Phase)
1469        EdkLogger.debug(EdkLogger.DEBUG_1, "GeneratedTokenNumber = %s" % str(GeneratedTokenNumber))
1470
1471        #
1472        # following four Dict items hold the information for LocalTokenNumberTable
1473        #
1474        Dict['TOKEN_INIT'][GeneratedTokenNumber] = 'Init'
1475        if Pcd.InitString == 'UNINIT':
1476            Dict['TOKEN_INIT'][GeneratedTokenNumber] = 'Uninit'
1477
1478        Dict['TOKEN_CNAME'][GeneratedTokenNumber] = CName
1479        Dict['TOKEN_GUID'][GeneratedTokenNumber] = TokenSpaceGuid
1480        Dict['TOKEN_TYPE'][GeneratedTokenNumber] = ' | '.join(Pcd.TokenTypeList)
1481
1482        if Platform.Platform.PcdInfoFlag:
1483            TokenSpaceGuidCNameArray = StringToArray('"' + TokenSpaceGuidCName + '"' )
1484            if TokenSpaceGuidCNameArray not in Dict['PCD_TOKENSPACE']:
1485                Dict['PCD_TOKENSPACE'].append(TokenSpaceGuidCNameArray)
1486                Dict['PCD_TOKENSPACE_LENGTH'].append( len(TokenSpaceGuidCNameArray.split(",")) )
1487            Dict['PCD_TOKENSPACE_MAP'][GeneratedTokenNumber] = Dict['PCD_TOKENSPACE'].index(TokenSpaceGuidCNameArray)
1488            CNameBinArray = StringToArray('"' + CName + '"' )
1489            Dict['PCD_CNAME'][GeneratedTokenNumber] = CNameBinArray
1490
1491            Dict['PCD_CNAME_LENGTH'][GeneratedTokenNumber] = len(CNameBinArray.split(","))
1492
1493
1494        Pcd.TokenTypeList = list(set(Pcd.TokenTypeList))
1495
1496        # search the Offset and Table, used by LocalTokenNumberTableOffset
1497        if 'PCD_TYPE_HII' in Pcd.TokenTypeList:
1498            # Find index by CName, TokenSpaceGuid
1499            Offset = GetMatchedIndex(CName, Dict['VARIABLE_HEAD_CNAME_DECL'], TokenSpaceGuid, Dict['VARIABLE_HEAD_GUID_DECL'])
1500            assert(Offset != -1)
1501            Table = Dict['VARIABLE_DB_VALUE']
1502        if 'PCD_TYPE_VPD' in Pcd.TokenTypeList:
1503            Offset = GetMatchedIndex(CName, Dict['VPD_HEAD_CNAME_DECL'], TokenSpaceGuid, Dict['VPD_HEAD_GUID_DECL'])
1504            assert(Offset != -1)
1505            Table = Dict['VPD_DB_VALUE']
1506        if 'PCD_TYPE_STRING' in Pcd.TokenTypeList and 'PCD_TYPE_HII' not in Pcd.TokenTypeList:
1507            # Find index by CName, TokenSpaceGuid
1508            Offset = GetMatchedIndex(CName, Dict['STRING_HEAD_CNAME_DECL'], TokenSpaceGuid, Dict['STRING_HEAD_GUID_DECL'])
1509            Offset = PCD_STRING_INDEX_MAP[Offset]
1510            assert(Offset != -1)
1511            Table = Dict['STRING_DB_VALUE']
1512        if 'PCD_TYPE_DATA' in Pcd.TokenTypeList:
1513            # need to store whether it is in init table or not
1514            Offset = GetMatchedIndex(CName, Dict[Pcd.InitString+'_CNAME_DECL_'+Pcd.DatumType], TokenSpaceGuid, Dict[Pcd.InitString+'_GUID_DECL_'+Pcd.DatumType])
1515            assert(Offset != -1)
1516            if Pcd.InitString == 'UNINIT':
1517                Table =  Dict[Pcd.InitString+'_GUID_DECL_'+Pcd.DatumType]
1518            else:
1519                Table = Dict[Pcd.InitString+'_DB_VALUE_'+Pcd.DatumType]
1520        Dict['LOCAL_TOKEN_NUMBER_DB_VALUE'][GeneratedTokenNumber] = (Offset, Table)
1521
1522        #
1523        # Update VARDEF_HEADER
1524        #
1525        if 'PCD_TYPE_HII' in Pcd.TokenTypeList:
1526            Dict['VARDEF_HEADER'][GeneratedTokenNumber] = '_Variable_Header'
1527        else:
1528            Dict['VARDEF_HEADER'][GeneratedTokenNumber] = ''
1529
1530
1531        if Pcd.Type in gDynamicExPcd:
1532
1533            if Phase == 'DXE':
1534                GeneratedTokenNumber += NumberOfPeiLocalTokens
1535            #
1536            # Per, PCD architecture specification, PCD Token Number is 1 based and 0 is defined as invalid token number.
1537            # For each EX type PCD, a PCD Token Number is assigned. When the
1538            # PCD Driver/PEIM map EX_GUID and EX_TOKEN_NUMBER to the PCD Token Number,
1539            # the non-EX Protocol/PPI interface can be called to get/set the value. This assumption is made by
1540            # Pcd Driver/PEIM in MdeModulePkg.
1541            # Therefore, 1 is added to GeneratedTokenNumber to generate a PCD Token Number before being inserted
1542            # to the EXMAPPING_TABLE.
1543            #
1544
1545
1546            Dict['EXMAPPING_TABLE_EXTOKEN'].append(str(Pcd.TokenValue) + 'U')
1547            Dict['EXMAPPING_TABLE_LOCAL_TOKEN'].append(str(GeneratedTokenNumber + 1) + 'U')
1548            Dict['EXMAPPING_TABLE_GUID_INDEX'].append(str(GuidList.index(TokenSpaceGuid)) + 'U')
1549
1550    if Platform.Platform.PcdInfoFlag:
1551        for index in range(len(Dict['PCD_TOKENSPACE_MAP'])):
1552            TokenSpaceIndex = StringTableSize
1553            for i in range(Dict['PCD_TOKENSPACE_MAP'][index]):
1554                TokenSpaceIndex += Dict['PCD_TOKENSPACE_LENGTH'][i]
1555            Dict['PCD_TOKENSPACE_OFFSET'].append(TokenSpaceIndex)
1556        for index in range(len(Dict['PCD_TOKENSPACE'])):
1557            StringTableSize += Dict['PCD_TOKENSPACE_LENGTH'][index]
1558            StringTableIndex += 1
1559        for index in range(len(Dict['PCD_CNAME'])):
1560            Dict['PCD_CNAME_OFFSET'].append(StringTableSize)
1561            Dict['PCD_NAME_OFFSET'].append(Dict['PCD_TOKENSPACE_OFFSET'][index])
1562            Dict['PCD_NAME_OFFSET'].append(StringTableSize)
1563            StringTableSize += Dict['PCD_CNAME_LENGTH'][index]
1564            StringTableIndex += 1
1565    if GuidList != []:
1566        Dict['GUID_TABLE_EMPTY'] = 'FALSE'
1567        Dict['GUID_TABLE_SIZE'] = str(len(GuidList)) + 'U'
1568    else:
1569        Dict['GUID_STRUCTURE'] = [GuidStringToGuidStructureString('00000000-0000-0000-0000-000000000000')]
1570
1571    if StringTableIndex == 0:
1572        Dict['STRING_TABLE_INDEX'].append('')
1573        Dict['STRING_TABLE_LENGTH'].append(1)
1574        Dict['STRING_TABLE_CNAME'].append('')
1575        Dict['STRING_TABLE_GUID'].append('')
1576        Dict['STRING_TABLE_VALUE'].append('{ 0 }')
1577    else:
1578        Dict['STRING_TABLE_EMPTY'] = 'FALSE'
1579        Dict['STRING_TABLE_SIZE'] = str(StringTableSize) + 'U'
1580
1581    if Dict['SIZE_TABLE_CNAME'] == []:
1582        Dict['SIZE_TABLE_CNAME'].append('')
1583        Dict['SIZE_TABLE_GUID'].append('')
1584        Dict['SIZE_TABLE_CURRENT_LENGTH'].append(['0U'])
1585        Dict['SIZE_TABLE_MAXIMUM_LENGTH'].append('0U')
1586
1587    if NumberOfLocalTokens != 0:
1588        Dict['DATABASE_EMPTY']                = 'FALSE'
1589        Dict['LOCAL_TOKEN_NUMBER_TABLE_SIZE'] = NumberOfLocalTokens
1590        Dict['LOCAL_TOKEN_NUMBER']            = NumberOfLocalTokens
1591
1592    if NumberOfExTokens != 0:
1593        Dict['EXMAP_TABLE_EMPTY']    = 'FALSE'
1594        Dict['EXMAPPING_TABLE_SIZE'] = str(NumberOfExTokens) + 'U'
1595        Dict['EX_TOKEN_NUMBER']      = str(NumberOfExTokens) + 'U'
1596    else:
1597        Dict['EXMAPPING_TABLE_EXTOKEN'].append('0U')
1598        Dict['EXMAPPING_TABLE_LOCAL_TOKEN'].append('0U')
1599        Dict['EXMAPPING_TABLE_GUID_INDEX'].append('0U')
1600
1601    if NumberOfSizeItems != 0:
1602        Dict['SIZE_TABLE_SIZE'] = str(NumberOfSizeItems * 2) + 'U'
1603
1604    if NumberOfSkuEnabledPcd != 0:
1605        Dict['SKU_HEAD_SIZE'] = str(NumberOfSkuEnabledPcd) + 'U'
1606
1607    for AvailableSkuNumber in SkuObj.SkuIdNumberSet:
1608        if AvailableSkuNumber not in Dict['SKUID_VALUE']:
1609            Dict['SKUID_VALUE'].append(AvailableSkuNumber)
1610    Dict['SKUID_VALUE'][0] = len(Dict['SKUID_VALUE']) - 1
1611
1612    AutoGenH.Append(gPcdDatabaseAutoGenH.Replace(Dict))
1613    if NumberOfLocalTokens == 0:
1614        AutoGenC.Append(gEmptyPcdDatabaseAutoGenC.Replace(Dict))
1615    else:
1616        #
1617        # Update Size Table to the right order, it should be same with LocalTokenNumberTable
1618        #
1619        SizeCNameTempList = []
1620        SizeGuidTempList = []
1621        SizeCurLenTempList = []
1622        SizeMaxLenTempList = []
1623        ReOrderFlag = True
1624
1625        if len(Dict['SIZE_TABLE_CNAME']) == 1:
1626            if not (Dict['SIZE_TABLE_CNAME'][0] and Dict['SIZE_TABLE_GUID'][0]):
1627                ReOrderFlag = False
1628
1629        if ReOrderFlag:
1630            for Count in range(len(Dict['TOKEN_CNAME'])):
1631                for Count1 in range(len(Dict['SIZE_TABLE_CNAME'])):
1632                    if Dict['TOKEN_CNAME'][Count] == Dict['SIZE_TABLE_CNAME'][Count1] and \
1633                        Dict['TOKEN_GUID'][Count] == Dict['SIZE_TABLE_GUID'][Count1]:
1634                        SizeCNameTempList.append(Dict['SIZE_TABLE_CNAME'][Count1])
1635                        SizeGuidTempList.append(Dict['SIZE_TABLE_GUID'][Count1])
1636                        SizeCurLenTempList.append(Dict['SIZE_TABLE_CURRENT_LENGTH'][Count1])
1637                        SizeMaxLenTempList.append(Dict['SIZE_TABLE_MAXIMUM_LENGTH'][Count1])
1638
1639            for Count in range(len(Dict['SIZE_TABLE_CNAME'])):
1640                Dict['SIZE_TABLE_CNAME'][Count] = SizeCNameTempList[Count]
1641                Dict['SIZE_TABLE_GUID'][Count] = SizeGuidTempList[Count]
1642                Dict['SIZE_TABLE_CURRENT_LENGTH'][Count] = SizeCurLenTempList[Count]
1643                Dict['SIZE_TABLE_MAXIMUM_LENGTH'][Count] = SizeMaxLenTempList[Count]
1644
1645        AutoGenC.Append(gPcdDatabaseAutoGenC.Replace(Dict))
1646
1647    if Platform.Platform.VarCheckFlag:
1648        dest = os.path.join(Platform.BuildDir, 'FV')
1649        VarCheckTab.dump(dest, Phase)
1650    Buffer = BuildExDataBase(Dict)
1651    return AutoGenH, AutoGenC, Buffer
1652
1653def GetOrderedDynamicPcdList(DynamicPcdList, PcdTokenNumberList):
1654    ReorderedDyPcdList = [None for i in range(len(DynamicPcdList))]
1655    for Pcd in DynamicPcdList:
1656        if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in PcdTokenNumberList:
1657            ReorderedDyPcdList[PcdTokenNumberList[Pcd.TokenCName, Pcd.TokenSpaceGuidCName]-1] = Pcd
1658    return ReorderedDyPcdList
1659
1660