]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
Sync EDKII BaseTools to BaseTools project r1971
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / WorkspaceDatabase.py
CommitLineData
52302d4d
LG
1## @file\r
2# This file is used to create a database used by build tool\r
3#\r
40d841f6
LG
4# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
5# This program and the accompanying materials\r
52302d4d
LG
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
17import sqlite3\r
18import os\r
19import os.path\r
20import pickle\r
21\r
22import Common.EdkLogger as EdkLogger\r
23import Common.GlobalData as GlobalData\r
24\r
25from Common.String import *\r
26from Common.DataType import *\r
27from Common.Misc import *\r
28from types import *\r
29\r
30from CommonDataClass.CommonClass import SkuInfoClass\r
31\r
32from MetaDataTable import *\r
33from MetaFileTable import *\r
34from MetaFileParser import *\r
35from 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
42class 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
768class 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
1088class 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
2005class 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
2213determine 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
2373if __name__ == '__main__':\r
2374 pass\r
2375\r