Added doxygen comments
[people/mcb30/basetools.git] / Source / Python / Workspace / WorkspaceDatabase.py
1 ## @file\r
2 # This file is used to create a database used by build tool\r
3 #\r
4 # Copyright (c) 2008, 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 ##\r
15 # Import Modules\r
16 #\r
17 import sqlite3\r
18 import os\r
19 import os.path\r
20 \r
21 import Common.EdkLogger as EdkLogger\r
22 from CommonDataClass.DataClass import *\r
23 from CommonDataClass.ModuleClass import *\r
24 from Common.String import *\r
25 from Common.DataType import *\r
26 from Common.Misc import *\r
27 \r
28 from MetaDataTable import *\r
29 from MetaFileTable import *\r
30 from MetaFileParser import *\r
31 from BuildClassObject import *\r
32 \r
33 ## Platform build information from DSC file\r
34 #\r
35 #  This class is used to retrieve information stored in database and convert them\r
36 # into PlatformBuildClassObject form for easier use for AutoGen.\r
37 #\r
38 class DscBuildData(PlatformBuildClassObject):\r
39     # dict used to convert PCD type in database to string used by build tool\r
40     _PCD_TYPE_STRING_ = {\r
41         MODEL_PCD_FIXED_AT_BUILD        :   "FixedAtBuild",\r
42         MODEL_PCD_PATCHABLE_IN_MODULE   :   "PatchableInModule",\r
43         MODEL_PCD_FEATURE_FLAG          :   "FeatureFlag",\r
44         MODEL_PCD_DYNAMIC               :   "Dynamic",\r
45         MODEL_PCD_DYNAMIC_DEFAULT       :   "Dynamic",\r
46         MODEL_PCD_DYNAMIC_HII           :   "DynamicHii",\r
47         MODEL_PCD_DYNAMIC_VPD           :   "DynamicVpd",\r
48         MODEL_PCD_DYNAMIC_EX            :   "DynamicEx",\r
49         MODEL_PCD_DYNAMIC_EX_DEFAULT    :   "DynamicEx",\r
50         MODEL_PCD_DYNAMIC_EX_HII        :   "DynamicExHii",\r
51         MODEL_PCD_DYNAMIC_EX_VPD        :   "DynamicExVpd",\r
52     }\r
53 \r
54     # dict used to convert part of [Defines] to members of DscBuildData directly\r
55     _PROPERTY_ = {\r
56         #\r
57         # Required Fields\r
58         #\r
59         TAB_DSC_DEFINES_PLATFORM_NAME           :   "_PlatformName",\r
60         TAB_DSC_DEFINES_PLATFORM_GUID           :   "_Guid",\r
61         TAB_DSC_DEFINES_PLATFORM_VERSION        :   "_Version",\r
62         TAB_DSC_DEFINES_DSC_SPECIFICATION       :   "_DscSpecification",\r
63         #TAB_DSC_DEFINES_OUTPUT_DIRECTORY        :   "_OutputDirectory",\r
64         #TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES :   "_SupArchList",\r
65         #TAB_DSC_DEFINES_BUILD_TARGETS           :   "_BuildTargets",\r
66         #TAB_DSC_DEFINES_SKUID_IDENTIFIER        :   "_SkuName",\r
67         #TAB_DSC_DEFINES_FLASH_DEFINITION        :   "_FlashDefinition",\r
68         TAB_DSC_DEFINES_BUILD_NUMBER            :   "_BuildNumber",\r
69         TAB_DSC_DEFINES_MAKEFILE_NAME           :   "_MakefileName",\r
70         TAB_DSC_DEFINES_BS_BASE_ADDRESS         :   "_BsBaseAddress",\r
71         TAB_DSC_DEFINES_RT_BASE_ADDRESS         :   "_RtBaseAddress",\r
72     }\r
73 \r
74     # used to compose dummy library class name for those forced library instances\r
75     _NullLibraryNumber = 0\r
76 \r
77     ## Constructor of DscBuildData\r
78     #\r
79     #  Initialize object of DscBuildData\r
80     #\r
81     #   @param      FilePath        The path of platform description file\r
82     #   @param      RawData         The raw data of DSC file\r
83     #   @param      BuildDataBase   Database used to retrieve module/package information\r
84     #   @param      Arch            The target architecture\r
85     #   @param      Platform        (not used for DscBuildData)\r
86     #   @param      Macros          Macros used for replacement in DSC file\r
87     #\r
88     def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}):\r
89         self.DescFilePath = FilePath\r
90         self._RawData = RawData\r
91         self._Bdb = BuildDataBase\r
92         self._Arch = Arch\r
93         self._Macros = Macros\r
94         self._Clear()\r
95 \r
96     ## XXX[key] = value\r
97     def __setitem__(self, key, value):\r
98         self.__dict__[self._PROPERTY_[key]] = value\r
99 \r
100     ## value = XXX[key]\r
101     def __getitem__(self, key):\r
102         return self.__dict__[self._PROPERTY_[key]]\r
103 \r
104     ## "in" test support\r
105     def __contains__(self, key):\r
106         return key in self._PROPERTY_\r
107 \r
108     ## Set all internal used members of DscBuildData to None\r
109     def _Clear(self):\r
110         self._Header            = None\r
111         self._PlatformName      = None\r
112         self._Guid              = None\r
113         self._Version           = None\r
114         self._DscSpecification  = None\r
115         self._OutputDirectory   = None\r
116         self._SupArchList       = None\r
117         self._BuildTargets      = None\r
118         self._SkuName           = None\r
119         self._FlashDefinition   = None\r
120         self._BuildNumber       = None\r
121         self._MakefileName      = None\r
122         self._BsBaseAddress     = None\r
123         self._RtBaseAddress     = None\r
124         self._SkuIds            = None\r
125         self._Modules           = None\r
126         self._LibraryInstances  = None\r
127         self._LibraryClasses    = None\r
128         self._Pcds              = None\r
129         self._BuildOptions      = None\r
130 \r
131     ## Get architecture\r
132     def _GetArch(self):\r
133         return self._Arch\r
134 \r
135     ## Set architecture\r
136     #   \r
137     #   Changing the default ARCH to another may affect all other information\r
138     # because all information in a platform may be ARCH-related. That's\r
139     # why we need to clear all internal used members, in order to cause all \r
140     # information to be re-retrieved.\r
141     # \r
142     #   @param  Value   The value of ARCH\r
143     # \r
144     def _SetArch(self, Value):\r
145         if self._Arch == Value:\r
146             return\r
147         self._Arch = Value\r
148         self._Clear()\r
149 \r
150     ## Retrieve all information in [Defines] section\r
151     #\r
152     #   (Retriving all [Defines] information in one-shot is just to save time.)\r
153     # \r
154     def _GetHeaderInfo(self):\r
155         RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]\r
156         for Record in RecordList:\r
157             Name = Record[0]\r
158             # items defined _PROPERTY_ don't need additional processing\r
159             if Name in self:\r
160                 self[Name] = Record[1]\r
161             # some special items in [Defines] section need special treatment\r
162             elif Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:\r
163                 self._OutputDirectory = NormPath(Record[1], self._Macros)\r
164             elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:\r
165                 self._FlashDefinition = NormPath(Record[1], self._Macros)\r
166             elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:\r
167                 self._SupArchList = GetSplitValueList(Record[1], TAB_VALUE_SPLIT)\r
168             elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:\r
169                 self._BuildTargets = GetSplitValueList(Record[1])\r
170             elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:\r
171                 if self._SkuName == None:\r
172                     self._SkuName = Record[1]\r
173         # set _Header to non-None in order to avoid database re-querying\r
174         self._Header = 'DUMMY'\r
175 \r
176     ## Retrieve platform name\r
177     def _GetPlatformName(self):\r
178         if self._PlatformName == None:\r
179             if self._Header == None:\r
180                 self._GetHeaderInfo()\r
181             if self._PlatformName == None:\r
182                 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.DescFilePath)\r
183         return self._PlatformName\r
184 \r
185     ## Retrieve file guid\r
186     def _GetFileGuid(self):\r
187         if self._Guid == None:\r
188             if self._Header == None:\r
189                 self._GetHeaderInfo()\r
190             if self._Guid == None:\r
191                 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No FILE_GUID", File=self.DescFilePath)\r
192         return self._Guid\r
193 \r
194     ## Retrieve platform version\r
195     def _GetVersion(self):\r
196         if self._Version == None:\r
197             if self._Header == None:\r
198                 self._GetHeaderInfo()\r
199             if self._Version == None:\r
200                 self._Version = ''\r
201         return self._Version\r
202 \r
203     ## Retrieve platform description file version\r
204     def _GetDscSpec(self):\r
205         if self._DscSpecification == None:\r
206             if self._Header == None:\r
207                 self._GetHeaderInfo()\r
208             if self._DscSpecification == None:\r
209                 self._DscSpecification = ''\r
210         return self._DscSpecification\r
211 \r
212     ## Retrieve OUTPUT_DIRECTORY\r
213     def _GetOutpuDir(self):\r
214         if self._OutputDirectory == None:\r
215             if self._Header == None:\r
216                 self._GetHeaderInfo()\r
217             if self._OutputDirectory == None:\r
218                 self._OutputDirectory = os.path.join("Build", self._PlatformName)\r
219         return self._OutputDirectory\r
220 \r
221     ## Retrieve SUPPORTED_ARCHITECTURES\r
222     def _GetSupArch(self):\r
223         if self._SupArchList == None:\r
224             if self._Header == None:\r
225                 self._GetHeaderInfo()\r
226             if self._SupArchList == None:\r
227                 self._SupArchList = ARCH_LIST\r
228         return self._SupArchList\r
229 \r
230     ## Retrieve BUILD_TARGETS\r
231     def _GetBuildTarget(self):\r
232         if self._BuildTargets == None:\r
233             if self._Header == None:\r
234                 self._GetHeaderInfo()\r
235             if self._BuildTargets == None:\r
236                 self._BuildTargets = ['DEBUG', 'RELEASE']\r
237         return self._BuildTargets\r
238 \r
239     ## Retrieve SKUID_IDENTIFIER\r
240     def _GetSkuName(self):\r
241         if self._SkuName == None:\r
242             if self._Header == None:\r
243                 self._GetHeaderInfo()\r
244             if self._SkuName == None or self._SkuName not in self.SkuIds:\r
245                 self._SkuName = 'DEFAULT'\r
246         return self._SkuName\r
247 \r
248     ## Override SKUID_IDENTIFIER\r
249     def _SetSkuName(self, Value):\r
250         if Value in self.SkuIds:\r
251             self._SkuName = Value\r
252 \r
253     def _GetFdfFile(self):\r
254         if self._FlashDefinition == None:\r
255             if self._Header == None:\r
256                 self._GetHeaderInfo()\r
257             if self._FlashDefinition == None:\r
258                 self._FlashDefinition = ''\r
259         return self._FlashDefinition\r
260 \r
261     ## Retrieve FLASH_DEFINITION\r
262     def _GetBuildNumber(self):\r
263         if self._BuildNumber == None:\r
264             if self._Header == None:\r
265                 self._GetHeaderInfo()\r
266             if self._BuildNumber == None:\r
267                 self._BuildNumber = ''\r
268         return self._BuildNumber\r
269 \r
270     ## Retrieve MAKEFILE_NAME\r
271     def _GetMakefileName(self):\r
272         if self._MakefileName == None:\r
273             if self._Header == None:\r
274                 self._GetHeaderInfo()\r
275             if self._MakefileName == None:\r
276                 self._MakefileName = ''\r
277         return self._MakefileName\r
278 \r
279     ## Retrieve BsBaseAddress\r
280     def _GetBsBaseAddress(self):\r
281         if self._BsBaseAddress == None:\r
282             if self._Header == None:\r
283                 self._GetHeaderInfo()\r
284             if self._BsBaseAddress == None:\r
285                 self._BsBaseAddress = ''\r
286         return self._BsBaseAddress\r
287 \r
288     ## Retrieve RtBaseAddress\r
289     def _GetRtBaseAddress(self):\r
290         if self._RtBaseAddress == None:\r
291             if self._Header == None:\r
292                 self._GetHeaderInfo()\r
293             if self._RtBaseAddress == None:\r
294                 self._RtBaseAddress = ''\r
295         return self._RtBaseAddress\r
296 \r
297     ## Retrieve [SkuIds] section information\r
298     def _GetSkuIds(self):\r
299         if self._SkuIds == None:\r
300             self._SkuIds = {}\r
301             RecordList = self._RawData[MODEL_EFI_SKU_ID]\r
302             for Record in RecordList:\r
303                 if Record[0] in [None, '']:\r
304                     EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',\r
305                                     File=self.DescFilePath, Line=Record[-1])\r
306                 if Record[1] in [None, '']:\r
307                     EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',\r
308                                     File=self.DescFilePath, Line=Record[-1])\r
309                 self._SkuIds[Record[1]] = Record[0]\r
310             if 'DEFAULT' not in self._SkuIds:\r
311                 self._SkuIds['DEFAULT'] = 0\r
312         return self._SkuIds\r
313 \r
314     ## Retrieve [Components] section information\r
315     def _GetModules(self):\r
316         if self._Modules != None:\r
317             return self._Modules\r
318 \r
319         self._Modules = sdict()\r
320         RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]\r
321         for Record in RecordList:\r
322             ModuleFile = NormPath(Record[0], self._Macros)\r
323             ModuleId = Record[5]\r
324             LineNo = Record[6]\r
325             # check the file existence\r
326             if not ValidFile(ModuleFile):\r
327                 EdkLogger.error('build', FILE_NOT_FOUND, File=self.DescFilePath, \r
328                                 ExtraData=ModuleFile, Line=LineNo)\r
329             if ModuleFile in self._Modules:\r
330                 continue\r
331             Module = ModuleBuildClassObject()\r
332             Module.DescFilePath = ModuleFile\r
333 \r
334             # get module private library instance\r
335             RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]\r
336             for Record in RecordList:\r
337                 LibraryClass = Record[0]\r
338                 LibraryPath = NormPath(Record[1], self._Macros)\r
339                 LineNo = Record[-1]\r
340                 if not ValidFile(LibraryPath):\r
341                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=LibraryPath,\r
342                                     File=self.DescFilePath, Line=LineNo)\r
343                 if LibraryClass == '' or LibraryClass == 'NULL':\r
344                     self._NullLibraryNumber += 1\r
345                     LibraryClass = 'NULL%d' % self._NullLibraryNumber\r
346                     EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))\r
347                 Module.LibraryClasses[LibraryClass] = LibraryPath\r
348                 if LibraryPath not in self.LibraryInstances:\r
349                     self.LibraryInstances.append(LibraryPath)\r
350 \r
351             # get module private PCD setting\r
352             for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \\r
353                          MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:\r
354                 RecordList = self._RawData[Type, self._Arch, None, ModuleId]\r
355                 for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:\r
356                     TokenList = GetSplitValueList(Setting)\r
357                     DefaultValue = TokenList[0]\r
358                     if len(TokenList) > 1:\r
359                         MaxDatumSize = TokenList[1]\r
360                     else:\r
361                         MaxDatumSize = ''\r
362                     Type = self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD]\r
363                     Pcd = PcdClassObject(\r
364                             PcdCName,\r
365                             TokenSpaceGuid,\r
366                             Type,\r
367                             '',\r
368                             DefaultValue,\r
369                             '',\r
370                             MaxDatumSize,\r
371                             {},\r
372                             None\r
373                             )\r
374                     Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd\r
375 \r
376             # get module private build options\r
377             RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]\r
378             for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:\r
379                 if (ToolChainFamily, ToolChain) not in Module.BuildOptions:\r
380                     Module.BuildOptions[ToolChainFamily, ToolChain] = Option\r
381                 else:\r
382                     OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]\r
383                     Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option\r
384 \r
385             self._Modules[ModuleFile] = Module\r
386         return self._Modules\r
387 \r
388     ## Retrieve all possible library instances used in this platform\r
389     def _GetLibraryInstances(self):\r
390         if self._LibraryInstances == None:\r
391             self._GetLibraryClasses()\r
392         return self._LibraryInstances\r
393 \r
394     ## Retrieve [LibraryClasses] information\r
395     def _GetLibraryClasses(self):\r
396         if self._LibraryClasses == None:\r
397             self._LibraryInstances = []\r
398             # \r
399             # tdict is a special dict kind of type, used for selecting correct \r
400             # library instance for given library class and module type\r
401             # \r
402             LibraryClassDict = tdict(True, 3)\r
403             # track all library class names\r
404             LibraryClassSet = set()\r
405             RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]\r
406             for LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, LineNo in RecordList:\r
407                 LibraryClassSet.add(LibraryClass)\r
408                 LibraryInstance = NormPath(LibraryInstance, self._Macros)\r
409                 if not ValidFile(LibraryInstance):\r
410                     EdkLogger.error('build', FILE_NOT_FOUND, File=self.DescFilePath, \r
411                                     ExtraData=LibraryInstance, Line=LineNo)\r
412                 LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance\r
413                 if LibraryInstance not in self._LibraryInstances:\r
414                     self._LibraryInstances.append(LibraryInstance)\r
415 \r
416             # resolve the specific library instance for each class and each module type \r
417             self._LibraryClasses = tdict(True)\r
418             for LibraryClass in LibraryClassSet:\r
419                 # try all possible module types\r
420                 for ModuleType in SUP_MODULE_LIST:\r
421                     LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]\r
422                     if LibraryInstance == None:\r
423                         continue\r
424                     self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance\r
425 \r
426             # for R8 style library instances, which are listed in different section\r
427             RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]\r
428             for Record in RecordList:\r
429                 File = NormPath(Record[0], self._Macros)\r
430                 LineNo = Record[-1]\r
431                 if not ValidFile(File):\r
432                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
433                                     File=self.DescFilePath, Line=LineNo)\r
434                 if File not in self._LibraryInstances:\r
435                     self._LibraryInstances.append(File)\r
436                 # \r
437                 # we need the module name as the library class name, so we have\r
438                 # to parse it here. (self._Bdb[] will trigger a file parse if it\r
439                 # hasn't been parsed)\r
440                 # \r
441                 Library = self._Bdb[File, self._Arch]\r
442                 self._LibraryClasses[Library.BaseName, ':dummy:'] = Library\r
443         return self._LibraryClasses\r
444 \r
445     ## Retrieve all PCD settings in platform\r
446     def _GetPcds(self):\r
447         if self._Pcds == None:\r
448             self._Pcds = {}\r
449             self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))\r
450             self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))\r
451             self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))\r
452             self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))\r
453             self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))\r
454             self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))\r
455             self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))\r
456             self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))\r
457             self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))\r
458         return self._Pcds\r
459 \r
460     ## Retrieve [BuildOptions]\r
461     def _GetBuildOptions(self):\r
462         if self._BuildOptions == None:\r
463             self._BuildOptions = {}\r
464             RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION]\r
465             for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:\r
466                 self._BuildOptions[ToolChainFamily, ToolChain] = Option\r
467         return self._BuildOptions\r
468 \r
469     ## Retrieve non-dynamic PCD settings\r
470     #\r
471     #   @param  Type    PCD type\r
472     # \r
473     #   @retval a dict object contains settings of given PCD type\r
474     # \r
475     def _GetPcd(self, Type):\r
476         Pcds = {}\r
477         # \r
478         # tdict is a special dict kind of type, used for selecting correct \r
479         # PCD settings for certain ARCH\r
480         # \r
481         PcdDict = tdict(True, 3)\r
482         PcdSet = set()\r
483         # Find out all possible PCD candidates for self._Arch\r
484         RecordList = self._RawData[Type, self._Arch]\r
485         for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
486             PcdSet.add((PcdCName, TokenSpaceGuid))\r
487             PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting\r
488         # Remove redundant PCD candidates\r
489         for PcdCName, TokenSpaceGuid in PcdSet:\r
490             ValueList = ['', '', '']\r
491             Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]\r
492             if Setting == None:\r
493                 continue\r
494             TokenList = Setting.split(TAB_VALUE_SPLIT)\r
495             ValueList[0:len(TokenList)] = TokenList\r
496             PcdValue, DatumType, MaxDatumSize = ValueList\r
497             Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
498                                                 PcdCName,\r
499                                                 TokenSpaceGuid,\r
500                                                 self._PCD_TYPE_STRING_[Type],\r
501                                                 DatumType,\r
502                                                 PcdValue,\r
503                                                 '',\r
504                                                 MaxDatumSize,\r
505                                                 {},\r
506                                                 None\r
507                                                 )\r
508         return Pcds\r
509 \r
510     ## Retrieve dynamic PCD settings\r
511     #\r
512     #   @param  Type    PCD type\r
513     # \r
514     #   @retval a dict object contains settings of given PCD type\r
515     # \r
516     def _GetDynamicPcd(self, Type):\r
517         Pcds = {}\r
518         # \r
519         # tdict is a special dict kind of type, used for selecting correct \r
520         # PCD settings for certain ARCH and SKU\r
521         # \r
522         PcdDict = tdict(True, 4)\r
523         PcdSet = set()\r
524         # Find out all possible PCD candidates for self._Arch\r
525         RecordList = self._RawData[Type, self._Arch]\r
526         for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
527             PcdSet.add((PcdCName, TokenSpaceGuid))\r
528             PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting\r
529         # Remove redundant PCD candidates, per the ARCH and SKU\r
530         for PcdCName, TokenSpaceGuid in PcdSet:\r
531             ValueList = ['', '', '']\r
532             Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]\r
533             if Setting == None:\r
534                 continue\r
535             TokenList = Setting.split(TAB_VALUE_SPLIT)\r
536             ValueList[0:len(TokenList)] = TokenList\r
537             PcdValue, DatumType, MaxDatumSize = ValueList\r
538 \r
539             SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', '', PcdValue)\r
540             Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
541                                                 PcdCName,\r
542                                                 TokenSpaceGuid,\r
543                                                 self._PCD_TYPE_STRING_[Type],\r
544                                                 DatumType,\r
545                                                 PcdValue,\r
546                                                 '',\r
547                                                 MaxDatumSize,\r
548                                                 {self.SkuName : SkuInfo},\r
549                                                 None\r
550                                                 )\r
551         return Pcds\r
552 \r
553     ## Retrieve dynamic HII PCD settings\r
554     #\r
555     #   @param  Type    PCD type\r
556     # \r
557     #   @retval a dict object contains settings of given PCD type\r
558     # \r
559     def _GetDynamicHiiPcd(self, Type):\r
560         Pcds = {}\r
561         # \r
562         # tdict is a special dict kind of type, used for selecting correct \r
563         # PCD settings for certain ARCH and SKU\r
564         # \r
565         PcdDict = tdict(True, 4)\r
566         PcdSet = set()\r
567         RecordList = self._RawData[Type, self._Arch]\r
568         # Find out all possible PCD candidates for self._Arch\r
569         for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
570             PcdSet.add((PcdCName, TokenSpaceGuid))\r
571             PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting\r
572         # Remove redundant PCD candidates, per the ARCH and SKU\r
573         for PcdCName, TokenSpaceGuid in PcdSet:\r
574             ValueList = ['', '', '', '']\r
575             Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]\r
576             if Setting == None:\r
577                 continue\r
578             TokenList = Setting.split(TAB_VALUE_SPLIT)\r
579             ValueList[0:len(TokenList)] = TokenList\r
580             VariableName, VariableGuid, VariableOffset, DefaultValue = ValueList\r
581             SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue)\r
582             Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
583                                                 PcdCName,\r
584                                                 TokenSpaceGuid,\r
585                                                 self._PCD_TYPE_STRING_[Type],\r
586                                                 '',\r
587                                                 DefaultValue,\r
588                                                 '',\r
589                                                 '',\r
590                                                 {self.SkuName : SkuInfo},\r
591                                                 None\r
592                                                 )\r
593         return Pcds\r
594 \r
595     ## Retrieve dynamic VPD PCD settings\r
596     #\r
597     #   @param  Type    PCD type\r
598     # \r
599     #   @retval a dict object contains settings of given PCD type\r
600     # \r
601     def _GetDynamicVpdPcd(self, Type):\r
602         Pcds = {}\r
603         # \r
604         # tdict is a special dict kind of type, used for selecting correct \r
605         # PCD settings for certain ARCH and SKU\r
606         # \r
607         PcdDict = tdict(True, 4)\r
608         PcdSet = set()\r
609         # Find out all possible PCD candidates for self._Arch\r
610         RecordList = self._RawData[Type, self._Arch]\r
611         for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
612             PcdSet.add((PcdCName, TokenSpaceGuid))\r
613             PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting\r
614         # Remove redundant PCD candidates, per the ARCH and SKU\r
615         for PcdCName, TokenSpaceGuid in PcdSet:\r
616             ValueList = ['', '']\r
617             Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]\r
618             if Setting == None:\r
619                 continue\r
620             TokenList = Setting.split(TAB_VALUE_SPLIT)\r
621             ValueList[0:len(TokenList)] = TokenList\r
622             VpdOffset, MaxDatumSize = ValueList\r
623 \r
624             SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', VpdOffset)\r
625             Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
626                                                 PcdCName,\r
627                                                 TokenSpaceGuid,\r
628                                                 self._PCD_TYPE_STRING_[Type],\r
629                                                 '',\r
630                                                 '',\r
631                                                 '',\r
632                                                 MaxDatumSize,\r
633                                                 {self.SkuName : SkuInfo},\r
634                                                 None\r
635                                                 )\r
636         return Pcds\r
637 \r
638     ## Add external modules\r
639     #\r
640     #   The external modules are mostly those listed in FDF file, which don't \r
641     # need "build".\r
642     # \r
643     #   @param  FilePath    The path of module description file\r
644     # \r
645     def AddModule(self, FilePath):\r
646         FilePath = NormPath(FilePath)\r
647         if FilePath not in self.Modules:\r
648             Module = ModuleBuildClassObject()\r
649             Module.DescFilePath = FilePath\r
650             self.Modules.append(Module)\r
651 \r
652     ## Add external PCDs\r
653     #\r
654     #   The external PCDs are mostly those listed in FDF file to specify address\r
655     # or offset information.\r
656     # \r
657     #   @param  Name    Name of the PCD\r
658     #   @param  Guid    Token space guid of the PCD\r
659     #   @param  Value   Value of the PCD\r
660     # \r
661     def AddPcd(self, Name, Guid, Value):\r
662         if (Name, Guid) not in self.Pcds:\r
663             self.Pcds[Name, Guid] = PcdClassObject(\r
664                                         Name,\r
665                                         Guid,\r
666                                         '',\r
667                                         '',\r
668                                         '',\r
669                                         '',\r
670                                         '',\r
671                                         {},\r
672                                         None\r
673                                         )\r
674         self.Pcds[Name, Guid].DefaultValue = Value\r
675 \r
676     Arch                = property(_GetArch, _SetArch)\r
677     Platform            = property(_GetPlatformName)\r
678     PlatformName        = property(_GetPlatformName)\r
679     Guid                = property(_GetFileGuid)\r
680     Version             = property(_GetVersion)\r
681     DscSpecification    = property(_GetDscSpec)\r
682     OutputDirectory     = property(_GetOutpuDir)\r
683     SupArchList         = property(_GetSupArch)\r
684     BuildTargets        = property(_GetBuildTarget)\r
685     SkuName             = property(_GetSkuName, _SetSkuName)\r
686     FlashDefinition     = property(_GetFdfFile)\r
687     BuildNumber         = property(_GetBuildNumber)\r
688     MakefileName        = property(_GetMakefileName)\r
689     BsBaseAddress       = property(_GetBsBaseAddress)\r
690     RtBaseAddress       = property(_GetRtBaseAddress)\r
691 \r
692     SkuIds              = property(_GetSkuIds)\r
693     Modules             = property(_GetModules)\r
694     LibraryInstances    = property(_GetLibraryInstances)\r
695     LibraryClasses      = property(_GetLibraryClasses)\r
696     Pcds                = property(_GetPcds)\r
697     BuildOptions        = property(_GetBuildOptions)\r
698 \r
699 ## Platform build information from DSC file\r
700 #\r
701 #  This class is used to retrieve information stored in database and convert them\r
702 # into PackageBuildClassObject form for easier use for AutoGen.\r
703 #\r
704 class DecBuildData(PackageBuildClassObject):\r
705     # dict used to convert PCD type in database to string used by build tool\r
706     _PCD_TYPE_STRING_ = {\r
707         MODEL_PCD_FIXED_AT_BUILD        :   "FixedAtBuild",\r
708         MODEL_PCD_PATCHABLE_IN_MODULE   :   "PatchableInModule",\r
709         MODEL_PCD_FEATURE_FLAG          :   "FeatureFlag",\r
710         MODEL_PCD_DYNAMIC               :   "Dynamic",\r
711         MODEL_PCD_DYNAMIC_DEFAULT       :   "Dynamic",\r
712         MODEL_PCD_DYNAMIC_HII           :   "DynamicHii",\r
713         MODEL_PCD_DYNAMIC_VPD           :   "DynamicVpd",\r
714         MODEL_PCD_DYNAMIC_EX            :   "DynamicEx",\r
715         MODEL_PCD_DYNAMIC_EX_DEFAULT    :   "DynamicEx",\r
716         MODEL_PCD_DYNAMIC_EX_HII        :   "DynamicExHii",\r
717         MODEL_PCD_DYNAMIC_EX_VPD        :   "DynamicExVpd",\r
718     }\r
719 \r
720     # dict used to convert part of [Defines] to members of DecBuildData directly\r
721     _PROPERTY_ = {\r
722         #\r
723         # Required Fields\r
724         #\r
725         TAB_DEC_DEFINES_PACKAGE_NAME                : "_PackageName",\r
726         TAB_DEC_DEFINES_PACKAGE_GUID                : "_Guid",\r
727         TAB_DEC_DEFINES_PACKAGE_VERSION             : "_Version",\r
728     }\r
729 \r
730 \r
731     ## Constructor of DecBuildData\r
732     #\r
733     #  Initialize object of DecBuildData\r
734     #\r
735     #   @param      FilePath        The path of package description file\r
736     #   @param      RawData         The raw data of DEC file\r
737     #   @param      BuildDataBase   Database used to retrieve module information\r
738     #   @param      Arch            The target architecture\r
739     #   @param      Platform        (not used for DecBuildData)\r
740     #   @param      Macros          Macros used for replacement in DSC file\r
741     #\r
742     def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}):\r
743         self.DescFilePath = FilePath\r
744         self._PackageDir = os.path.dirname(FilePath)\r
745         self._RawData = RawData\r
746         self._Bdb = BuildDataBase\r
747         self._Arch = Arch\r
748         self._Macros = Macros\r
749         self._Clear()\r
750 \r
751     ## XXX[key] = value\r
752     def __setitem__(self, key, value):\r
753         self.__dict__[self._PROPERTY_[key]] = value\r
754 \r
755     ## value = XXX[key]\r
756     def __getitem__(self, key):\r
757         return self.__dict__[self._PROPERTY_[key]]\r
758 \r
759     ## "in" test support\r
760     def __contains__(self, key):\r
761         return key in self._PROPERTY_\r
762 \r
763     ## Set all internal used members of DecBuildData to None\r
764     def _Clear(self):\r
765         self._Header            = None\r
766         self._PackageName       = None\r
767         self._Guid              = None\r
768         self._Version           = None\r
769         self._Protocols         = None\r
770         self._Ppis              = None\r
771         self._Guids             = None\r
772         self._Includes          = None\r
773         self._LibraryClasses    = None\r
774         self._Pcds              = None\r
775 \r
776     ## Get architecture\r
777     def _GetArch(self):\r
778         return self._Arch\r
779 \r
780     ## Set architecture\r
781     #   \r
782     #   Changing the default ARCH to another may affect all other information\r
783     # because all information in a platform may be ARCH-related. That's\r
784     # why we need to clear all internal used members, in order to cause all \r
785     # information to be re-retrieved.\r
786     # \r
787     #   @param  Value   The value of ARCH\r
788     # \r
789     def _SetArch(self, Value):\r
790         if self._Arch == Value:\r
791             return\r
792         self._Arch = Value\r
793         self._Clear()\r
794 \r
795     ## Retrieve all information in [Defines] section\r
796     #\r
797     #   (Retriving all [Defines] information in one-shot is just to save time.)\r
798     # \r
799     def _GetHeaderInfo(self):\r
800         RecordList = self._RawData[MODEL_META_DATA_HEADER]\r
801         for Record in RecordList:\r
802             Name = Record[0]\r
803             if Name in self:\r
804                 self[Name] = Record[1]\r
805         self._Header = 'DUMMY'\r
806 \r
807     ## Retrieve package name\r
808     def _GetPackageName(self):\r
809         if self._PackageName == None:\r
810             if self._Header == None:\r
811                 self._GetHeaderInfo()\r
812             if self._PackageName == None:\r
813                 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.DescFilePath)\r
814         return self._PackageName\r
815 \r
816     ## Retrieve file guid\r
817     def _GetFileGuid(self):\r
818         if self._Guid == None:\r
819             if self._Header == None:\r
820                 self._GetHeaderInfo()\r
821             if self._Guid == None:\r
822                 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.DescFilePath)\r
823         return self._Guid\r
824 \r
825     ## Retrieve package version\r
826     def _GetVersion(self):\r
827         if self._Version == None:\r
828             if self._Header == None:\r
829                 self._GetHeaderInfo()\r
830             if self._Version == None:\r
831                 self._Version = ''\r
832         return self._Version\r
833 \r
834     ## Retrieve protocol definitions (name/value pairs)\r
835     def _GetProtocol(self):\r
836         if self._Protocols == None:\r
837             # \r
838             # tdict is a special kind of dict, used for selecting correct \r
839             # protocol defition for given ARCH\r
840             # \r
841             ProtocolDict = tdict(True)\r
842             NameList = []\r
843             # find out all protocol definitions for specific and 'common' arch\r
844             RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]\r
845             for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:\r
846                 if Name not in NameList:\r
847                     NameList.append(Name)\r
848                 ProtocolDict[Arch, Name] = Guid\r
849             # use sdict to keep the order\r
850             self._Protocols = sdict()\r
851             for Name in NameList:\r
852                 # \r
853                 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
854                 # will automatically turn to 'common' ARCH for trying\r
855                 # \r
856                 self._Protocols[Name] = ProtocolDict[self._Arch, Name]\r
857         return self._Protocols\r
858 \r
859     ## Retrieve PPI definitions (name/value pairs)\r
860     def _GetPpi(self):\r
861         if self._Ppis == None:\r
862             # \r
863             # tdict is a special kind of dict, used for selecting correct \r
864             # PPI defition for given ARCH\r
865             # \r
866             PpiDict = tdict(True)\r
867             NameList = []\r
868             # find out all PPI definitions for specific arch and 'common' arch\r
869             RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]\r
870             for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:\r
871                 if Name not in NameList:\r
872                     NameList.append(Name)\r
873                 PpiDict[Arch, Name] = Guid\r
874             # use sdict to keep the order\r
875             self._Ppis = sdict()\r
876             for Name in NameList:\r
877                 # \r
878                 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
879                 # will automatically turn to 'common' ARCH for trying\r
880                 # \r
881                 self._Ppis[Name] = PpiDict[self._Arch, Name]\r
882         return self._Ppis\r
883 \r
884     ## Retrieve GUID definitions (name/value pairs)\r
885     def _GetGuid(self):\r
886         if self._Guids == None:\r
887             # \r
888             # tdict is a special kind of dict, used for selecting correct \r
889             # GUID defition for given ARCH\r
890             # \r
891             GuidDict = tdict(True)\r
892             NameList = []\r
893             # find out all protocol definitions for specific and 'common' arch\r
894             RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]\r
895             for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:\r
896                 if Name not in NameList:\r
897                     NameList.append(Name)\r
898                 GuidDict[Arch, Name] = Guid\r
899             # use sdict to keep the order\r
900             self._Guids = sdict()\r
901             for Name in NameList:\r
902                 # \r
903                 # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
904                 # will automatically turn to 'common' ARCH for trying\r
905                 # \r
906                 self._Guids[Name] = GuidDict[self._Arch, Name]\r
907         return self._Guids\r
908 \r
909     ## Retrieve public include paths declared in this package\r
910     def _GetInclude(self):\r
911         if self._Includes == None:\r
912             self._Includes = []\r
913             RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]\r
914             for Record in RecordList:\r
915                 File = NormPath(Record[0], self._Macros)\r
916                 LineNo = Record[-1]\r
917                 # validate the path\r
918                 if not ValidFile(File, self._PackageDir):\r
919                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
920                                     File=self.DescFilePath, Line=LineNo)\r
921                 # avoid duplicate include path\r
922                 if File not in self._Includes:\r
923                     self._Includes.append(File)\r
924         return self._Includes\r
925 \r
926     ## Retrieve library class declarations (not used in build at present)\r
927     def _GetLibraryClass(self):\r
928         if self._LibraryClasses == None:\r
929             # \r
930             # tdict is a special kind of dict, used for selecting correct \r
931             # library class declaration for given ARCH\r
932             # \r
933             LibraryClassDict = tdict(True)\r
934             LibraryClassSet = set()\r
935             RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]\r
936             for LibraryClass, File, Dummy, Arch, ID, LineNo in RecordList:\r
937                 File = NormPath(File, self._Macros)\r
938                 if not ValidFile(File, self._PackageDir):\r
939                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
940                                     File=self.DescFilePath, Line=LineNo)\r
941                 LibraryClassSet.add(LibraryClass)\r
942                 LibraryClassDict[Arch, LibraryClass] = File\r
943             self._LibraryClasses = sdict()\r
944             for LibraryClass in LibraryClassSet:\r
945                 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]\r
946         return self._LibraryClasses\r
947 \r
948     ## Retrieve PCD declarations\r
949     def _GetPcds(self):\r
950         if self._Pcds == None:\r
951             self._Pcds = {}\r
952             self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))\r
953             self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))\r
954             self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))\r
955             self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))\r
956             self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))\r
957         return self._Pcds\r
958 \r
959     ## Retrieve PCD declarations for given type\r
960     def _GetPcd(self, Type):\r
961         Pcds = {}\r
962         # \r
963         # tdict is a special kind of dict, used for selecting correct \r
964         # PCD declaration for given ARCH\r
965         # \r
966         PcdDict = tdict(True, 3)\r
967         # for summarizing PCD\r
968         PcdSet = set()\r
969         # find out all PCDs of the 'type'\r
970         RecordList = self._RawData[Type, self._Arch]\r
971         for TokenSpaceGuid, PcdCName, Setting, Arch, Dummy1, Dummy2 in RecordList:\r
972             PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting\r
973             PcdSet.add((PcdCName, TokenSpaceGuid))\r
974 \r
975         for PcdCName, TokenSpaceGuid in PcdSet:\r
976             ValueList = ['', '', '']\r
977             # \r
978             # limit the ARCH to self._Arch, if no self._Arch found, tdict\r
979             # will automatically turn to 'common' ARCH and try again\r
980             # \r
981             Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]\r
982             if Setting == None:\r
983                 continue\r
984             TokenList = Setting.split(TAB_VALUE_SPLIT)\r
985             ValueList[0:len(TokenList)] = TokenList\r
986             DefaultValue, DatumType, TokenNumber = ValueList\r
987             Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject(\r
988                                                                             PcdCName,\r
989                                                                             TokenSpaceGuid,\r
990                                                                             self._PCD_TYPE_STRING_[Type],\r
991                                                                             DatumType,\r
992                                                                             DefaultValue,\r
993                                                                             TokenNumber,\r
994                                                                             '',\r
995                                                                             {},\r
996                                                                             None\r
997                                                                             )\r
998         return Pcds\r
999 \r
1000 \r
1001     Arch            = property(_GetArch, _SetArch)\r
1002     PackageName     = property(_GetPackageName)\r
1003     Guid            = property(_GetFileGuid)\r
1004     Version         = property(_GetVersion)\r
1005 \r
1006     Protocols       = property(_GetProtocol)\r
1007     Ppis            = property(_GetPpi)\r
1008     Guids           = property(_GetGuid)\r
1009     Includes        = property(_GetInclude)\r
1010     LibraryClasses  = property(_GetLibraryClass)\r
1011     Pcds            = property(_GetPcds)\r
1012 \r
1013 ## Module build information from INF file\r
1014 #\r
1015 #  This class is used to retrieve information stored in database and convert them\r
1016 # into ModuleBuildClassObject form for easier use for AutoGen.\r
1017 #\r
1018 class InfBuildData(ModuleBuildClassObject):\r
1019     # dict used to convert PCD type in database to string used by build tool\r
1020     _PCD_TYPE_STRING_ = {\r
1021         MODEL_PCD_FIXED_AT_BUILD        :   "FixedAtBuild",\r
1022         MODEL_PCD_PATCHABLE_IN_MODULE   :   "PatchableInModule",\r
1023         MODEL_PCD_FEATURE_FLAG          :   "FeatureFlag",\r
1024         MODEL_PCD_DYNAMIC               :   "Dynamic",\r
1025         MODEL_PCD_DYNAMIC_DEFAULT       :   "Dynamic",\r
1026         MODEL_PCD_DYNAMIC_HII           :   "DynamicHii",\r
1027         MODEL_PCD_DYNAMIC_VPD           :   "DynamicVpd",\r
1028         MODEL_PCD_DYNAMIC_EX            :   "DynamicEx",\r
1029         MODEL_PCD_DYNAMIC_EX_DEFAULT    :   "DynamicEx",\r
1030         MODEL_PCD_DYNAMIC_EX_HII        :   "DynamicExHii",\r
1031         MODEL_PCD_DYNAMIC_EX_VPD        :   "DynamicExVpd",\r
1032     }\r
1033 \r
1034     # dict used to convert part of [Defines] to members of InfBuildData directly\r
1035     _PROPERTY_ = {\r
1036         #\r
1037         # Required Fields\r
1038         #\r
1039         TAB_INF_DEFINES_BASE_NAME                   : "_BaseName",\r
1040         TAB_INF_DEFINES_FILE_GUID                   : "_Guid",\r
1041         TAB_INF_DEFINES_MODULE_TYPE                 : "_ModuleType",\r
1042         #\r
1043         # Optional Fields\r
1044         #\r
1045         TAB_INF_DEFINES_INF_VERSION                 : "_AutoGenVersion",\r
1046         TAB_INF_DEFINES_COMPONENT_TYPE              : "_ComponentType",\r
1047         TAB_INF_DEFINES_MAKEFILE_NAME               : "_MakefileName",\r
1048         #TAB_INF_DEFINES_CUSTOM_MAKEFILE             : "_CustomMakefile",\r
1049         TAB_INF_DEFINES_VERSION_NUMBER              : "_Version",\r
1050         TAB_INF_DEFINES_VERSION_STRING              : "_Version",\r
1051         TAB_INF_DEFINES_VERSION                     : "_Version",\r
1052         TAB_INF_DEFINES_PCD_IS_DRIVER               : "_PcdIsDriver",\r
1053         TAB_INF_DEFINES_SHADOW                      : "_Shadow",\r
1054     }\r
1055 \r
1056     # dict used to convert Component type to Module type\r
1057     _MODULE_TYPE_ = {\r
1058         "LIBRARY"               :   "BASE",\r
1059         "SECURITY_CORE"         :   "SEC",\r
1060         "PEI_CORE"              :   "PEI_CORE",\r
1061         "COMBINED_PEIM_DRIVER"  :   "PEIM",\r
1062         "PIC_PEIM"              :   "PEIM",\r
1063         "RELOCATABLE_PEIM"      :   "PEIM",\r
1064         "PE32_PEIM"             :   "PEIM",\r
1065         "BS_DRIVER"             :   "DXE_DRIVER",\r
1066         "RT_DRIVER"             :   "DXE_RUNTIME_DRIVER",\r
1067         "SAL_RT_DRIVER"         :   "DXE_SAL_DRIVER",\r
1068     #    "BS_DRIVER"             :   "DXE_SMM_DRIVER",\r
1069     #    "BS_DRIVER"             :   "UEFI_DRIVER",\r
1070         "APPLICATION"           :   "UEFI_APPLICATION",\r
1071         "LOGO"                  :   "BASE",\r
1072     }\r
1073 \r
1074     # regular expression for converting XXX_FLAGS in [nmake] section to new type\r
1075     _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE)\r
1076     # dict used to convert old tool name used in [nmake] section to new ones\r
1077     _TOOL_CODE_ = {\r
1078         "C"         :   "CC",\r
1079         "LIB"       :   "SLINK",\r
1080         "LINK"      :   "DLINK",\r
1081     }\r
1082     \r
1083 \r
1084     ## Constructor of DscBuildData\r
1085     #\r
1086     #  Initialize object of DscBuildData\r
1087     #\r
1088     #   @param      FilePath        The path of platform description file\r
1089     #   @param      RawData         The raw data of DSC file\r
1090     #   @param      BuildDataBase   Database used to retrieve module/package information\r
1091     #   @param      Arch            The target architecture\r
1092     #   @param      Platform        The name of platform employing this module\r
1093     #   @param      Macros          Macros used for replacement in DSC file\r
1094     #\r
1095     def __init__(self, FilePath, RawData, BuildDatabase, Arch='COMMON', Platform='COMMON', Macros={}):\r
1096         self.DescFilePath = FilePath\r
1097         self._ModuleDir = os.path.dirname(FilePath)\r
1098         self._RawData = RawData\r
1099         self._Bdb = BuildDatabase\r
1100         self._Arch = Arch\r
1101         self._Platform = 'COMMON'\r
1102         self._Macros = Macros\r
1103         self._Clear()\r
1104 \r
1105     ## XXX[key] = value\r
1106     def __setitem__(self, key, value):\r
1107         self.__dict__[self._PROPERTY_[key]] = value\r
1108 \r
1109     ## value = XXX[key]\r
1110     def __getitem__(self, key):\r
1111         return self.__dict__[self._PROPERTY_[key]]\r
1112 \r
1113     ## "in" test support\r
1114     def __contains__(self, key):\r
1115         return key in self._PROPERTY_\r
1116 \r
1117     ## Set all internal used members of InfBuildData to None\r
1118     def _Clear(self):\r
1119         self._Header_               = None\r
1120         self._AutoGenVersion        = None\r
1121         self._DescFilePath          = None\r
1122         self._BaseName              = None\r
1123         self._ModuleType            = None\r
1124         self._ComponentType         = None\r
1125         self._Guid                  = None\r
1126         self._Version               = None\r
1127         self._PcdIsDriver           = None\r
1128         self._BinaryModule          = None\r
1129         self._Shadow                = None\r
1130         self._MakefileName          = None\r
1131         self._CustomMakefile        = None\r
1132         self._Specification         = None\r
1133         self._LibraryClass          = None\r
1134         self._ModuleEntryPointList  = None\r
1135         self._ModuleUnloadImageList = None\r
1136         self._ConstructorList       = None\r
1137         self._DestructorList        = None\r
1138         self._Binaries              = None\r
1139         self._Sources               = None\r
1140         self._LibraryClasses        = None\r
1141         self._Libraries             = None\r
1142         self._Protocols             = None\r
1143         self._Ppis                  = None\r
1144         self._Guids                 = None\r
1145         self._Includes              = None\r
1146         self._Packages              = None\r
1147         self._Pcds                  = None\r
1148         self._BuildOptions          = None\r
1149         self._Depex                 = None\r
1150 \r
1151     ## Get architecture\r
1152     def _GetArch(self):\r
1153         return self._Arch\r
1154 \r
1155     ## Set architecture\r
1156     #   \r
1157     #   Changing the default ARCH to another may affect all other information\r
1158     # because all information in a platform may be ARCH-related. That's\r
1159     # why we need to clear all internal used members, in order to cause all \r
1160     # information to be re-retrieved.\r
1161     # \r
1162     #   @param  Value   The value of ARCH\r
1163     # \r
1164     def _SetArch(self, Value):\r
1165         if self._Arch == Value:\r
1166             return\r
1167         self._Arch = Value\r
1168         self._Clear()\r
1169 \r
1170     ## Return the name of platform employing this module\r
1171     def _GetPlatform(self):\r
1172         return self._Platform\r
1173 \r
1174     ## Change the name of platform employing this module\r
1175     # \r
1176     #   Changing the default name of platform to another may affect some information\r
1177     # because they may be PLATFORM-related. That's why we need to clear all internal\r
1178     # used members, in order to cause all information to be re-retrieved.\r
1179     # \r
1180     def _SetPlatform(self, Value):\r
1181         if self._Platform == Value:\r
1182             return\r
1183         self._Platform = Value\r
1184         self._Clear()\r
1185 \r
1186     ## Retrieve all information in [Defines] section\r
1187     #\r
1188     #   (Retriving all [Defines] information in one-shot is just to save time.)\r
1189     # \r
1190     def _GetHeaderInfo(self):\r
1191         RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]\r
1192         for Record in RecordList:\r
1193             Name = Record[0]\r
1194             # items defined _PROPERTY_ don't need additional processing\r
1195             if Name in self:\r
1196                 self[Name] = Record[1]\r
1197             # some special items in [Defines] section need special treatment\r
1198             elif Name == 'EFI_SPECIFICATION_VERSION':\r
1199                 if self._Specification == None:\r
1200                     self._Specification = sdict()\r
1201                 self._Specification[Name] = Record[1]\r
1202             elif Name == 'EDK_RELEASE_VERSION':\r
1203                 if self._Specification == None:\r
1204                     self._Specification = sdict()\r
1205                 self._Specification[Name] = Record[1]\r
1206             elif Name == 'LIBRARY_CLASS':\r
1207                 if self._LibraryClass == None:\r
1208                     self._LibraryClass = []\r
1209                 ValueList = GetSplitValueList(Record[1])\r
1210                 LibraryClass = ValueList[0]\r
1211                 if len(ValueList) > 1:\r
1212                     SupModuleList = GetSplitValueList(ValueList[1], ' ')\r
1213                 else:\r
1214                     SupModuleList = SUP_MODULE_LIST\r
1215                 self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList))\r
1216             elif Name == 'ENTRY_POINT':\r
1217                 if self._ModuleEntryPointList == None:\r
1218                     self._ModuleEntryPointList = []\r
1219                 self._ModuleEntryPointList.append(Record[1])\r
1220             elif Name == 'UNLOAD_IMAGE':\r
1221                 if self._ModuleUnloadImageList == None:\r
1222                     self._ModuleUnloadImageList = []\r
1223                 if Record[1] == '':\r
1224                     continue\r
1225                 self._ModuleUnloadImageList.append(Record[1])\r
1226             elif Name == 'CONSTRUCTOR':\r
1227                 if self._ConstructorList == None:\r
1228                     self._ConstructorList = []\r
1229                 if Record[1] == '':\r
1230                     continue\r
1231                 self._ConstructorList.append(Record[1])\r
1232             elif Name == 'DESTRUCTOR':\r
1233                 if self._DestructorList == None:\r
1234                     self._DestructorList = []\r
1235                 if Record[1] == '':\r
1236                     continue\r
1237                 self._DestructorList.append(Record[1])\r
1238             elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE:\r
1239                 TokenList = GetSplitValueList(Record[1])\r
1240                 if self._CustomMakefile == None:\r
1241                     self._CustomMakefile = {}\r
1242                 if len(TokenList) < 2:\r
1243                     self._CustomMakefile['MSFT'] = TokenList[0]\r
1244                     self._CustomMakefile['GCC'] = TokenList[0]\r
1245                 else:\r
1246                     if TokenList[0] not in ['MSFT', 'GCC']:\r
1247                         EdkLogger.error("build", FORMAT_NOT_SUPPORTED,\r
1248                                         "No supported family [%s]" % TokenList[0], \r
1249                                         File=self.DescFilePath, Line=Record[-1])\r
1250                     self._CustomMakefile[TokenList[0]] = TokenList[1]\r
1251 \r
1252         # \r
1253         # Retrieve information in sections specific to R8.x modules\r
1254         # \r
1255         if self._AutoGenVersion < 0x00010005:   # _AutoGenVersion may be None, which is less than anything\r
1256             if self._ComponentType in self._MODULE_TYPE_:\r
1257                 self._ModuleType = self._MODULE_TYPE_[self._ComponentType]\r
1258             if self._ComponentType == 'LIBRARY':\r
1259                 self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)]\r
1260             # make use some [nmake] section macros\r
1261             RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform]\r
1262             for Name,Value,Dummy,Arch,Platform,ID,LineNo in RecordList:\r
1263                 if Name == "IMAGE_ENTRY_POINT":\r
1264                     if self._ModuleEntryPointList == None:\r
1265                         self._ModuleEntryPointList = []\r
1266                     self._ModuleEntryPointList.append(Value)\r
1267                 elif Name == "DPX_SOURCE":\r
1268                     File = NormPath(Value, self._Macros)\r
1269                     if not ValidFile(File, self._ModuleDir):\r
1270                         EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
1271                                         File=self.DescFilePath, Line=LineNo)\r
1272                     if self.Sources == None:\r
1273                         self._Sources = []\r
1274                     self._Sources.append(ModuleSourceFileClass(File, "", "", "", ""))\r
1275                 else:\r
1276                     ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name)\r
1277                     if len(ToolList) == 0 or len(ToolList) != 1:\r
1278                         EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name, \r
1279                                        File=self.DescFilePath, Line=LineNo)\r
1280                     else:\r
1281                         if self._BuildOptions == None:\r
1282                             self._BuildOptions = sdict()\r
1283 \r
1284                         if ToolList[0] in self._TOOL_CODE_:\r
1285                             Tool = self._TOOL_CODE_[ToolList[0]]\r
1286                         else:\r
1287                             Tool = ToolList[0]\r
1288                         ToolChain = "*_*_*_%s_FLAGS" % Tool\r
1289                         ToolChainFamily = 'MSFT'    # R8.x only support MSFT tool chain\r
1290                         if (ToolChainFamily, ToolChain) not in self._BuildOptions:\r
1291                             self._BuildOptions[ToolChainFamily, ToolChain] = Value\r
1292                         else:\r
1293                             OptionString = self._BuildOptions[ToolChainFamily, ToolChain]\r
1294                             self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value\r
1295         # set _Header to non-None in order to avoid database re-querying\r
1296         self._Header_ = 'DUMMY'\r
1297 \r
1298     ## Retrieve file version\r
1299     def _GetInfVersion(self):\r
1300         if self._AutoGenVersion == None:\r
1301             if self._Header_ == None:\r
1302                 self._GetHeaderInfo()\r
1303             if self._AutoGenVersion == None:\r
1304                 self._AutoGenVersion = 0x00010000\r
1305         return self._AutoGenVersion\r
1306 \r
1307     ## Retrieve BASE_NAME\r
1308     def _GetBaseName(self):\r
1309         if self._BaseName == None:\r
1310             if self._Header_ == None:\r
1311                 self._GetHeaderInfo()\r
1312             if self._BaseName == None:\r
1313                 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.DescFilePath)\r
1314         return self._BaseName\r
1315 \r
1316     ## Retrieve MODULE_TYPE\r
1317     def _GetModuleType(self):\r
1318         if self._ModuleType == None:\r
1319             if self._Header_ == None:\r
1320                 self._GetHeaderInfo()\r
1321             if self._ModuleType == None:\r
1322                 self._ModuleType = 'BASE'\r
1323         return self._ModuleType\r
1324 \r
1325     ## Retrieve COMPONENT_TYPE\r
1326     def _GetComponentType(self):\r
1327         if self._ComponentType == None:\r
1328             if self._Header_ == None:\r
1329                 self._GetHeaderInfo()\r
1330             if self._ComponentType == None:\r
1331                 self._ComponentType = ''\r
1332         return self._ComponentType\r
1333 \r
1334     ## Retrieve file guid\r
1335     def _GetFileGuid(self):\r
1336         if self._Guid == None:\r
1337             if self._Header_ == None:\r
1338                 self._GetHeaderInfo()\r
1339             if self._Guid == None:\r
1340                 self._Guid = '00000000-0000-0000-000000000000'\r
1341         return self._Guid\r
1342 \r
1343     ## Retrieve module version\r
1344     def _GetVersion(self):\r
1345         if self._Version == None:\r
1346             if self._Header_ == None:\r
1347                 self._GetHeaderInfo()\r
1348             if self._Version == None:\r
1349                 self._Version = '0.0'\r
1350         return self._Version\r
1351 \r
1352     ## Retrieve PCD_IS_DRIVER\r
1353     def _GetPcdIsDriver(self):\r
1354         if self._PcdIsDriver == None:\r
1355             if self._Header_ == None:\r
1356                 self._GetHeaderInfo()\r
1357             if self._PcdIsDriver == None:\r
1358                 self._PcdIsDriver = ''\r
1359         return self._PcdIsDriver\r
1360 \r
1361     ## Retrieve SHADOW\r
1362     def _GetShadow(self):\r
1363         if self._Shadow == None:\r
1364             if self._Header_ == None:\r
1365                 self._GetHeaderInfo()\r
1366             if self._Shadow != None and self._Shadow.upper() == 'TRUE':\r
1367                 self._Shadow = True\r
1368             else:\r
1369                 self._Shadow = False\r
1370         return self._Shadow\r
1371 \r
1372     ## Retrieve CUSTOM_MAKEFILE\r
1373     def _GetMakefile(self):\r
1374         if self._CustomMakefile == None:\r
1375             if self._Header_ == None:\r
1376                 self._GetHeaderInfo()\r
1377             if self._CustomMakefile == None:\r
1378                 self._CustomMakefile = {}\r
1379         return self._CustomMakefile\r
1380 \r
1381     ## Retrieve EFI_SPECIFICATION_VERSION\r
1382     def _GetSpec(self):\r
1383         if self._Specification == None:\r
1384             if self._Header_ == None:\r
1385                 self._GetHeaderInfo()\r
1386             if self._Specification == None:\r
1387                 self._Specification = {}\r
1388         return self._Specification\r
1389 \r
1390     ## Retrieve LIBRARY_CLASS\r
1391     def _GetLibraryClass(self):\r
1392         if self._LibraryClass == None:\r
1393             if self._Header_ == None:\r
1394                 self._GetHeaderInfo()\r
1395             if self._LibraryClass == None:\r
1396                 self._LibraryClass = []\r
1397         return self._LibraryClass\r
1398 \r
1399     ## Retrieve ENTRY_POINT\r
1400     def _GetEntryPoint(self):\r
1401         if self._ModuleEntryPointList == None:\r
1402             if self._Header_ == None:\r
1403                 self._GetHeaderInfo()\r
1404             if self._ModuleEntryPointList == None:\r
1405                 self._ModuleEntryPointList = []\r
1406         return self._ModuleEntryPointList\r
1407 \r
1408     ## Retrieve UNLOAD_IMAGE\r
1409     def _GetUnloadImage(self):\r
1410         if self._ModuleUnloadImageList == None:\r
1411             if self._Header_ == None:\r
1412                 self._GetHeaderInfo()\r
1413             if self._ModuleUnloadImageList == None:\r
1414                 self._ModuleUnloadImageList = []\r
1415         return self._ModuleUnloadImageList\r
1416 \r
1417     ## Retrieve CONSTRUCTOR\r
1418     def _GetConstructor(self):\r
1419         if self._ConstructorList == None:\r
1420             if self._Header_ == None:\r
1421                 self._GetHeaderInfo()\r
1422             if self._ConstructorList == None:\r
1423                 self._ConstructorList = []\r
1424         return self._ConstructorList\r
1425 \r
1426     ## Retrieve DESTRUCTOR\r
1427     def _GetDestructor(self):\r
1428         if self._DestructorList == None:\r
1429             if self._Header_ == None:\r
1430                 self._GetHeaderInfo()\r
1431             if self._DestructorList == None:\r
1432                 self._DestructorList = []\r
1433         return self._DestructorList\r
1434                         \r
1435     ## Retrieve binary files\r
1436     def _GetBinaryFiles(self):\r
1437         if self._Binaries == None:\r
1438             self._Binaries = []\r
1439             RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]\r
1440             for Record in RecordList:\r
1441                 FileType = Record[0]\r
1442                 File = NormPath(Record[1], self._Macros)\r
1443                 LineNo = Record[-1]\r
1444                 if not ValidFile(File, self._ModuleDir):\r
1445                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
1446                                     File=self.DescFilePath, Line=LineNo)\r
1447                 Target = Record[2]\r
1448                 FeatureFlag = Record[3]\r
1449                 self._Binaries.append(ModuleBinaryFileClass(File, FileType, Target, FeatureFlag, self._Arch))\r
1450         return self._Binaries\r
1451 \r
1452     ## Retrieve source files\r
1453     def _GetSourceFiles(self):\r
1454         if self._Sources == None:\r
1455             self._Sources = []\r
1456             RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]\r
1457             for Record in RecordList:\r
1458                 File = NormPath(Record[0], self._Macros)\r
1459                 LineNo = Record[-1]\r
1460                 if not ValidFile(File, self._ModuleDir):\r
1461                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
1462                                     File=self.DescFilePath, Line=LineNo)\r
1463                 ToolChainFamily = Record[1]\r
1464                 TagName = Record[2]\r
1465                 ToolCode = Record[3]\r
1466                 FeatureFlag = Record[4]\r
1467                 self._Sources.append(ModuleSourceFileClass(File, TagName, ToolCode, ToolChainFamily, FeatureFlag))\r
1468         return self._Sources\r
1469 \r
1470     ## Retrieve library classes employed by this module\r
1471     def _GetLibraryClassUses(self):\r
1472         if self._LibraryClasses == None:\r
1473             self._LibraryClasses = sdict()\r
1474             RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]\r
1475             for Record in RecordList:\r
1476                 Lib = Record[0]\r
1477                 Instance = Record[1]\r
1478                 if Instance != None and Instance != '':\r
1479                     Instance = NormPath(Instance, self._Macros)\r
1480                 self._LibraryClasses[Lib] = Instance\r
1481         return self._LibraryClasses\r
1482 \r
1483     ## Retrieve library names (for R8.x style of modules)\r
1484     def _GetLibraryNames(self):\r
1485         if self._Libraries == None:\r
1486             self._Libraries = []\r
1487             RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]\r
1488             for Record in RecordList:\r
1489                 # in case of name with '.lib' extension, which is unusual in R8.x inf\r
1490                 LibraryName = os.path.splitext(Record[0])[0]\r
1491                 if LibraryName not in self._Libraries:\r
1492                     self._Libraries.append(LibraryName)\r
1493         return self._Libraries\r
1494 \r
1495     ## Retrieve protocols consumed/produced by this module\r
1496     def _GetProtocols(self):\r
1497         if self._Protocols == None:\r
1498             self._Protocols = sdict()\r
1499             RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]\r
1500             for Record in RecordList:\r
1501                 CName = Record[0]\r
1502                 Value = GuidValue(CName, self.Packages)\r
1503                 if Value == None:\r
1504                     PackageList = '\t' + "\n\t".join([str(P) for P in self.Packages])\r
1505                     EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Value of [%s] is not found in" % CName,\r
1506                                     ExtraData=PackageList, File=self.DescFilePath, Line=Record[-1])\r
1507                 self._Protocols[CName] = Value\r
1508         return self._Protocols\r
1509 \r
1510     ## Retrieve PPIs consumed/produced by this module\r
1511     def _GetPpis(self):\r
1512         if self._Ppis == None:\r
1513             self._Ppis = sdict()\r
1514             RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]\r
1515             for Record in RecordList:\r
1516                 CName = Record[0]\r
1517                 Value = GuidValue(CName, self.Packages)\r
1518                 if Value == None:\r
1519                     PackageList = '\t' + "\n\t".join([str(P) for P in self.Packages])\r
1520                     EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Value of [%s] is not found in " % CName,\r
1521                                     ExtraData=PackageList, File=self.DescFilePath, Line=Record[-1])\r
1522                 self._Ppis[CName] = Value\r
1523         return self._Ppis\r
1524 \r
1525     ## Retrieve GUIDs consumed/produced by this module\r
1526     def _GetGuids(self):\r
1527         if self._Guids == None:\r
1528             self._Guids = sdict()\r
1529             RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]\r
1530             for Record in RecordList:\r
1531                 CName = Record[0]\r
1532                 Value = GuidValue(CName, self.Packages)\r
1533                 if Value == None:\r
1534                     PackageList = '\t' + "\n\t".join([str(P) for P in self.Packages])\r
1535                     EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Value of [%s] is not found in" % CName,\r
1536                                     ExtraData=PackageList, File=self.DescFilePath, Line=Record[-1])\r
1537                 self._Guids[CName] = Value\r
1538         return self._Guids\r
1539 \r
1540     ## Retrieve include paths necessary for this module (for R8.x style of modules)\r
1541     def _GetIncludes(self):\r
1542         if self._Includes == None:\r
1543             self._Includes = []\r
1544             RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]\r
1545             # [includes] section must be used only in old (R8.x) inf file\r
1546             if self.AutoGenVersion >= 0x00010005 and len(RecordList) > 0:\r
1547                 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, "No [include] section allowed",\r
1548                                 File=self.DescFilePath, Line=RecordList[0][-1]-1)\r
1549             for Record in RecordList:\r
1550                 File = NormPath(Record[0], self._Macros)\r
1551                 LineNo = Record[-1]\r
1552                 #if File[0] == '.':\r
1553                 #    if not ValidFile(File, self._ModuleDir):\r
1554                 #        EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
1555                 #                        File=self.DescFilePath, Line=LineNo)\r
1556                 #else:\r
1557                 #    if not ValidFile(File):\r
1558                 #        EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
1559                 #                        File=self.DescFilePath, Line=LineNo)\r
1560                 if File in self._Includes:\r
1561                     continue\r
1562                 self._Includes.append(File)\r
1563         return self._Includes\r
1564 \r
1565     ## Retrieve packages this module depends on\r
1566     def _GetPackages(self):\r
1567         if self._Packages == None:\r
1568             self._Packages = []\r
1569             RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]\r
1570             for Record in RecordList:\r
1571                 File = NormPath(Record[0], self._Macros)\r
1572                 LineNo = Record[-1]\r
1573                 if not ValidFile(File):\r
1574                     EdkLogger.error('build', FILE_NOT_FOUND, ExtraData=File,\r
1575                                     File=self.DescFilePath, Line=LineNo)\r
1576                 # parse this package now. we need it to get protocol/ppi/guid value\r
1577                 Package = self._Bdb[File, self._Arch]\r
1578                 self._Packages.append(Package)\r
1579         return self._Packages\r
1580 \r
1581     ## Retrieve PCDs used in this module\r
1582     def _GetPcds(self):\r
1583         if self._Pcds == None:\r
1584             self._Pcds = {}\r
1585             self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))\r
1586             self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))\r
1587             self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))\r
1588             self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))\r
1589             self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))\r
1590         return self._Pcds\r
1591 \r
1592     ## Retrieve build options specific to this module\r
1593     def _GetBuildOptions(self):\r
1594         if self._BuildOptions == None:\r
1595             self._BuildOptions = sdict()\r
1596             RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]\r
1597             for Record in RecordList:\r
1598                 ToolChainFamily = Record[0]\r
1599                 ToolChain = Record[1]\r
1600                 Option = Record[2]\r
1601                 if (ToolChainFamily, ToolChain) not in self._BuildOptions:\r
1602                     self._BuildOptions[ToolChainFamily, ToolChain] = Option\r
1603                 else:\r
1604                     # concatenate the option string if they're for the same tool \r
1605                     OptionString = self._BuildOptions[ToolChainFamily, ToolChain]\r
1606                     self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option\r
1607         return self._BuildOptions\r
1608 \r
1609     ## Retrieve depedency expression\r
1610     def _GetDepex(self):\r
1611         if self._Depex == None:\r
1612             self._Depex = []\r
1613             RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch, self._Platform]\r
1614             for Record in RecordList:\r
1615                 TokenList = Record[0].split()\r
1616                 for Token in TokenList:\r
1617                     if Token in DEPEX_SUPPORTED_OPCODE or Token.endswith(".inf"):\r
1618                         self._Depex.append(Token)\r
1619                     else:\r
1620                         # get the GUID value now\r
1621                         Value = GuidValue(Token, self.Packages)\r
1622                         if Value == None:\r
1623                             PackageList = '\t' + "\n\t".join([str(P) for P in self.Packages])\r
1624                             EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Value of [%s] is not found in" % Token,\r
1625                                             ExtraData=PackageList, File=self.DescFilePath, Line=Record[-1])\r
1626                         self._Depex.append(Value)\r
1627         return self._Depex\r
1628 \r
1629     ## Retrieve PCD for given type\r
1630     def _GetPcd(self, Type):\r
1631         Pcds = {}\r
1632         PcdDict = tdict(True, 4)\r
1633         PcdSet = set()\r
1634         RecordList = self._RawData[Type, self._Arch, self._Platform]\r
1635         for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Dummy1, LineNo in RecordList:\r
1636             PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)\r
1637             PcdSet.add((PcdCName, TokenSpaceGuid))\r
1638             # get the guid value\r
1639             if TokenSpaceGuid not in self.Guids:\r
1640                 Value = GuidValue(TokenSpaceGuid, self.Packages)\r
1641                 if Value == None:\r
1642                     PackageList = '\t' + "\n\t".join([str(P) for P in self.Packages])\r
1643                     EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Value of [%s] is not found in" % PcdCName,\r
1644                                     ExtraData=PackageList, File=self.DescFilePath, Line=LineNo)\r
1645                 self.Guids[TokenSpaceGuid] = Value\r
1646 \r
1647         # resolve PCD type, value, datum info, etc. by getting its definition from package\r
1648         for PcdCName, TokenSpaceGuid in PcdSet:\r
1649             ValueList = ['', '']\r
1650             Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]\r
1651             if Setting == None:\r
1652                 continue\r
1653             TokenList = Setting.split(TAB_VALUE_SPLIT)\r
1654             ValueList[0:len(TokenList)] = TokenList\r
1655             DefaultValue = ValueList[0]\r
1656             Pcd = PcdClassObject(\r
1657                     PcdCName,\r
1658                     TokenSpaceGuid,\r
1659                     '',\r
1660                     '',\r
1661                     DefaultValue,\r
1662                     '',\r
1663                     '',\r
1664                     {},\r
1665                     self.Guids[TokenSpaceGuid]\r
1666                     )\r
1667 \r
1668             # get necessary info from package declaring this PCD\r
1669             for Package in self.Packages:\r
1670                 # \r
1671                 # 'dynamic' in INF means its type is determined by platform;\r
1672                 # if platform doesn't give its type, use 'lowest' one in the \r
1673                 # following order, if any\r
1674                 # \r
1675                 #   "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"\r
1676                 # \r
1677                 PcdType = self._PCD_TYPE_STRING_[Type]\r
1678                 if Type in [MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:\r
1679                     for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]:\r
1680                         if (PcdCName, TokenSpaceGuid, T) in Package.Pcds:\r
1681                             PcdType = T\r
1682                             break\r
1683 \r
1684                 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:\r
1685                     PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]\r
1686                     Pcd.Type = PcdType\r
1687                     Pcd.TokenValue = PcdInPackage.TokenValue\r
1688                     Pcd.DatumType = PcdInPackage.DatumType\r
1689                     Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize\r
1690                     if Pcd.DefaultValue in [None, '']:\r
1691                         Pcd.DefaultValue = PcdInPackage.DefaultValue\r
1692                     break\r
1693             else:\r
1694                 EdkLogger.error(\r
1695                             'build', \r
1696                             PARSER_ERROR,\r
1697                             "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdCName, self.DescFilePath),\r
1698                             File =self.DescFilePath, Line=LineNo,\r
1699                             ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages])\r
1700                             )\r
1701             Pcds[PcdCName, TokenSpaceGuid] = Pcd\r
1702         return Pcds\r
1703 \r
1704     Arch                    = property(_GetArch, _SetArch)\r
1705     Platform                = property(_GetPlatform, _SetPlatform)\r
1706 \r
1707     AutoGenVersion          = property(_GetInfVersion)\r
1708     BaseName                = property(_GetBaseName)\r
1709     ModuleType              = property(_GetModuleType)\r
1710     ComponentType           = property(_GetComponentType)\r
1711     Guid                    = property(_GetFileGuid)\r
1712     Version                 = property(_GetVersion)\r
1713     PcdIsDriver             = property(_GetPcdIsDriver)\r
1714     Shadow                  = property(_GetShadow)\r
1715     CustomMakefile          = property(_GetMakefile)\r
1716     Specification           = property(_GetSpec)\r
1717     LibraryClass            = property(_GetLibraryClass)\r
1718     ModuleEntryPointList    = property(_GetEntryPoint)\r
1719     ModuleUnloadImageList   = property(_GetUnloadImage)\r
1720     ConstructorList         = property(_GetConstructor)\r
1721     DestructorList          = property(_GetDestructor)\r
1722 \r
1723     Binaries                = property(_GetBinaryFiles)\r
1724     Sources                 = property(_GetSourceFiles)\r
1725     LibraryClasses          = property(_GetLibraryClassUses)\r
1726     Libraries               = property(_GetLibraryNames)\r
1727     Protocols               = property(_GetProtocols)\r
1728     Ppis                    = property(_GetPpis)\r
1729     Guids                   = property(_GetGuids)\r
1730     Includes                = property(_GetIncludes)\r
1731     Packages                = property(_GetPackages)\r
1732     Pcds                    = property(_GetPcds)\r
1733     BuildOptions            = property(_GetBuildOptions)\r
1734     Depex                   = property(_GetDepex)\r
1735 \r
1736 \r
1737 ## Database\r
1738 #\r
1739 #   This class defined the build databse for all modules, packages and platform.\r
1740 # It will call corresponding parser for the given file if it cannot find it in\r
1741 # the database.\r
1742\r
1743 # @param DbPath             Path of database file\r
1744 # @param GlobalMacros       Global macros used for replacement during file parsing\r
1745 # @prarm RenewDb=False      Create new database file if it's already there\r
1746 #\r
1747 class WorkspaceDatabase(object):\r
1748     # file parser\r
1749     _FILE_PARSER_ = {\r
1750         MODEL_FILE_INF  :   InfParser,\r
1751         MODEL_FILE_DEC  :   DecParser,\r
1752         MODEL_FILE_DSC  :   DscParser,\r
1753         MODEL_FILE_FDF  :   None, #FdfParser,\r
1754         MODEL_FILE_CIF  :   None\r
1755     }\r
1756 \r
1757     # file table\r
1758     _FILE_TABLE_ = {\r
1759         MODEL_FILE_INF  :   ModuleTable,\r
1760         MODEL_FILE_DEC  :   PackageTable,\r
1761         MODEL_FILE_DSC  :   PlatformTable,\r
1762     }\r
1763 \r
1764     # default database file path\r
1765     _DB_PATH_ = "Conf/.cache/build.db"\r
1766 \r
1767     # \r
1768     # internal class used for call corresponding file parser and caching the result\r
1769     # to avoid unnecessary re-parsing\r
1770     # \r
1771     class BuildObjectFactory(object):\r
1772         _FILE_TYPE_ = {\r
1773             ".INF"  : MODEL_FILE_INF,\r
1774             ".DEC"  : MODEL_FILE_DEC,\r
1775             ".DSC"  : MODEL_FILE_DSC,\r
1776             ".FDF"  : MODEL_FILE_FDF,\r
1777             ".CIF"  : MODEL_FILE_CIF,\r
1778         }\r
1779 \r
1780         # convert to xxxBuildData object\r
1781         _GENERATOR_ = {\r
1782             MODEL_FILE_INF  :   InfBuildData,\r
1783             MODEL_FILE_DEC  :   DecBuildData,\r
1784             MODEL_FILE_DSC  :   DscBuildData,\r
1785             MODEL_FILE_FDF  :   None #FlashDefTable,\r
1786         }\r
1787 \r
1788         _CACHE_ = {}    # (FilePath, Arch)  : <object>\r
1789 \r
1790         # constructor\r
1791         def __init__(self, WorkspaceDb):\r
1792             self.WorkspaceDb = WorkspaceDb\r
1793 \r
1794         # key = (FilePath, Arch='COMMON')\r
1795         def __contains__(self, Key):\r
1796             FilePath = Key[0]\r
1797             Arch = 'COMMON'\r
1798             if len(Key) > 1:\r
1799                 Arch = Key[1]\r
1800             return (FilePath, Arch) in self._CACHE_\r
1801 \r
1802         # key = (FilePath, Arch='COMMON')\r
1803         def __getitem__(self, Key):\r
1804             FilePath = Key[0]\r
1805             Arch = 'COMMON'\r
1806             Platform = 'COMMON'\r
1807             if len(Key) > 1:\r
1808                 Arch = Key[1]\r
1809             if len(Key) > 2:\r
1810                 Platform = Key[2]\r
1811 \r
1812             # if it's generated before, just return the cached one\r
1813             Key = (FilePath, Arch)\r
1814             if Key in self._CACHE_:\r
1815                 return self._CACHE_[Key]\r
1816 \r
1817             # check file type\r
1818             FileExt = os.path.splitext(FilePath)[1].upper()\r
1819             if FileExt not in self._FILE_TYPE_:\r
1820                 return None\r
1821             FileType = self._FILE_TYPE_[FileExt]\r
1822             if FileType not in self._GENERATOR_:\r
1823                 return None\r
1824 \r
1825             # get table for current file\r
1826             MetaFile = self.WorkspaceDb[FilePath, FileType]\r
1827             BuildObject = self._GENERATOR_[FileType](\r
1828                                     FilePath, \r
1829                                     MetaFile, \r
1830                                     self,\r
1831                                     Arch,\r
1832                                     Platform,\r
1833                                     self.WorkspaceDb._GlobalMacros\r
1834                                     )\r
1835             self._CACHE_[Key] = BuildObject\r
1836             return BuildObject\r
1837 \r
1838     # placeholder for file format conversion\r
1839     class TransformObjectFactory:\r
1840         def __init__(self, WorkspaceDb):\r
1841             self.WorkspaceDb = WorkspaceDb\r
1842 \r
1843         # key = FilePath, Arch\r
1844         def __getitem__(self, Key):\r
1845             pass\r
1846 \r
1847     ## Constructor of WorkspaceDatabase\r
1848     # \r
1849     # @param DbPath             Path of database file\r
1850     # @param GlobalMacros       Global macros used for replacement during file parsing\r
1851     # @prarm RenewDb=False      Create new database file if it's already there\r
1852     #\r
1853     def __init__(self, DbPath, GlobalMacros={}, RenewDb=False):\r
1854         self._GlobalMacros = GlobalMacros\r
1855 \r
1856         if DbPath == None or DbPath == '':\r
1857             DbPath = self._DB_PATH_\r
1858 \r
1859         # don't create necessary path for db in memory\r
1860         if DbPath != ':memory:':\r
1861             DbDir = os.path.split(DbPath)[0]\r
1862             if not os.path.exists(DbDir):\r
1863                 os.makedirs(DbDir)\r
1864         # remove db file in case inconsistency between db and file in file system\r
1865         if RenewDb and os.path.exists(DbPath):\r
1866             os.remove(DbPath)\r
1867         # create db with optimized parameters\r
1868         self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED')\r
1869         self.Conn.execute("PRAGMA synchronous=OFF")\r
1870         self.Conn.execute("PRAGMA temp_store=MEMORY")\r
1871         self.Conn.execute("PRAGMA count_changes=OFF")\r
1872         self.Conn.execute("PRAGMA cache_size=8192")\r
1873         #self.Conn.execute("PRAGMA page_size=8192")\r
1874 \r
1875         # to avoid non-ascii character conversion issue\r
1876         self.Conn.text_factory = str\r
1877         self.Cur = self.Conn.cursor()\r
1878 \r
1879         # create table for internal uses\r
1880         self.TblDataModel = TableDataModel(self.Cur)\r
1881         self.TblFile = TableFile(self.Cur)\r
1882 \r
1883         # conversion object for build or file format conversion purpose\r
1884         self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)\r
1885         self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)\r
1886     \r
1887     ## Initialize build database\r
1888     def InitDatabase(self):\r
1889         EdkLogger.verbose("\nInitialize build database started ...")\r
1890         \r
1891         #\r
1892         # Create new tables\r
1893         #\r
1894         self.TblDataModel.Create(False)\r
1895         self.TblFile.Create(False)\r
1896         \r
1897         #\r
1898         # Initialize table DataModel\r
1899         #\r
1900         self.TblDataModel.InitTable()\r
1901         EdkLogger.verbose("Initialize build database ... DONE!")\r
1902 \r
1903     ## Query a table\r
1904     #\r
1905     # @param Table:  The instance of the table to be queried\r
1906     #\r
1907     def QueryTable(self, Table):\r
1908         Table.Query()\r
1909     \r
1910     ## Close entire database\r
1911     #\r
1912     # Commit all first \r
1913     # Close the connection and cursor\r
1914     #\r
1915     def Close(self):\r
1916         self.Conn.commit()\r
1917         self.Cur.close()\r
1918         self.Conn.close()\r
1919 \r
1920     ## Get unique file ID for the gvien file\r
1921     def GetFileId(self, FilePath):\r
1922         return self.TblFile.GetFileId(FilePath)\r
1923 \r
1924     ## Get file type value for the gvien file ID\r
1925     def GetFileType(self, FileId):\r
1926         return self.TblFile.GetFileType(FileId)\r
1927 \r
1928     ## Get time stamp stored in file table\r
1929     def GetTimeStamp(self, FileId):\r
1930         return self.TblFile.GetFileTimeStamp(FileId)\r
1931 \r
1932     ## Update time stamp in file table\r
1933     def SetTimeStamp(self, FileId, TimeStamp):\r
1934         return self.TblFile.SetFileTimeStamp(FileId, TimeStamp)\r
1935 \r
1936     ## Check if a table integrity flag exists or not\r
1937     def CheckIntegrity(self, TableName):\r
1938         Result = self.Cur.execute("select min(ID) from %s" % (TableName)).fetchall()\r
1939         if Result[0][0] != -1:\r
1940             return False\r
1941         return True\r
1942 \r
1943     ## Compose table name for given file type and file ID\r
1944     def GetTableName(self, FileType, FileId):\r
1945         return "_%s_%s" % (FileType, FileId)\r
1946 \r
1947     ## Return a temp table containing all content of the given file\r
1948     # \r
1949     #   @param  FileInfo    The tuple containing path and type of a file\r
1950     # \r
1951     def __getitem__(self, FileInfo):\r
1952         FilePath, FileType = FileInfo\r
1953         if FileType not in self._FILE_TABLE_:\r
1954             return None\r
1955 \r
1956         # flag used to indicate if it's parsed or not\r
1957         Parsed = False\r
1958         FileId = self.GetFileId(FilePath)\r
1959         if FileId != None:\r
1960             TimeStamp = os.stat(FilePath)[8]\r
1961             TableName = self.GetTableName(FileType, FileId)\r
1962             if TimeStamp != self.GetTimeStamp(FileId):\r
1963                 # update the timestamp in database\r
1964                 self.SetTimeStamp(FileId, TimeStamp)\r
1965             else:\r
1966                 # if the table exists and is integrity, don't parse it\r
1967                 Parsed = self.CheckIntegrity(TableName)\r
1968         else:\r
1969             FileId = self.TblFile.InsertFile(FilePath, FileType)\r
1970             TableName = self.GetTableName(FileType, FileId)\r
1971 \r
1972         FileTable = self._FILE_TABLE_[FileType](self.Cur, TableName, FileId)\r
1973         FileTable.Create(not Parsed)\r
1974         Parser = self._FILE_PARSER_[FileType](FilePath, FileId, FileType, FileTable)\r
1975         # set the "Finished" flag in parser in order to avoid re-parsing (if parsed)\r
1976         Parser.Finished = Parsed\r
1977         return Parser\r
1978 \r
1979     ## Summarize all packages in the database\r
1980     def _GetPackageList(self):\r
1981         PackageList = []\r
1982         for Module in self.ModuleList:\r
1983             for Package in Module.Packages:\r
1984                 if Package not in PackageList:\r
1985                     PackageList.append(Package)\r
1986         return PackageList\r
1987 \r
1988     ## Summarize all platforms in the database\r
1989     def _GetPlatformList(self):\r
1990         PlatformList = []\r
1991         for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC):\r
1992             try:\r
1993                 Platform = self.BuildObject[PlatformFile, 'COMMON']\r
1994             except:\r
1995                 Platform = None\r
1996             if Platform != None:\r
1997                 PlatformList.append(Platform)\r
1998         return PlatformList\r
1999 \r
2000     ## Summarize all modules in the database\r
2001     def _GetModuleList(self):\r
2002         ModuleList = []\r
2003         for ModuleFile in self.TblFile.GetFileList(MODEL_FILE_INF):\r
2004             try:\r
2005                 Module = self.BuildObject[ModuleFile, 'COMMON']\r
2006             except:\r
2007                 Module = None\r
2008             if Module != None:\r
2009                 ModuleList.append(Module)\r
2010         return ModuleList\r
2011 \r
2012     PlatformList = property(_GetPlatformList)\r
2013     PackageList = property(_GetPackageList)\r
2014     ModuleList = property(_GetModuleList)\r
2015 \r
2016 ##\r
2017 #\r
2018 # This acts like the main() function for the script, unless it is 'import'ed into another\r
2019 # script.\r
2020 #\r
2021 if __name__ == '__main__':\r
2022     pass\r
2023 \r