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