1 ## @file 2 # This file is used to create a database used by build tool 3 # 4 # Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR> 5 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> 6 # This program and the accompanying materials 7 # are licensed and made available under the terms and conditions of the BSD License 8 # which accompanies this distribution. The full text of the license may be found at 9 # http://opensource.org/licenses/bsd-license.php 10 # 11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 # 14 15 ## 16 # Import Modules 17 # 18 import sqlite3 19 import Common.LongFilePathOs as os 20 import pickle 21 import uuid 22 23 import Common.EdkLogger as EdkLogger 24 import Common.GlobalData as GlobalData 25 from Common.MultipleWorkspace import MultipleWorkspace as mws 26 27 from Common.String import * 28 from Common.DataType import * 29 from Common.Misc import * 30 from types import * 31 32 from CommonDataClass.CommonClass import SkuInfoClass 33 34 from MetaDataTable import * 35 from MetaFileTable import * 36 from MetaFileParser import * 37 from BuildClassObject import * 38 from WorkspaceCommon import GetDeclaredPcd 39 from Common.Misc import AnalyzeDscPcd 40 from Common.Misc import ProcessDuplicatedInf 41 import re 42 from Common.Parsing import IsValidWord 43 from Common.VariableAttributes import VariableAttributes 44 import Common.GlobalData as GlobalData 45 46 ## Platform build information from DSC file 47 # 48 # This class is used to retrieve information stored in database and convert them 49 # into PlatformBuildClassObject form for easier use for AutoGen. 50 # 51 class DscBuildData(PlatformBuildClassObject): 52 # dict used to convert PCD type in database to string used by build tool 53 _PCD_TYPE_STRING_ = { 54 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild", 55 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule", 56 MODEL_PCD_FEATURE_FLAG : "FeatureFlag", 57 MODEL_PCD_DYNAMIC : "Dynamic", 58 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic", 59 MODEL_PCD_DYNAMIC_HII : "DynamicHii", 60 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd", 61 MODEL_PCD_DYNAMIC_EX : "DynamicEx", 62 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx", 63 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii", 64 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd", 65 } 66 67 # dict used to convert part of [Defines] to members of DscBuildData directly 68 _PROPERTY_ = { 69 # 70 # Required Fields 71 # 72 TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName", 73 TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid", 74 TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version", 75 TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification", 76 #TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory", 77 #TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList", 78 #TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets", 79 TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName", 80 #TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition", 81 TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber", 82 TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName", 83 TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress", 84 TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress", 85 #TAB_DSC_DEFINES_RFC_LANGUAGES : "_RFCLanguages", 86 #TAB_DSC_DEFINES_ISO_LANGUAGES : "_ISOLanguages", 87 } 88 89 # used to compose dummy library class name for those forced library instances 90 _NullLibraryNumber = 0 91 92 ## Constructor of DscBuildData 93 # 94 # Initialize object of DscBuildData 95 # 96 # @param FilePath The path of platform description file 97 # @param RawData The raw data of DSC file 98 # @param BuildDataBase Database used to retrieve module/package information 99 # @param Arch The target architecture 100 # @param Platform (not used for DscBuildData) 101 # @param Macros Macros used for replacement in DSC file 102 # 103 def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None): 104 self.MetaFile = FilePath 105 self._RawData = RawData 106 self._Bdb = BuildDataBase 107 self._Arch = Arch 108 self._Target = Target 109 self._Toolchain = Toolchain 110 self._Clear() 111 self._HandleOverridePath() 112 113 ## XXX[key] = value 114 def __setitem__(self, key, value): 115 self.__dict__[self._PROPERTY_[key]] = value 116 117 ## value = XXX[key] 118 def __getitem__(self, key): 119 return self.__dict__[self._PROPERTY_[key]] 120 121 ## "in" test support 122 def __contains__(self, key): 123 return key in self._PROPERTY_ 124 125 ## Set all internal used members of DscBuildData to None 126 def _Clear(self): 127 self._Header = None 128 self._PlatformName = None 129 self._Guid = None 130 self._Version = None 131 self._DscSpecification = None 132 self._OutputDirectory = None 133 self._SupArchList = None 134 self._BuildTargets = None 135 self._SkuName = None 136 self._SkuIdentifier = None 137 self._AvilableSkuIds = None 138 self._PcdInfoFlag = None 139 self._VarCheckFlag = None 140 self._FlashDefinition = None 141 self._Prebuild = None 142 self._Postbuild = None 143 self._BuildNumber = None 144 self._MakefileName = None 145 self._BsBaseAddress = None 146 self._RtBaseAddress = None 147 self._SkuIds = None 148 self._Modules = None 149 self._LibraryInstances = None 150 self._LibraryClasses = None 151 self._Pcds = None 152 self._DecPcds = None 153 self._BuildOptions = None 154 self._ModuleTypeOptions = None 155 self._LoadFixAddress = None 156 self._RFCLanguages = None 157 self._ISOLanguages = None 158 self._VpdToolGuid = None 159 self.__Macros = None 160 161 162 ## handle Override Path of Module 163 def _HandleOverridePath(self): 164 RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch] 165 Macros = self._Macros 166 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 167 for Record in RecordList: 168 ModuleId = Record[5] 169 LineNo = Record[6] 170 ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, Arch=self._Arch) 171 RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId] 172 if RecordList != []: 173 SourceOverridePath = mws.join(GlobalData.gWorkspace, NormPath(RecordList[0][0])) 174 175 # Check if the source override path exists 176 if not os.path.isdir(SourceOverridePath): 177 EdkLogger.error('build', FILE_NOT_FOUND, Message='Source override path does not exist:', File=self.MetaFile, ExtraData=SourceOverridePath, Line=LineNo) 178 179 #Add to GlobalData Variables 180 GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath 181 182 ## Get current effective macros 183 def _GetMacros(self): 184 if self.__Macros == None: 185 self.__Macros = {} 186 self.__Macros.update(GlobalData.gPlatformDefines) 187 self.__Macros.update(GlobalData.gGlobalDefines) 188 self.__Macros.update(GlobalData.gCommandLineDefines) 189 return self.__Macros 190 191 ## Get architecture 192 def _GetArch(self): 193 return self._Arch 194 195 ## Set architecture 196 # 197 # Changing the default ARCH to another may affect all other information 198 # because all information in a platform may be ARCH-related. That's 199 # why we need to clear all internal used members, in order to cause all 200 # information to be re-retrieved. 201 # 202 # @param Value The value of ARCH 203 # 204 def _SetArch(self, Value): 205 if self._Arch == Value: 206 return 207 self._Arch = Value 208 self._Clear() 209 210 ## Retrieve all information in [Defines] section 211 # 212 # (Retriving all [Defines] information in one-shot is just to save time.) 213 # 214 def _GetHeaderInfo(self): 215 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch] 216 for Record in RecordList: 217 Name = Record[1] 218 # items defined _PROPERTY_ don't need additional processing 219 220 # some special items in [Defines] section need special treatment 221 if Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY: 222 self._OutputDirectory = NormPath(Record[2], self._Macros) 223 if ' ' in self._OutputDirectory: 224 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY", 225 File=self.MetaFile, Line=Record[-1], 226 ExtraData=self._OutputDirectory) 227 elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION: 228 self._FlashDefinition = PathClass(NormPath(Record[2], self._Macros), GlobalData.gWorkspace) 229 ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf') 230 if ErrorCode != 0: 231 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1], 232 ExtraData=ErrorInfo) 233 elif Name == TAB_DSC_PREBUILD: 234 PrebuildValue = Record[2] 235 if Record[2][0] == '"': 236 if Record[2][-1] != '"': 237 EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD, 238 File=self.MetaFile, Line=Record[-1]) 239 PrebuildValue = Record[2][1:-1] 240 self._Prebuild = PathClass(NormPath(PrebuildValue, self._Macros), GlobalData.gWorkspace) 241 elif Name == TAB_DSC_POSTBUILD: 242 PostbuildValue = Record[2] 243 if Record[2][0] == '"': 244 if Record[2][-1] != '"': 245 EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD, 246 File=self.MetaFile, Line=Record[-1]) 247 PostbuildValue = Record[2][1:-1] 248 self._Postbuild = PathClass(NormPath(PostbuildValue, self._Macros), GlobalData.gWorkspace) 249 elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES: 250 self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT) 251 elif Name == TAB_DSC_DEFINES_BUILD_TARGETS: 252 self._BuildTargets = GetSplitValueList(Record[2]) 253 elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER: 254 if self._SkuName == None: 255 self._SkuName = Record[2] 256 self._SkuIdentifier = Record[2] 257 self._AvilableSkuIds = Record[2] 258 elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION: 259 self._PcdInfoFlag = Record[2] 260 elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION: 261 self._VarCheckFlag = Record[2] 262 elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS: 263 try: 264 self._LoadFixAddress = int (Record[2], 0) 265 except: 266 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (Record[2])) 267 elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES: 268 if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1: 269 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for RFC_LANGUAGES must have double quotes around it, for example: RFC_LANGUAGES = "en-us;zh-hans"', 270 File=self.MetaFile, Line=Record[-1]) 271 LanguageCodes = Record[2][1:-1] 272 if not LanguageCodes: 273 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement', 274 File=self.MetaFile, Line=Record[-1]) 275 LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT) 276 # check whether there is empty entries in the list 277 if None in LanguageList: 278 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement', 279 File=self.MetaFile, Line=Record[-1]) 280 self._RFCLanguages = LanguageList 281 elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES: 282 if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1: 283 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"', 284 File=self.MetaFile, Line=Record[-1]) 285 LanguageCodes = Record[2][1:-1] 286 if not LanguageCodes: 287 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement', 288 File=self.MetaFile, Line=Record[-1]) 289 if len(LanguageCodes)%3: 290 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES', 291 File=self.MetaFile, Line=Record[-1]) 292 LanguageList = [] 293 for i in range(0, len(LanguageCodes), 3): 294 LanguageList.append(LanguageCodes[i:i+3]) 295 self._ISOLanguages = LanguageList 296 elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID: 297 # 298 # try to convert GUID to a real UUID value to see whether the GUID is format 299 # for VPD_TOOL_GUID is correct. 300 # 301 try: 302 uuid.UUID(Record[2]) 303 except: 304 EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile) 305 self._VpdToolGuid = Record[2] 306 elif Name in self: 307 self[Name] = Record[2] 308 # set _Header to non-None in order to avoid database re-querying 309 self._Header = 'DUMMY' 310 311 ## Retrieve platform name 312 def _GetPlatformName(self): 313 if self._PlatformName == None: 314 if self._Header == None: 315 self._GetHeaderInfo() 316 if self._PlatformName == None: 317 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile) 318 return self._PlatformName 319 320 ## Retrieve file guid 321 def _GetFileGuid(self): 322 if self._Guid == None: 323 if self._Header == None: 324 self._GetHeaderInfo() 325 if self._Guid == None: 326 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_GUID", File=self.MetaFile) 327 return self._Guid 328 329 ## Retrieve platform version 330 def _GetVersion(self): 331 if self._Version == None: 332 if self._Header == None: 333 self._GetHeaderInfo() 334 if self._Version == None: 335 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_VERSION", File=self.MetaFile) 336 return self._Version 337 338 ## Retrieve platform description file version 339 def _GetDscSpec(self): 340 if self._DscSpecification == None: 341 if self._Header == None: 342 self._GetHeaderInfo() 343 if self._DscSpecification == None: 344 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No DSC_SPECIFICATION", File=self.MetaFile) 345 return self._DscSpecification 346 347 ## Retrieve OUTPUT_DIRECTORY 348 def _GetOutpuDir(self): 349 if self._OutputDirectory == None: 350 if self._Header == None: 351 self._GetHeaderInfo() 352 if self._OutputDirectory == None: 353 self._OutputDirectory = os.path.join("Build", self._PlatformName) 354 return self._OutputDirectory 355 356 ## Retrieve SUPPORTED_ARCHITECTURES 357 def _GetSupArch(self): 358 if self._SupArchList == None: 359 if self._Header == None: 360 self._GetHeaderInfo() 361 if self._SupArchList == None: 362 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No SUPPORTED_ARCHITECTURES", File=self.MetaFile) 363 return self._SupArchList 364 365 ## Retrieve BUILD_TARGETS 366 def _GetBuildTarget(self): 367 if self._BuildTargets == None: 368 if self._Header == None: 369 self._GetHeaderInfo() 370 if self._BuildTargets == None: 371 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile) 372 return self._BuildTargets 373 374 def _GetPcdInfoFlag(self): 375 if self._PcdInfoFlag == None or self._PcdInfoFlag.upper() == 'FALSE': 376 return False 377 elif self._PcdInfoFlag.upper() == 'TRUE': 378 return True 379 else: 380 return False 381 def _GetVarCheckFlag(self): 382 if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE': 383 return False 384 elif self._VarCheckFlag.upper() == 'TRUE': 385 return True 386 else: 387 return False 388 def _GetAviableSkuIds(self): 389 if self._AvilableSkuIds: 390 return self._AvilableSkuIds 391 return self.SkuIdentifier 392 def _GetSkuIdentifier(self): 393 if self._SkuName: 394 return self._SkuName 395 if self._SkuIdentifier == None: 396 if self._Header == None: 397 self._GetHeaderInfo() 398 return self._SkuIdentifier 399 ## Retrieve SKUID_IDENTIFIER 400 def _GetSkuName(self): 401 if self._SkuName == None: 402 if self._Header == None: 403 self._GetHeaderInfo() 404 if (self._SkuName == None or self._SkuName not in self.SkuIds): 405 self._SkuName = 'DEFAULT' 406 return self._SkuName 407 408 ## Override SKUID_IDENTIFIER 409 def _SetSkuName(self, Value): 410 self._SkuName = Value 411 self._Pcds = None 412 413 def _GetFdfFile(self): 414 if self._FlashDefinition == None: 415 if self._Header == None: 416 self._GetHeaderInfo() 417 if self._FlashDefinition == None: 418 self._FlashDefinition = '' 419 return self._FlashDefinition 420 421 def _GetPrebuild(self): 422 if self._Prebuild == None: 423 if self._Header == None: 424 self._GetHeaderInfo() 425 if self._Prebuild == None: 426 self._Prebuild = '' 427 return self._Prebuild 428 429 def _GetPostbuild(self): 430 if self._Postbuild == None: 431 if self._Header == None: 432 self._GetHeaderInfo() 433 if self._Postbuild == None: 434 self._Postbuild = '' 435 return self._Postbuild 436 437 ## Retrieve FLASH_DEFINITION 438 def _GetBuildNumber(self): 439 if self._BuildNumber == None: 440 if self._Header == None: 441 self._GetHeaderInfo() 442 if self._BuildNumber == None: 443 self._BuildNumber = '' 444 return self._BuildNumber 445 446 ## Retrieve MAKEFILE_NAME 447 def _GetMakefileName(self): 448 if self._MakefileName == None: 449 if self._Header == None: 450 self._GetHeaderInfo() 451 if self._MakefileName == None: 452 self._MakefileName = '' 453 return self._MakefileName 454 455 ## Retrieve BsBaseAddress 456 def _GetBsBaseAddress(self): 457 if self._BsBaseAddress == None: 458 if self._Header == None: 459 self._GetHeaderInfo() 460 if self._BsBaseAddress == None: 461 self._BsBaseAddress = '' 462 return self._BsBaseAddress 463 464 ## Retrieve RtBaseAddress 465 def _GetRtBaseAddress(self): 466 if self._RtBaseAddress == None: 467 if self._Header == None: 468 self._GetHeaderInfo() 469 if self._RtBaseAddress == None: 470 self._RtBaseAddress = '' 471 return self._RtBaseAddress 472 473 ## Retrieve the top address for the load fix address 474 def _GetLoadFixAddress(self): 475 if self._LoadFixAddress == None: 476 if self._Header == None: 477 self._GetHeaderInfo() 478 479 if self._LoadFixAddress == None: 480 self._LoadFixAddress = self._Macros.get(TAB_FIX_LOAD_TOP_MEMORY_ADDRESS, '0') 481 482 try: 483 self._LoadFixAddress = int (self._LoadFixAddress, 0) 484 except: 485 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (self._LoadFixAddress)) 486 487 # 488 # If command line defined, should override the value in DSC file. 489 # 490 if 'FIX_LOAD_TOP_MEMORY_ADDRESS' in GlobalData.gCommandLineDefines.keys(): 491 try: 492 self._LoadFixAddress = int(GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'], 0) 493 except: 494 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'])) 495 496 if self._LoadFixAddress < 0: 497 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid negative value 0x%x" % (self._LoadFixAddress)) 498 if self._LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self._LoadFixAddress % 0x1000 != 0: 499 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid unaligned 4K value 0x%x" % (self._LoadFixAddress)) 500 501 return self._LoadFixAddress 502 503 ## Retrieve RFCLanguage filter 504 def _GetRFCLanguages(self): 505 if self._RFCLanguages == None: 506 if self._Header == None: 507 self._GetHeaderInfo() 508 if self._RFCLanguages == None: 509 self._RFCLanguages = [] 510 return self._RFCLanguages 511 512 ## Retrieve ISOLanguage filter 513 def _GetISOLanguages(self): 514 if self._ISOLanguages == None: 515 if self._Header == None: 516 self._GetHeaderInfo() 517 if self._ISOLanguages == None: 518 self._ISOLanguages = [] 519 return self._ISOLanguages 520 ## Retrieve the GUID string for VPD tool 521 def _GetVpdToolGuid(self): 522 if self._VpdToolGuid == None: 523 if self._Header == None: 524 self._GetHeaderInfo() 525 if self._VpdToolGuid == None: 526 self._VpdToolGuid = '' 527 return self._VpdToolGuid 528 529 ## Retrieve [SkuIds] section information 530 def _GetSkuIds(self): 531 if self._SkuIds == None: 532 self._SkuIds = sdict() 533 RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch] 534 for Record in RecordList: 535 if Record[0] in [None, '']: 536 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number', 537 File=self.MetaFile, Line=Record[-1]) 538 if Record[1] in [None, '']: 539 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name', 540 File=self.MetaFile, Line=Record[-1]) 541 self._SkuIds[Record[1]] = Record[0] 542 if 'DEFAULT' not in self._SkuIds: 543 self._SkuIds['DEFAULT'] = '0' 544 if 'COMMON' not in self._SkuIds: 545 self._SkuIds['COMMON'] = '0' 546 return self._SkuIds 547 548 ## Retrieve [Components] section information 549 def _GetModules(self): 550 if self._Modules != None: 551 return self._Modules 552 553 self._Modules = sdict() 554 RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch] 555 Macros = self._Macros 556 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 557 for Record in RecordList: 558 DuplicatedFile = False 559 560 ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) 561 ModuleId = Record[5] 562 LineNo = Record[6] 563 564 # check the file validation 565 ErrorCode, ErrorInfo = ModuleFile.Validate('.inf') 566 if ErrorCode != 0: 567 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, 568 ExtraData=ErrorInfo) 569 # Check duplication 570 # If arch is COMMON, no duplicate module is checked since all modules in all component sections are selected 571 if self._Arch != 'COMMON' and ModuleFile in self._Modules: 572 DuplicatedFile = True 573 574 Module = ModuleBuildClassObject() 575 Module.MetaFile = ModuleFile 576 577 # get module private library instance 578 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId] 579 for Record in RecordList: 580 LibraryClass = Record[0] 581 LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch) 582 LineNo = Record[-1] 583 584 # check the file validation 585 ErrorCode, ErrorInfo = LibraryPath.Validate('.inf') 586 if ErrorCode != 0: 587 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, 588 ExtraData=ErrorInfo) 589 590 if LibraryClass == '' or LibraryClass == 'NULL': 591 self._NullLibraryNumber += 1 592 LibraryClass = 'NULL%d' % self._NullLibraryNumber 593 EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass)) 594 Module.LibraryClasses[LibraryClass] = LibraryPath 595 if LibraryPath not in self.LibraryInstances: 596 self.LibraryInstances.append(LibraryPath) 597 598 # get module private PCD setting 599 for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \ 600 MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]: 601 RecordList = self._RawData[Type, self._Arch, None, ModuleId] 602 for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: 603 TokenList = GetSplitValueList(Setting) 604 DefaultValue = TokenList[0] 605 if len(TokenList) > 1: 606 MaxDatumSize = TokenList[1] 607 else: 608 MaxDatumSize = '' 609 TypeString = self._PCD_TYPE_STRING_[Type] 610 Pcd = PcdClassObject( 611 PcdCName, 612 TokenSpaceGuid, 613 TypeString, 614 '', 615 DefaultValue, 616 '', 617 MaxDatumSize, 618 {}, 619 False, 620 None 621 ) 622 Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd 623 624 # get module private build options 625 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId] 626 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: 627 if (ToolChainFamily, ToolChain) not in Module.BuildOptions: 628 Module.BuildOptions[ToolChainFamily, ToolChain] = Option 629 else: 630 OptionString = Module.BuildOptions[ToolChainFamily, ToolChain] 631 Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option 632 633 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId] 634 if DuplicatedFile and not RecordList: 635 EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo) 636 if RecordList: 637 if len(RecordList) != 1: 638 EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.', 639 File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo) 640 ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace) 641 ModuleFile.Arch = self._Arch 642 643 self._Modules[ModuleFile] = Module 644 return self._Modules 645 646 ## Retrieve all possible library instances used in this platform 647 def _GetLibraryInstances(self): 648 if self._LibraryInstances == None: 649 self._GetLibraryClasses() 650 return self._LibraryInstances 651 652 ## Retrieve [LibraryClasses] information 653 def _GetLibraryClasses(self): 654 if self._LibraryClasses == None: 655 self._LibraryInstances = [] 656 # 657 # tdict is a special dict kind of type, used for selecting correct 658 # library instance for given library class and module type 659 # 660 LibraryClassDict = tdict(True, 3) 661 # track all library class names 662 LibraryClassSet = set() 663 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, -1] 664 Macros = self._Macros 665 for Record in RecordList: 666 LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, LineNo = Record 667 if LibraryClass == '' or LibraryClass == 'NULL': 668 self._NullLibraryNumber += 1 669 LibraryClass = 'NULL%d' % self._NullLibraryNumber 670 EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass)) 671 LibraryClassSet.add(LibraryClass) 672 LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch) 673 # check the file validation 674 ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf') 675 if ErrorCode != 0: 676 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, 677 ExtraData=ErrorInfo) 678 679 if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST: 680 EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType, 681 File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo) 682 LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance 683 if LibraryInstance not in self._LibraryInstances: 684 self._LibraryInstances.append(LibraryInstance) 685 686 # resolve the specific library instance for each class and each module type 687 self._LibraryClasses = tdict(True) 688 for LibraryClass in LibraryClassSet: 689 # try all possible module types 690 for ModuleType in SUP_MODULE_LIST: 691 LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass] 692 if LibraryInstance == None: 693 continue 694 self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance 695 696 # for Edk style library instances, which are listed in different section 697 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 698 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch] 699 for Record in RecordList: 700 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) 701 LineNo = Record[-1] 702 # check the file validation 703 ErrorCode, ErrorInfo = File.Validate('.inf') 704 if ErrorCode != 0: 705 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo, 706 ExtraData=ErrorInfo) 707 if File not in self._LibraryInstances: 708 self._LibraryInstances.append(File) 709 # 710 # we need the module name as the library class name, so we have 711 # to parse it here. (self._Bdb[] will trigger a file parse if it 712 # hasn't been parsed) 713 # 714 Library = self._Bdb[File, self._Arch, self._Target, self._Toolchain] 715 self._LibraryClasses[Library.BaseName, ':dummy:'] = Library 716 return self._LibraryClasses 717 718 def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo): 719 if self._DecPcds == None: 720 self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain) 721 FdfInfList = [] 722 if GlobalData.gFdfParser: 723 FdfInfList = GlobalData.gFdfParser.Profile.InfList 724 725 PkgSet = set() 726 for Inf in FdfInfList: 727 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch) 728 if ModuleFile in self._Modules: 729 continue 730 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain] 731 PkgSet.update(ModuleData.Packages) 732 DecPcds = {} 733 for Pkg in PkgSet: 734 for Pcd in Pkg.Pcds: 735 DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd] 736 self._DecPcds.update(DecPcds) 737 738 if (PcdCName, TokenSpaceGuid) not in self._DecPcds: 739 EdkLogger.error('build', PARSER_ERROR, 740 "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch), 741 File=self.MetaFile, Line=LineNo) 742 ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType) 743 if not IsValid and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]: 744 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo, 745 ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting)) 746 if ValueList[Index] and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]: 747 try: 748 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True) 749 except WrnExpression, Value: 750 ValueList[Index] = Value.result 751 except EvaluationException, Excpt: 752 if hasattr(Excpt, 'Pcd'): 753 if Excpt.Pcd in GlobalData.gPlatformOtherPcds: 754 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as" 755 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section" 756 " of the DSC file" % Excpt.Pcd, 757 File=self.MetaFile, Line=LineNo) 758 else: 759 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd, 760 File=self.MetaFile, Line=LineNo) 761 else: 762 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt), 763 File=self.MetaFile, Line=LineNo) 764 if ValueList[Index] == 'True': 765 ValueList[Index] = '1' 766 elif ValueList[Index] == 'False': 767 ValueList[Index] = '0' 768 if ValueList[Index]: 769 Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index]) 770 if not Valid: 771 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo, 772 ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName)) 773 return ValueList 774 775 ## Retrieve all PCD settings in platform 776 def _GetPcds(self): 777 if self._Pcds == None: 778 self._Pcds = sdict() 779 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD)) 780 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE)) 781 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG)) 782 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT)) 783 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII)) 784 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD)) 785 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT)) 786 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII)) 787 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD)) 788 return self._Pcds 789 790 ## Retrieve [BuildOptions] 791 def _GetBuildOptions(self): 792 if self._BuildOptions == None: 793 self._BuildOptions = sdict() 794 # 795 # Retrieve build option for EDKII and EDK style module 796 # 797 for CodeBase in (EDKII_NAME, EDK_NAME): 798 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase] 799 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList: 800 CurKey = (ToolChainFamily, ToolChain, CodeBase) 801 # 802 # Only flags can be appended 803 # 804 if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='): 805 self._BuildOptions[CurKey] = Option 806 else: 807 self._BuildOptions[CurKey] += ' ' + Option 808 return self._BuildOptions 809 810 def GetBuildOptionsByModuleType(self, Edk, ModuleType): 811 if self._ModuleTypeOptions == None: 812 self._ModuleTypeOptions = sdict() 813 if (Edk, ModuleType) not in self._ModuleTypeOptions: 814 options = sdict() 815 self._ModuleTypeOptions[Edk, ModuleType] = options 816 DriverType = '%s.%s' % (Edk, ModuleType) 817 CommonDriverType = '%s.%s' % ('COMMON', ModuleType) 818 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, DriverType] 819 for ToolChainFamily, ToolChain, Option, Arch, Type, Dummy3, Dummy4 in RecordList: 820 if Type == DriverType or Type == CommonDriverType: 821 Key = (ToolChainFamily, ToolChain, Edk) 822 if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='): 823 options[Key] = Option 824 else: 825 options[Key] += ' ' + Option 826 return self._ModuleTypeOptions[Edk, ModuleType] 827 828 ## Retrieve non-dynamic PCD settings 829 # 830 # @param Type PCD type 831 # 832 # @retval a dict object contains settings of given PCD type 833 # 834 def _GetPcd(self, Type): 835 Pcds = sdict() 836 # 837 # tdict is a special dict kind of type, used for selecting correct 838 # PCD settings for certain ARCH 839 # 840 841 SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds) 842 843 PcdDict = tdict(True, 3) 844 PcdSet = set() 845 # Find out all possible PCD candidates for self._Arch 846 RecordList = self._RawData[Type, self._Arch] 847 PcdValueDict = sdict() 848 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: 849 if SkuName in (SkuObj.SystemSkuId,'DEFAULT','COMMON'): 850 PcdSet.add((PcdCName, TokenSpaceGuid, SkuName,Dummy4)) 851 PcdDict[Arch, PcdCName, TokenSpaceGuid,SkuName] = Setting 852 853 #handle pcd value override 854 for PcdCName, TokenSpaceGuid, SkuName,Dummy4 in PcdSet: 855 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid,SkuName] 856 if Setting == None: 857 continue 858 PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4) 859 if (PcdCName, TokenSpaceGuid) in PcdValueDict: 860 PcdValueDict[PcdCName, TokenSpaceGuid][SkuName] = (PcdValue,DatumType,MaxDatumSize) 861 else: 862 PcdValueDict[PcdCName, TokenSpaceGuid] = {SkuName:(PcdValue,DatumType,MaxDatumSize)} 863 864 PcdsKeys = PcdValueDict.keys() 865 for PcdCName,TokenSpaceGuid in PcdsKeys: 866 867 PcdSetting = PcdValueDict[PcdCName, TokenSpaceGuid] 868 PcdValue = None 869 DatumType = None 870 MaxDatumSize = None 871 if 'COMMON' in PcdSetting: 872 PcdValue,DatumType,MaxDatumSize = PcdSetting['COMMON'] 873 if 'DEFAULT' in PcdSetting: 874 PcdValue,DatumType,MaxDatumSize = PcdSetting['DEFAULT'] 875 if SkuObj.SystemSkuId in PcdSetting: 876 PcdValue,DatumType,MaxDatumSize = PcdSetting[SkuObj.SystemSkuId] 877 878 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( 879 PcdCName, 880 TokenSpaceGuid, 881 self._PCD_TYPE_STRING_[Type], 882 DatumType, 883 PcdValue, 884 '', 885 MaxDatumSize, 886 {}, 887 False, 888 None 889 ) 890 return Pcds 891 892 ## Retrieve dynamic PCD settings 893 # 894 # @param Type PCD type 895 # 896 # @retval a dict object contains settings of given PCD type 897 # 898 def _GetDynamicPcd(self, Type): 899 900 SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds) 901 902 Pcds = sdict() 903 # 904 # tdict is a special dict kind of type, used for selecting correct 905 # PCD settings for certain ARCH and SKU 906 # 907 PcdDict = tdict(True, 4) 908 PcdList = [] 909 # Find out all possible PCD candidates for self._Arch 910 RecordList = self._RawData[Type, self._Arch] 911 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy() 912 913 AvailableSkuIdSet.update({'DEFAULT':0,'COMMON':0}) 914 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: 915 if SkuName not in AvailableSkuIdSet: 916 continue 917 918 PcdList.append((PcdCName, TokenSpaceGuid, SkuName,Dummy4)) 919 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting 920 # Remove redundant PCD candidates, per the ARCH and SKU 921 for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList: 922 923 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid] 924 if Setting == None: 925 continue 926 927 PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4) 928 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], '', '', '', '', '', PcdValue) 929 if (PcdCName,TokenSpaceGuid) in Pcds.keys(): 930 pcdObject = Pcds[PcdCName,TokenSpaceGuid] 931 pcdObject.SkuInfoList[SkuName] = SkuInfo 932 if MaxDatumSize.strip(): 933 CurrentMaxSize = int(MaxDatumSize.strip(),0) 934 else: 935 CurrentMaxSize = 0 936 if pcdObject.MaxDatumSize: 937 PcdMaxSize = int(pcdObject.MaxDatumSize,0) 938 else: 939 PcdMaxSize = 0 940 if CurrentMaxSize > PcdMaxSize: 941 pcdObject.MaxDatumSize = str(CurrentMaxSize) 942 else: 943 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( 944 PcdCName, 945 TokenSpaceGuid, 946 self._PCD_TYPE_STRING_[Type], 947 DatumType, 948 PcdValue, 949 '', 950 MaxDatumSize, 951 {SkuName : SkuInfo}, 952 False, 953 None 954 ) 955 956 for pcd in Pcds.values(): 957 pcdDecObject = self._DecPcds[pcd.TokenCName,pcd.TokenSpaceGuidCName] 958 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys(): 959 valuefromDec = pcdDecObject.DefaultValue 960 SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', '', valuefromDec) 961 pcd.SkuInfoList['DEFAULT'] = SkuInfo 962 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys(): 963 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON'] 964 del(pcd.SkuInfoList['COMMON']) 965 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys(): 966 del(pcd.SkuInfoList['COMMON']) 967 if SkuObj.SkuUsageType == SkuObj.SINGLE: 968 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys(): 969 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT'] 970 del(pcd.SkuInfoList['DEFAULT']) 971 972 return Pcds 973 974 def CompareVarAttr(self, Attr1, Attr2): 975 if not Attr1 or not Attr2: # for empty string 976 return True 977 Attr1s = [attr.strip() for attr in Attr1.split(",")] 978 Attr1Set = set(Attr1s) 979 Attr2s = [attr.strip() for attr in Attr2.split(",")] 980 Attr2Set = set(Attr2s) 981 if Attr2Set == Attr1Set: 982 return True 983 else: 984 return False 985 ## Retrieve dynamic HII PCD settings 986 # 987 # @param Type PCD type 988 # 989 # @retval a dict object contains settings of given PCD type 990 # 991 def _GetDynamicHiiPcd(self, Type): 992 993 SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds) 994 VariableAttrs = {} 995 996 Pcds = sdict() 997 # 998 # tdict is a special dict kind of type, used for selecting correct 999 # PCD settings for certain ARCH and SKU 1000 # 1001 PcdDict = tdict(True, 4) 1002 PcdSet = set() 1003 RecordList = self._RawData[Type, self._Arch] 1004 # Find out all possible PCD candidates for self._Arch 1005 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy() 1006 1007 AvailableSkuIdSet.update({'DEFAULT':0,'COMMON':0}) 1008 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: 1009 if SkuName not in AvailableSkuIdSet: 1010 continue 1011 PcdSet.add((PcdCName, TokenSpaceGuid, SkuName,Dummy4)) 1012 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting 1013 # Remove redundant PCD candidates, per the ARCH and SKU 1014 for PcdCName, TokenSpaceGuid,SkuName, Dummy4 in PcdSet: 1015 1016 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid] 1017 if Setting == None: 1018 continue 1019 VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4) 1020 1021 rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute) 1022 if not rt: 1023 EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg), 1024 ExtraData = "[%s]" % VarAttribute) 1025 ExceedMax = False 1026 FormatCorrect = True 1027 if VariableOffset.isdigit(): 1028 if int(VariableOffset,10) > 0xFFFF: 1029 ExceedMax = True 1030 elif re.match(r'[\t\s]*0[xX][a-fA-F0-9]+$',VariableOffset): 1031 if int(VariableOffset,16) > 0xFFFF: 1032 ExceedMax = True 1033 # For Offset written in "A.B" 1034 elif VariableOffset.find('.') > -1: 1035 VariableOffsetList = VariableOffset.split(".") 1036 if not (len(VariableOffsetList) == 2 1037 and IsValidWord(VariableOffsetList[0]) 1038 and IsValidWord(VariableOffsetList[1])): 1039 FormatCorrect = False 1040 else: 1041 FormatCorrect = False 1042 if not FormatCorrect: 1043 EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid,PcdCName))) 1044 1045 if ExceedMax: 1046 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid,PcdCName))) 1047 if (VariableName, VariableGuid) not in VariableAttrs: 1048 VariableAttrs[(VariableName, VariableGuid)] = VarAttribute 1049 else: 1050 if not self.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute): 1051 EdkLogger.error('Build', PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR, "The variable %s.%s for DynamicHii PCDs has conflicting attributes [%s] and [%s] " % (VariableGuid, VariableName, VarAttribute, VariableAttrs[(VariableName, VariableGuid)])) 1052 1053 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute = VarAttribute) 1054 pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid] 1055 if (PcdCName,TokenSpaceGuid) in Pcds.keys(): 1056 pcdObject = Pcds[PcdCName,TokenSpaceGuid] 1057 pcdObject.SkuInfoList[SkuName] = SkuInfo 1058 else: 1059 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( 1060 PcdCName, 1061 TokenSpaceGuid, 1062 self._PCD_TYPE_STRING_[Type], 1063 '', 1064 DefaultValue, 1065 '', 1066 '', 1067 {SkuName : SkuInfo}, 1068 False, 1069 None, 1070 pcdDecObject.validateranges, 1071 pcdDecObject.validlists, 1072 pcdDecObject.expressions 1073 ) 1074 1075 1076 for pcd in Pcds.values(): 1077 SkuInfoObj = pcd.SkuInfoList.values()[0] 1078 pcdDecObject = self._DecPcds[pcd.TokenCName,pcd.TokenSpaceGuidCName] 1079 # Only fix the value while no value provided in DSC file. 1080 for sku in pcd.SkuInfoList.values(): 1081 if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue==None): 1082 sku.HiiDefaultValue = pcdDecObject.DefaultValue 1083 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys(): 1084 valuefromDec = pcdDecObject.DefaultValue 1085 SkuInfo = SkuInfoClass('DEFAULT', '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec) 1086 pcd.SkuInfoList['DEFAULT'] = SkuInfo 1087 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys(): 1088 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON'] 1089 del(pcd.SkuInfoList['COMMON']) 1090 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys(): 1091 del(pcd.SkuInfoList['COMMON']) 1092 1093 if SkuObj.SkuUsageType == SkuObj.SINGLE: 1094 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys(): 1095 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT'] 1096 del(pcd.SkuInfoList['DEFAULT']) 1097 1098 1099 if pcd.MaxDatumSize.strip(): 1100 MaxSize = int(pcd.MaxDatumSize,0) 1101 else: 1102 MaxSize = 0 1103 if pcdDecObject.DatumType == 'VOID*': 1104 for (skuname,skuobj) in pcd.SkuInfoList.items(): 1105 datalen = 0 1106 if skuobj.HiiDefaultValue.startswith("L"): 1107 datalen = (len(skuobj.HiiDefaultValue)- 3 + 1) * 2 1108 elif skuobj.HiiDefaultValue.startswith("{"): 1109 datalen = len(skuobj.HiiDefaultValue.split(",")) 1110 else: 1111 datalen = len(skuobj.HiiDefaultValue) -2 + 1 1112 if datalen>MaxSize: 1113 MaxSize = datalen 1114 pcd.MaxDatumSize = str(MaxSize) 1115 return Pcds 1116 1117 ## Retrieve dynamic VPD PCD settings 1118 # 1119 # @param Type PCD type 1120 # 1121 # @retval a dict object contains settings of given PCD type 1122 # 1123 def _GetDynamicVpdPcd(self, Type): 1124 1125 SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds) 1126 1127 Pcds = sdict() 1128 # 1129 # tdict is a special dict kind of type, used for selecting correct 1130 # PCD settings for certain ARCH and SKU 1131 # 1132 PcdDict = tdict(True, 4) 1133 PcdList = [] 1134 # Find out all possible PCD candidates for self._Arch 1135 RecordList = self._RawData[Type, self._Arch] 1136 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy() 1137 1138 AvailableSkuIdSet.update({'DEFAULT':0,'COMMON':0}) 1139 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList: 1140 if SkuName not in AvailableSkuIdSet: 1141 continue 1142 1143 PcdList.append((PcdCName, TokenSpaceGuid,SkuName, Dummy4)) 1144 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting 1145 # Remove redundant PCD candidates, per the ARCH and SKU 1146 for PcdCName, TokenSpaceGuid, SkuName,Dummy4 in PcdList: 1147 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid] 1148 if Setting == None: 1149 continue 1150 # 1151 # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue 1152 # For the Integer & Boolean type, the optional data can only be InitialValue. 1153 # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype 1154 # until the DEC parser has been called. 1155 # 1156 VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4) 1157 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], '', '', '', '', VpdOffset, InitialValue) 1158 if (PcdCName,TokenSpaceGuid) in Pcds.keys(): 1159 pcdObject = Pcds[PcdCName,TokenSpaceGuid] 1160 pcdObject.SkuInfoList[SkuName] = SkuInfo 1161 if MaxDatumSize.strip(): 1162 CurrentMaxSize = int(MaxDatumSize.strip(),0) 1163 else: 1164 CurrentMaxSize = 0 1165 if pcdObject.MaxDatumSize: 1166 PcdMaxSize = int(pcdObject.MaxDatumSize,0) 1167 else: 1168 PcdMaxSize = 0 1169 if CurrentMaxSize > PcdMaxSize: 1170 pcdObject.MaxDatumSize = str(CurrentMaxSize) 1171 else: 1172 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject( 1173 PcdCName, 1174 TokenSpaceGuid, 1175 self._PCD_TYPE_STRING_[Type], 1176 '', 1177 InitialValue, 1178 '', 1179 MaxDatumSize, 1180 {SkuName : SkuInfo}, 1181 False, 1182 None 1183 ) 1184 for pcd in Pcds.values(): 1185 SkuInfoObj = pcd.SkuInfoList.values()[0] 1186 pcdDecObject = self._DecPcds[pcd.TokenCName,pcd.TokenSpaceGuidCName] 1187 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys(): 1188 valuefromDec = pcdDecObject.DefaultValue 1189 SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '','',SkuInfoObj.VpdOffset, valuefromDec) 1190 pcd.SkuInfoList['DEFAULT'] = SkuInfo 1191 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys(): 1192 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON'] 1193 del(pcd.SkuInfoList['COMMON']) 1194 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys(): 1195 del(pcd.SkuInfoList['COMMON']) 1196 if SkuObj.SkuUsageType == SkuObj.SINGLE: 1197 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys(): 1198 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT'] 1199 del(pcd.SkuInfoList['DEFAULT']) 1200 1201 return Pcds 1202 1203 ## Add external modules 1204 # 1205 # The external modules are mostly those listed in FDF file, which don't 1206 # need "build". 1207 # 1208 # @param FilePath The path of module description file 1209 # 1210 def AddModule(self, FilePath): 1211 FilePath = NormPath(FilePath) 1212 if FilePath not in self.Modules: 1213 Module = ModuleBuildClassObject() 1214 Module.MetaFile = FilePath 1215 self.Modules.append(Module) 1216 1217 ## Add external PCDs 1218 # 1219 # The external PCDs are mostly those listed in FDF file to specify address 1220 # or offset information. 1221 # 1222 # @param Name Name of the PCD 1223 # @param Guid Token space guid of the PCD 1224 # @param Value Value of the PCD 1225 # 1226 def AddPcd(self, Name, Guid, Value): 1227 if (Name, Guid) not in self.Pcds: 1228 self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None) 1229 self.Pcds[Name, Guid].DefaultValue = Value 1230 1231 _Macros = property(_GetMacros) 1232 Arch = property(_GetArch, _SetArch) 1233 Platform = property(_GetPlatformName) 1234 PlatformName = property(_GetPlatformName) 1235 Guid = property(_GetFileGuid) 1236 Version = property(_GetVersion) 1237 DscSpecification = property(_GetDscSpec) 1238 OutputDirectory = property(_GetOutpuDir) 1239 SupArchList = property(_GetSupArch) 1240 BuildTargets = property(_GetBuildTarget) 1241 SkuName = property(_GetSkuName, _SetSkuName) 1242 SkuIdentifier = property(_GetSkuIdentifier) 1243 AvilableSkuIds = property(_GetAviableSkuIds) 1244 PcdInfoFlag = property(_GetPcdInfoFlag) 1245 VarCheckFlag = property(_GetVarCheckFlag) 1246 FlashDefinition = property(_GetFdfFile) 1247 Prebuild = property(_GetPrebuild) 1248 Postbuild = property(_GetPostbuild) 1249 BuildNumber = property(_GetBuildNumber) 1250 MakefileName = property(_GetMakefileName) 1251 BsBaseAddress = property(_GetBsBaseAddress) 1252 RtBaseAddress = property(_GetRtBaseAddress) 1253 LoadFixAddress = property(_GetLoadFixAddress) 1254 RFCLanguages = property(_GetRFCLanguages) 1255 ISOLanguages = property(_GetISOLanguages) 1256 VpdToolGuid = property(_GetVpdToolGuid) 1257 SkuIds = property(_GetSkuIds) 1258 Modules = property(_GetModules) 1259 LibraryInstances = property(_GetLibraryInstances) 1260 LibraryClasses = property(_GetLibraryClasses) 1261 Pcds = property(_GetPcds) 1262 BuildOptions = property(_GetBuildOptions) 1263 1264 ## Platform build information from DEC file 1265 # 1266 # This class is used to retrieve information stored in database and convert them 1267 # into PackageBuildClassObject form for easier use for AutoGen. 1268 # 1269 class DecBuildData(PackageBuildClassObject): 1270 # dict used to convert PCD type in database to string used by build tool 1271 _PCD_TYPE_STRING_ = { 1272 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild", 1273 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule", 1274 MODEL_PCD_FEATURE_FLAG : "FeatureFlag", 1275 MODEL_PCD_DYNAMIC : "Dynamic", 1276 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic", 1277 MODEL_PCD_DYNAMIC_HII : "DynamicHii", 1278 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd", 1279 MODEL_PCD_DYNAMIC_EX : "DynamicEx", 1280 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx", 1281 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii", 1282 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd", 1283 } 1284 1285 # dict used to convert part of [Defines] to members of DecBuildData directly 1286 _PROPERTY_ = { 1287 # 1288 # Required Fields 1289 # 1290 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName", 1291 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid", 1292 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version", 1293 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile", 1294 } 1295 1296 1297 ## Constructor of DecBuildData 1298 # 1299 # Initialize object of DecBuildData 1300 # 1301 # @param FilePath The path of package description file 1302 # @param RawData The raw data of DEC file 1303 # @param BuildDataBase Database used to retrieve module information 1304 # @param Arch The target architecture 1305 # @param Platform (not used for DecBuildData) 1306 # @param Macros Macros used for replacement in DSC file 1307 # 1308 def __init__(self, File, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None): 1309 self.MetaFile = File 1310 self._PackageDir = File.Dir 1311 self._RawData = RawData 1312 self._Bdb = BuildDataBase 1313 self._Arch = Arch 1314 self._Target = Target 1315 self._Toolchain = Toolchain 1316 self._Clear() 1317 1318 ## XXX[key] = value 1319 def __setitem__(self, key, value): 1320 self.__dict__[self._PROPERTY_[key]] = value 1321 1322 ## value = XXX[key] 1323 def __getitem__(self, key): 1324 return self.__dict__[self._PROPERTY_[key]] 1325 1326 ## "in" test support 1327 def __contains__(self, key): 1328 return key in self._PROPERTY_ 1329 1330 ## Set all internal used members of DecBuildData to None 1331 def _Clear(self): 1332 self._Header = None 1333 self._PackageName = None 1334 self._Guid = None 1335 self._Version = None 1336 self._PkgUniFile = None 1337 self._Protocols = None 1338 self._Ppis = None 1339 self._Guids = None 1340 self._Includes = None 1341 self._LibraryClasses = None 1342 self._Pcds = None 1343 self.__Macros = None 1344 self._PrivateProtocols = None 1345 self._PrivatePpis = None 1346 self._PrivateGuids = None 1347 self._PrivateIncludes = None 1348 1349 ## Get current effective macros 1350 def _GetMacros(self): 1351 if self.__Macros == None: 1352 self.__Macros = {} 1353 self.__Macros.update(GlobalData.gGlobalDefines) 1354 return self.__Macros 1355 1356 ## Get architecture 1357 def _GetArch(self): 1358 return self._Arch 1359 1360 ## Set architecture 1361 # 1362 # Changing the default ARCH to another may affect all other information 1363 # because all information in a platform may be ARCH-related. That's 1364 # why we need to clear all internal used members, in order to cause all 1365 # information to be re-retrieved. 1366 # 1367 # @param Value The value of ARCH 1368 # 1369 def _SetArch(self, Value): 1370 if self._Arch == Value: 1371 return 1372 self._Arch = Value 1373 self._Clear() 1374 1375 ## Retrieve all information in [Defines] section 1376 # 1377 # (Retriving all [Defines] information in one-shot is just to save time.) 1378 # 1379 def _GetHeaderInfo(self): 1380 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch] 1381 for Record in RecordList: 1382 Name = Record[1] 1383 if Name in self: 1384 self[Name] = Record[2] 1385 self._Header = 'DUMMY' 1386 1387 ## Retrieve package name 1388 def _GetPackageName(self): 1389 if self._PackageName == None: 1390 if self._Header == None: 1391 self._GetHeaderInfo() 1392 if self._PackageName == None: 1393 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile) 1394 return self._PackageName 1395 1396 ## Retrieve file guid 1397 def _GetFileGuid(self): 1398 if self._Guid == None: 1399 if self._Header == None: 1400 self._GetHeaderInfo() 1401 if self._Guid == None: 1402 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile) 1403 return self._Guid 1404 1405 ## Retrieve package version 1406 def _GetVersion(self): 1407 if self._Version == None: 1408 if self._Header == None: 1409 self._GetHeaderInfo() 1410 if self._Version == None: 1411 self._Version = '' 1412 return self._Version 1413 1414 ## Retrieve protocol definitions (name/value pairs) 1415 def _GetProtocol(self): 1416 if self._Protocols == None: 1417 # 1418 # tdict is a special kind of dict, used for selecting correct 1419 # protocol defition for given ARCH 1420 # 1421 ProtocolDict = tdict(True) 1422 PrivateProtocolDict = tdict(True) 1423 NameList = [] 1424 PrivateNameList = [] 1425 PublicNameList = [] 1426 # find out all protocol definitions for specific and 'common' arch 1427 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch] 1428 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList: 1429 if PrivateFlag == 'PRIVATE': 1430 if Name not in PrivateNameList: 1431 PrivateNameList.append(Name) 1432 PrivateProtocolDict[Arch, Name] = Guid 1433 if Name in PublicNameList: 1434 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo) 1435 else: 1436 if Name not in PublicNameList: 1437 PublicNameList.append(Name) 1438 if Name in PrivateNameList: 1439 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo) 1440 if Name not in NameList: 1441 NameList.append(Name) 1442 ProtocolDict[Arch, Name] = Guid 1443 # use sdict to keep the order 1444 self._Protocols = sdict() 1445 self._PrivateProtocols = sdict() 1446 for Name in NameList: 1447 # 1448 # limit the ARCH to self._Arch, if no self._Arch found, tdict 1449 # will automatically turn to 'common' ARCH for trying 1450 # 1451 self._Protocols[Name] = ProtocolDict[self._Arch, Name] 1452 for Name in PrivateNameList: 1453 self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name] 1454 return self._Protocols 1455 1456 ## Retrieve PPI definitions (name/value pairs) 1457 def _GetPpi(self): 1458 if self._Ppis == None: 1459 # 1460 # tdict is a special kind of dict, used for selecting correct 1461 # PPI defition for given ARCH 1462 # 1463 PpiDict = tdict(True) 1464 PrivatePpiDict = tdict(True) 1465 NameList = [] 1466 PrivateNameList = [] 1467 PublicNameList = [] 1468 # find out all PPI definitions for specific arch and 'common' arch 1469 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch] 1470 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList: 1471 if PrivateFlag == 'PRIVATE': 1472 if Name not in PrivateNameList: 1473 PrivateNameList.append(Name) 1474 PrivatePpiDict[Arch, Name] = Guid 1475 if Name in PublicNameList: 1476 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo) 1477 else: 1478 if Name not in PublicNameList: 1479 PublicNameList.append(Name) 1480 if Name in PrivateNameList: 1481 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo) 1482 if Name not in NameList: 1483 NameList.append(Name) 1484 PpiDict[Arch, Name] = Guid 1485 # use sdict to keep the order 1486 self._Ppis = sdict() 1487 self._PrivatePpis = sdict() 1488 for Name in NameList: 1489 # 1490 # limit the ARCH to self._Arch, if no self._Arch found, tdict 1491 # will automatically turn to 'common' ARCH for trying 1492 # 1493 self._Ppis[Name] = PpiDict[self._Arch, Name] 1494 for Name in PrivateNameList: 1495 self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name] 1496 return self._Ppis 1497 1498 ## Retrieve GUID definitions (name/value pairs) 1499 def _GetGuid(self): 1500 if self._Guids == None: 1501 # 1502 # tdict is a special kind of dict, used for selecting correct 1503 # GUID defition for given ARCH 1504 # 1505 GuidDict = tdict(True) 1506 PrivateGuidDict = tdict(True) 1507 NameList = [] 1508 PrivateNameList = [] 1509 PublicNameList = [] 1510 # find out all protocol definitions for specific and 'common' arch 1511 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch] 1512 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList: 1513 if PrivateFlag == 'PRIVATE': 1514 if Name not in PrivateNameList: 1515 PrivateNameList.append(Name) 1516 PrivateGuidDict[Arch, Name] = Guid 1517 if Name in PublicNameList: 1518 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo) 1519 else: 1520 if Name not in PublicNameList: 1521 PublicNameList.append(Name) 1522 if Name in PrivateNameList: 1523 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo) 1524 if Name not in NameList: 1525 NameList.append(Name) 1526 GuidDict[Arch, Name] = Guid 1527 # use sdict to keep the order 1528 self._Guids = sdict() 1529 self._PrivateGuids = sdict() 1530 for Name in NameList: 1531 # 1532 # limit the ARCH to self._Arch, if no self._Arch found, tdict 1533 # will automatically turn to 'common' ARCH for trying 1534 # 1535 self._Guids[Name] = GuidDict[self._Arch, Name] 1536 for Name in PrivateNameList: 1537 self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name] 1538 return self._Guids 1539 1540 ## Retrieve public include paths declared in this package 1541 def _GetInclude(self): 1542 if self._Includes == None: 1543 self._Includes = [] 1544 self._PrivateIncludes = [] 1545 PublicInclues = [] 1546 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch] 1547 Macros = self._Macros 1548 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 1549 for Record in RecordList: 1550 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch) 1551 LineNo = Record[-1] 1552 # validate the path 1553 ErrorCode, ErrorInfo = File.Validate() 1554 if ErrorCode != 0: 1555 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) 1556 1557 # avoid duplicate include path 1558 if File not in self._Includes: 1559 self._Includes.append(File) 1560 if Record[4] == 'PRIVATE': 1561 if File not in self._PrivateIncludes: 1562 self._PrivateIncludes.append(File) 1563 if File in PublicInclues: 1564 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo) 1565 else: 1566 if File not in PublicInclues: 1567 PublicInclues.append(File) 1568 if File in self._PrivateIncludes: 1569 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo) 1570 1571 return self._Includes 1572 1573 ## Retrieve library class declarations (not used in build at present) 1574 def _GetLibraryClass(self): 1575 if self._LibraryClasses == None: 1576 # 1577 # tdict is a special kind of dict, used for selecting correct 1578 # library class declaration for given ARCH 1579 # 1580 LibraryClassDict = tdict(True) 1581 LibraryClassSet = set() 1582 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch] 1583 Macros = self._Macros 1584 for LibraryClass, File, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList: 1585 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch) 1586 # check the file validation 1587 ErrorCode, ErrorInfo = File.Validate() 1588 if ErrorCode != 0: 1589 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) 1590 LibraryClassSet.add(LibraryClass) 1591 LibraryClassDict[Arch, LibraryClass] = File 1592 self._LibraryClasses = sdict() 1593 for LibraryClass in LibraryClassSet: 1594 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass] 1595 return self._LibraryClasses 1596 1597 ## Retrieve PCD declarations 1598 def _GetPcds(self): 1599 if self._Pcds == None: 1600 self._Pcds = sdict() 1601 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD)) 1602 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE)) 1603 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG)) 1604 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC)) 1605 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX)) 1606 return self._Pcds 1607 1608 ## Retrieve PCD declarations for given type 1609 def _GetPcd(self, Type): 1610 Pcds = sdict() 1611 # 1612 # tdict is a special kind of dict, used for selecting correct 1613 # PCD declaration for given ARCH 1614 # 1615 PcdDict = tdict(True, 3) 1616 # for summarizing PCD 1617 PcdSet = set() 1618 # find out all PCDs of the 'type' 1619 RecordList = self._RawData[Type, self._Arch] 1620 for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList: 1621 PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting 1622 PcdSet.add((PcdCName, TokenSpaceGuid)) 1623 1624 for PcdCName, TokenSpaceGuid in PcdSet: 1625 # 1626 # limit the ARCH to self._Arch, if no self._Arch found, tdict 1627 # will automatically turn to 'common' ARCH and try again 1628 # 1629 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid] 1630 if Setting == None: 1631 continue 1632 1633 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting) 1634 1635 validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName) 1636 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject( 1637 PcdCName, 1638 TokenSpaceGuid, 1639 self._PCD_TYPE_STRING_[Type], 1640 DatumType, 1641 DefaultValue, 1642 TokenNumber, 1643 '', 1644 {}, 1645 False, 1646 None, 1647 list(validateranges), 1648 list(validlists), 1649 list(expressions) 1650 ) 1651 return Pcds 1652 1653 1654 _Macros = property(_GetMacros) 1655 Arch = property(_GetArch, _SetArch) 1656 PackageName = property(_GetPackageName) 1657 Guid = property(_GetFileGuid) 1658 Version = property(_GetVersion) 1659 1660 Protocols = property(_GetProtocol) 1661 Ppis = property(_GetPpi) 1662 Guids = property(_GetGuid) 1663 Includes = property(_GetInclude) 1664 LibraryClasses = property(_GetLibraryClass) 1665 Pcds = property(_GetPcds) 1666 1667 ## Module build information from INF file 1668 # 1669 # This class is used to retrieve information stored in database and convert them 1670 # into ModuleBuildClassObject form for easier use for AutoGen. 1671 # 1672 class InfBuildData(ModuleBuildClassObject): 1673 # dict used to convert PCD type in database to string used by build tool 1674 _PCD_TYPE_STRING_ = { 1675 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild", 1676 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule", 1677 MODEL_PCD_FEATURE_FLAG : "FeatureFlag", 1678 MODEL_PCD_DYNAMIC : "Dynamic", 1679 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic", 1680 MODEL_PCD_DYNAMIC_HII : "DynamicHii", 1681 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd", 1682 MODEL_PCD_DYNAMIC_EX : "DynamicEx", 1683 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx", 1684 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii", 1685 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd", 1686 } 1687 1688 # dict used to convert part of [Defines] to members of InfBuildData directly 1689 _PROPERTY_ = { 1690 # 1691 # Required Fields 1692 # 1693 TAB_INF_DEFINES_BASE_NAME : "_BaseName", 1694 TAB_INF_DEFINES_FILE_GUID : "_Guid", 1695 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType", 1696 # 1697 # Optional Fields 1698 # 1699 #TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion", 1700 TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType", 1701 TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName", 1702 #TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile", 1703 TAB_INF_DEFINES_DPX_SOURCE :"_DxsFile", 1704 TAB_INF_DEFINES_VERSION_NUMBER : "_Version", 1705 TAB_INF_DEFINES_VERSION_STRING : "_Version", 1706 TAB_INF_DEFINES_VERSION : "_Version", 1707 TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver", 1708 TAB_INF_DEFINES_SHADOW : "_Shadow", 1709 1710 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH : "_SourceOverridePath", 1711 } 1712 1713 # dict used to convert Component type to Module type 1714 _MODULE_TYPE_ = { 1715 "LIBRARY" : "BASE", 1716 "SECURITY_CORE" : "SEC", 1717 "PEI_CORE" : "PEI_CORE", 1718 "COMBINED_PEIM_DRIVER" : "PEIM", 1719 "PIC_PEIM" : "PEIM", 1720 "RELOCATABLE_PEIM" : "PEIM", 1721 "PE32_PEIM" : "PEIM", 1722 "BS_DRIVER" : "DXE_DRIVER", 1723 "RT_DRIVER" : "DXE_RUNTIME_DRIVER", 1724 "SAL_RT_DRIVER" : "DXE_SAL_DRIVER", 1725 "DXE_SMM_DRIVER" : "DXE_SMM_DRIVER", 1726 # "SMM_DRIVER" : "DXE_SMM_DRIVER", 1727 # "BS_DRIVER" : "DXE_SMM_DRIVER", 1728 # "BS_DRIVER" : "UEFI_DRIVER", 1729 "APPLICATION" : "UEFI_APPLICATION", 1730 "LOGO" : "BASE", 1731 } 1732 1733 # regular expression for converting XXX_FLAGS in [nmake] section to new type 1734 _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE) 1735 # dict used to convert old tool name used in [nmake] section to new ones 1736 _TOOL_CODE_ = { 1737 "C" : "CC", 1738 "LIB" : "SLINK", 1739 "LINK" : "DLINK", 1740 } 1741 1742 1743 ## Constructor of DscBuildData 1744 # 1745 # Initialize object of DscBuildData 1746 # 1747 # @param FilePath The path of platform description file 1748 # @param RawData The raw data of DSC file 1749 # @param BuildDataBase Database used to retrieve module/package information 1750 # @param Arch The target architecture 1751 # @param Platform The name of platform employing this module 1752 # @param Macros Macros used for replacement in DSC file 1753 # 1754 def __init__(self, FilePath, RawData, BuildDatabase, Arch='COMMON', Target=None, Toolchain=None): 1755 self.MetaFile = FilePath 1756 self._ModuleDir = FilePath.Dir 1757 self._RawData = RawData 1758 self._Bdb = BuildDatabase 1759 self._Arch = Arch 1760 self._Target = Target 1761 self._Toolchain = Toolchain 1762 self._Platform = 'COMMON' 1763 self._SourceOverridePath = None 1764 if FilePath.Key in GlobalData.gOverrideDir: 1765 self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key] 1766 self._Clear() 1767 1768 ## XXX[key] = value 1769 def __setitem__(self, key, value): 1770 self.__dict__[self._PROPERTY_[key]] = value 1771 1772 ## value = XXX[key] 1773 def __getitem__(self, key): 1774 return self.__dict__[self._PROPERTY_[key]] 1775 1776 ## "in" test support 1777 def __contains__(self, key): 1778 return key in self._PROPERTY_ 1779 1780 ## Set all internal used members of InfBuildData to None 1781 def _Clear(self): 1782 self._HeaderComments = None 1783 self._TailComments = None 1784 self._Header_ = None 1785 self._AutoGenVersion = None 1786 self._BaseName = None 1787 self._DxsFile = None 1788 self._ModuleType = None 1789 self._ComponentType = None 1790 self._BuildType = None 1791 self._Guid = None 1792 self._Version = None 1793 self._PcdIsDriver = None 1794 self._BinaryModule = None 1795 self._Shadow = None 1796 self._MakefileName = None 1797 self._CustomMakefile = None 1798 self._Specification = None 1799 self._LibraryClass = None 1800 self._ModuleEntryPointList = None 1801 self._ModuleUnloadImageList = None 1802 self._ConstructorList = None 1803 self._DestructorList = None 1804 self._Defs = None 1805 self._Binaries = None 1806 self._Sources = None 1807 self._LibraryClasses = None 1808 self._Libraries = None 1809 self._Protocols = None 1810 self._ProtocolComments = None 1811 self._Ppis = None 1812 self._PpiComments = None 1813 self._Guids = None 1814 self._GuidsUsedByPcd = sdict() 1815 self._GuidComments = None 1816 self._Includes = None 1817 self._Packages = None 1818 self._Pcds = None 1819 self._PcdComments = None 1820 self._BuildOptions = None 1821 self._Depex = None 1822 self._DepexExpression = None 1823 self.__Macros = None 1824 1825 ## Get current effective macros 1826 def _GetMacros(self): 1827 if self.__Macros == None: 1828 self.__Macros = {} 1829 # EDK_GLOBAL defined macros can be applied to EDK module 1830 if self.AutoGenVersion < 0x00010005: 1831 self.__Macros.update(GlobalData.gEdkGlobal) 1832 self.__Macros.update(GlobalData.gGlobalDefines) 1833 return self.__Macros 1834 1835 ## Get architecture 1836 def _GetArch(self): 1837 return self._Arch 1838 1839 ## Set architecture 1840 # 1841 # Changing the default ARCH to another may affect all other information 1842 # because all information in a platform may be ARCH-related. That's 1843 # why we need to clear all internal used members, in order to cause all 1844 # information to be re-retrieved. 1845 # 1846 # @param Value The value of ARCH 1847 # 1848 def _SetArch(self, Value): 1849 if self._Arch == Value: 1850 return 1851 self._Arch = Value 1852 self._Clear() 1853 1854 ## Return the name of platform employing this module 1855 def _GetPlatform(self): 1856 return self._Platform 1857 1858 ## Change the name of platform employing this module 1859 # 1860 # Changing the default name of platform to another may affect some information 1861 # because they may be PLATFORM-related. That's why we need to clear all internal 1862 # used members, in order to cause all information to be re-retrieved. 1863 # 1864 def _SetPlatform(self, Value): 1865 if self._Platform == Value: 1866 return 1867 self._Platform = Value 1868 self._Clear() 1869 def _GetHeaderComments(self): 1870 if not self._HeaderComments: 1871 self._HeaderComments = [] 1872 RecordList = self._RawData[MODEL_META_DATA_HEADER_COMMENT] 1873 for Record in RecordList: 1874 self._HeaderComments.append(Record[0]) 1875 return self._HeaderComments 1876 def _GetTailComments(self): 1877 if not self._TailComments: 1878 self._TailComments = [] 1879 RecordList = self._RawData[MODEL_META_DATA_TAIL_COMMENT] 1880 for Record in RecordList: 1881 self._TailComments.append(Record[0]) 1882 return self._TailComments 1883 ## Retrieve all information in [Defines] section 1884 # 1885 # (Retriving all [Defines] information in one-shot is just to save time.) 1886 # 1887 def _GetHeaderInfo(self): 1888 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform] 1889 for Record in RecordList: 1890 Name, Value = Record[1], ReplaceMacro(Record[2], self._Macros, False) 1891 # items defined _PROPERTY_ don't need additional processing 1892 if Name in self: 1893 self[Name] = Value 1894 if self._Defs == None: 1895 self._Defs = sdict() 1896 self._Defs[Name] = Value 1897 # some special items in [Defines] section need special treatment 1898 elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'): 1899 if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'): 1900 Name = 'UEFI_SPECIFICATION_VERSION' 1901 if self._Specification == None: 1902 self._Specification = sdict() 1903 self._Specification[Name] = GetHexVerValue(Value) 1904 if self._Specification[Name] == None: 1905 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, 1906 "'%s' format is not supported for %s" % (Value, Name), 1907 File=self.MetaFile, Line=Record[-1]) 1908 elif Name == 'LIBRARY_CLASS': 1909 if self._LibraryClass == None: 1910 self._LibraryClass = [] 1911 ValueList = GetSplitValueList(Value) 1912 LibraryClass = ValueList[0] 1913 if len(ValueList) > 1: 1914 SupModuleList = GetSplitValueList(ValueList[1], ' ') 1915 else: 1916 SupModuleList = SUP_MODULE_LIST 1917 self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList)) 1918 elif Name == 'ENTRY_POINT': 1919 if self._ModuleEntryPointList == None: 1920 self._ModuleEntryPointList = [] 1921 self._ModuleEntryPointList.append(Value) 1922 elif Name == 'UNLOAD_IMAGE': 1923 if self._ModuleUnloadImageList == None: 1924 self._ModuleUnloadImageList = [] 1925 if not Value: 1926 continue 1927 self._ModuleUnloadImageList.append(Value) 1928 elif Name == 'CONSTRUCTOR': 1929 if self._ConstructorList == None: 1930 self._ConstructorList = [] 1931 if not Value: 1932 continue 1933 self._ConstructorList.append(Value) 1934 elif Name == 'DESTRUCTOR': 1935 if self._DestructorList == None: 1936 self._DestructorList = [] 1937 if not Value: 1938 continue 1939 self._DestructorList.append(Value) 1940 elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE: 1941 TokenList = GetSplitValueList(Value) 1942 if self._CustomMakefile == None: 1943 self._CustomMakefile = {} 1944 if len(TokenList) < 2: 1945 self._CustomMakefile['MSFT'] = TokenList[0] 1946 self._CustomMakefile['GCC'] = TokenList[0] 1947 else: 1948 if TokenList[0] not in ['MSFT', 'GCC']: 1949 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, 1950 "No supported family [%s]" % TokenList[0], 1951 File=self.MetaFile, Line=Record[-1]) 1952 self._CustomMakefile[TokenList[0]] = TokenList[1] 1953 else: 1954 if self._Defs == None: 1955 self._Defs = sdict() 1956 self._Defs[Name] = Value 1957 1958 # 1959 # Retrieve information in sections specific to Edk.x modules 1960 # 1961 if self.AutoGenVersion >= 0x00010005: 1962 if not self._ModuleType: 1963 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, 1964 "MODULE_TYPE is not given", File=self.MetaFile) 1965 if self._ModuleType not in SUP_MODULE_LIST: 1966 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform] 1967 for Record in RecordList: 1968 Name = Record[1] 1969 if Name == "MODULE_TYPE": 1970 LineNo = Record[6] 1971 break 1972 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, 1973 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self._ModuleType, ' '.join(l for l in SUP_MODULE_LIST)), 1974 File=self.MetaFile, Line=LineNo) 1975 if (self._Specification == None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A): 1976 if self._ModuleType == SUP_MODULE_SMM_CORE: 1977 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) 1978 if self._Defs and 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \ 1979 and 'PCI_CLASS_CODE' in self._Defs and 'PCI_REVISION' in self._Defs: 1980 self._BuildType = 'UEFI_OPTIONROM' 1981 if 'PCI_COMPRESS' in self._Defs: 1982 if self._Defs['PCI_COMPRESS'] not in ('TRUE', 'FALSE'): 1983 EdkLogger.error("build", FORMAT_INVALID, "Expected TRUE/FALSE for PCI_COMPRESS: %s" %self.MetaFile) 1984 1985 elif self._Defs and 'UEFI_HII_RESOURCE_SECTION' in self._Defs \ 1986 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE': 1987 self._BuildType = 'UEFI_HII' 1988 else: 1989 self._BuildType = self._ModuleType.upper() 1990 1991 if self._DxsFile: 1992 File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch) 1993 # check the file validation 1994 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False) 1995 if ErrorCode != 0: 1996 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, 1997 File=self.MetaFile, Line=LineNo) 1998 if self.Sources == None: 1999 self._Sources = [] 2000 self._Sources.append(File) 2001 else: 2002 if not self._ComponentType: 2003 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, 2004 "COMPONENT_TYPE is not given", File=self.MetaFile) 2005 self._BuildType = self._ComponentType.upper() 2006 if self._ComponentType in self._MODULE_TYPE_: 2007 self._ModuleType = self._MODULE_TYPE_[self._ComponentType] 2008 if self._ComponentType == 'LIBRARY': 2009 self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)] 2010 # make use some [nmake] section macros 2011 Macros = self._Macros 2012 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 2013 Macros['PROCESSOR'] = self._Arch 2014 RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform] 2015 for Name, Value, Dummy, Arch, Platform, ID, LineNo in RecordList: 2016 Value = ReplaceMacro(Value, Macros, True) 2017 if Name == "IMAGE_ENTRY_POINT": 2018 if self._ModuleEntryPointList == None: 2019 self._ModuleEntryPointList = [] 2020 self._ModuleEntryPointList.append(Value) 2021 elif Name == "DPX_SOURCE": 2022 File = PathClass(NormPath(Value), self._ModuleDir, Arch=self._Arch) 2023 # check the file validation 2024 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False) 2025 if ErrorCode != 0: 2026 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, 2027 File=self.MetaFile, Line=LineNo) 2028 if self.Sources == None: 2029 self._Sources = [] 2030 self._Sources.append(File) 2031 else: 2032 ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name) 2033 if len(ToolList) == 0 or len(ToolList) != 1: 2034 pass 2035 # EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name, 2036 # File=self.MetaFile, Line=LineNo) 2037 else: 2038 if self._BuildOptions == None: 2039 self._BuildOptions = sdict() 2040 2041 if ToolList[0] in self._TOOL_CODE_: 2042 Tool = self._TOOL_CODE_[ToolList[0]] 2043 else: 2044 Tool = ToolList[0] 2045 ToolChain = "*_*_*_%s_FLAGS" % Tool 2046 ToolChainFamily = 'MSFT' # Edk.x only support MSFT tool chain 2047 #ignore not replaced macros in value 2048 ValueList = GetSplitList(' ' + Value, '/D') 2049 Dummy = ValueList[0] 2050 for Index in range(1, len(ValueList)): 2051 if ValueList[Index][-1] == '=' or ValueList[Index] == '': 2052 continue 2053 Dummy = Dummy + ' /D ' + ValueList[Index] 2054 Value = Dummy.strip() 2055 if (ToolChainFamily, ToolChain) not in self._BuildOptions: 2056 self._BuildOptions[ToolChainFamily, ToolChain] = Value 2057 else: 2058 OptionString = self._BuildOptions[ToolChainFamily, ToolChain] 2059 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value 2060 # set _Header to non-None in order to avoid database re-querying 2061 self._Header_ = 'DUMMY' 2062 2063 ## Retrieve file version 2064 def _GetInfVersion(self): 2065 if self._AutoGenVersion == None: 2066 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform] 2067 for Record in RecordList: 2068 if Record[1] == TAB_INF_DEFINES_INF_VERSION: 2069 if '.' in Record[2]: 2070 ValueList = Record[2].split('.') 2071 Major = '%04o' % int(ValueList[0], 0) 2072 Minor = '%04o' % int(ValueList[1], 0) 2073 self._AutoGenVersion = int('0x' + Major + Minor, 0) 2074 else: 2075 self._AutoGenVersion = int(Record[2], 0) 2076 break 2077 if self._AutoGenVersion == None: 2078 self._AutoGenVersion = 0x00010000 2079 return self._AutoGenVersion 2080 2081 ## Retrieve BASE_NAME 2082 def _GetBaseName(self): 2083 if self._BaseName == None: 2084 if self._Header_ == None: 2085 self._GetHeaderInfo() 2086 if self._BaseName == None: 2087 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile) 2088 return self._BaseName 2089 2090 ## Retrieve DxsFile 2091 def _GetDxsFile(self): 2092 if self._DxsFile == None: 2093 if self._Header_ == None: 2094 self._GetHeaderInfo() 2095 if self._DxsFile == None: 2096 self._DxsFile = '' 2097 return self._DxsFile 2098 2099 ## Retrieve MODULE_TYPE 2100 def _GetModuleType(self): 2101 if self._ModuleType == None: 2102 if self._Header_ == None: 2103 self._GetHeaderInfo() 2104 if self._ModuleType == None: 2105 self._ModuleType = 'BASE' 2106 if self._ModuleType not in SUP_MODULE_LIST: 2107 self._ModuleType = "USER_DEFINED" 2108 return self._ModuleType 2109 2110 ## Retrieve COMPONENT_TYPE 2111 def _GetComponentType(self): 2112 if self._ComponentType == None: 2113 if self._Header_ == None: 2114 self._GetHeaderInfo() 2115 if self._ComponentType == None: 2116 self._ComponentType = 'USER_DEFINED' 2117 return self._ComponentType 2118 2119 ## Retrieve "BUILD_TYPE" 2120 def _GetBuildType(self): 2121 if self._BuildType == None: 2122 if self._Header_ == None: 2123 self._GetHeaderInfo() 2124 if not self._BuildType: 2125 self._BuildType = "BASE" 2126 return self._BuildType 2127 2128 ## Retrieve file guid 2129 def _GetFileGuid(self): 2130 if self._Guid == None: 2131 if self._Header_ == None: 2132 self._GetHeaderInfo() 2133 if self._Guid == None: 2134 self._Guid = '00000000-0000-0000-0000-000000000000' 2135 return self._Guid 2136 2137 ## Retrieve module version 2138 def _GetVersion(self): 2139 if self._Version == None: 2140 if self._Header_ == None: 2141 self._GetHeaderInfo() 2142 if self._Version == None: 2143 self._Version = '0.0' 2144 return self._Version 2145 2146 ## Retrieve PCD_IS_DRIVER 2147 def _GetPcdIsDriver(self): 2148 if self._PcdIsDriver == None: 2149 if self._Header_ == None: 2150 self._GetHeaderInfo() 2151 if self._PcdIsDriver == None: 2152 self._PcdIsDriver = '' 2153 return self._PcdIsDriver 2154 2155 ## Retrieve SHADOW 2156 def _GetShadow(self): 2157 if self._Shadow == None: 2158 if self._Header_ == None: 2159 self._GetHeaderInfo() 2160 if self._Shadow != None and self._Shadow.upper() == 'TRUE': 2161 self._Shadow = True 2162 else: 2163 self._Shadow = False 2164 return self._Shadow 2165 2166 ## Retrieve CUSTOM_MAKEFILE 2167 def _GetMakefile(self): 2168 if self._CustomMakefile == None: 2169 if self._Header_ == None: 2170 self._GetHeaderInfo() 2171 if self._CustomMakefile == None: 2172 self._CustomMakefile = {} 2173 return self._CustomMakefile 2174 2175 ## Retrieve EFI_SPECIFICATION_VERSION 2176 def _GetSpec(self): 2177 if self._Specification == None: 2178 if self._Header_ == None: 2179 self._GetHeaderInfo() 2180 if self._Specification == None: 2181 self._Specification = {} 2182 return self._Specification 2183 2184 ## Retrieve LIBRARY_CLASS 2185 def _GetLibraryClass(self): 2186 if self._LibraryClass == None: 2187 if self._Header_ == None: 2188 self._GetHeaderInfo() 2189 if self._LibraryClass == None: 2190 self._LibraryClass = [] 2191 return self._LibraryClass 2192 2193 ## Retrieve ENTRY_POINT 2194 def _GetEntryPoint(self): 2195 if self._ModuleEntryPointList == None: 2196 if self._Header_ == None: 2197 self._GetHeaderInfo() 2198 if self._ModuleEntryPointList == None: 2199 self._ModuleEntryPointList = [] 2200 return self._ModuleEntryPointList 2201 2202 ## Retrieve UNLOAD_IMAGE 2203 def _GetUnloadImage(self): 2204 if self._ModuleUnloadImageList == None: 2205 if self._Header_ == None: 2206 self._GetHeaderInfo() 2207 if self._ModuleUnloadImageList == None: 2208 self._ModuleUnloadImageList = [] 2209 return self._ModuleUnloadImageList 2210 2211 ## Retrieve CONSTRUCTOR 2212 def _GetConstructor(self): 2213 if self._ConstructorList == None: 2214 if self._Header_ == None: 2215 self._GetHeaderInfo() 2216 if self._ConstructorList == None: 2217 self._ConstructorList = [] 2218 return self._ConstructorList 2219 2220 ## Retrieve DESTRUCTOR 2221 def _GetDestructor(self): 2222 if self._DestructorList == None: 2223 if self._Header_ == None: 2224 self._GetHeaderInfo() 2225 if self._DestructorList == None: 2226 self._DestructorList = [] 2227 return self._DestructorList 2228 2229 ## Retrieve definies other than above ones 2230 def _GetDefines(self): 2231 if self._Defs == None: 2232 if self._Header_ == None: 2233 self._GetHeaderInfo() 2234 if self._Defs == None: 2235 self._Defs = sdict() 2236 return self._Defs 2237 2238 ## Retrieve binary files 2239 def _GetBinaries(self): 2240 if self._Binaries == None: 2241 self._Binaries = [] 2242 RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform] 2243 Macros = self._Macros 2244 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 2245 Macros['PROCESSOR'] = self._Arch 2246 for Record in RecordList: 2247 FileType = Record[0] 2248 LineNo = Record[-1] 2249 Target = 'COMMON' 2250 FeatureFlag = [] 2251 if Record[2]: 2252 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT) 2253 if TokenList: 2254 Target = TokenList[0] 2255 if len(TokenList) > 1: 2256 FeatureFlag = Record[1:] 2257 2258 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target) 2259 # check the file validation 2260 ErrorCode, ErrorInfo = File.Validate() 2261 if ErrorCode != 0: 2262 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) 2263 self._Binaries.append(File) 2264 return self._Binaries 2265 2266 ## Retrieve binary files with error check. 2267 def _GetBinaryFiles(self): 2268 Binaries = self._GetBinaries() 2269 if GlobalData.gIgnoreSource and Binaries == []: 2270 ErrorInfo = "The INF file does not contain any Binaries to use in creating the image\n" 2271 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile) 2272 2273 return Binaries 2274 ## Check whether it exists the binaries with current ARCH in AsBuild INF 2275 def _IsSupportedArch(self): 2276 if self._GetBinaries() and not self._GetSourceFiles(): 2277 return True 2278 else: 2279 return False 2280 ## Retrieve source files 2281 def _GetSourceFiles(self): 2282 #Ignore all source files in a binary build mode 2283 if GlobalData.gIgnoreSource: 2284 self._Sources = [] 2285 return self._Sources 2286 2287 if self._Sources == None: 2288 self._Sources = [] 2289 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform] 2290 Macros = self._Macros 2291 for Record in RecordList: 2292 LineNo = Record[-1] 2293 ToolChainFamily = Record[1] 2294 TagName = Record[2] 2295 ToolCode = Record[3] 2296 FeatureFlag = Record[4] 2297 if self.AutoGenVersion < 0x00010005: 2298 Macros["EDK_SOURCE"] = GlobalData.gEcpSource 2299 Macros['PROCESSOR'] = self._Arch 2300 SourceFile = NormPath(Record[0], Macros) 2301 if SourceFile[0] == os.path.sep: 2302 SourceFile = mws.join(GlobalData.gWorkspace, SourceFile[1:]) 2303 # old module source files (Edk) 2304 File = PathClass(SourceFile, self._ModuleDir, self._SourceOverridePath, 2305 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode) 2306 # check the file validation 2307 ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False) 2308 if ErrorCode != 0: 2309 if File.Ext.lower() == '.h': 2310 EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo, 2311 File=self.MetaFile, Line=LineNo) 2312 continue 2313 else: 2314 EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo) 2315 else: 2316 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '', 2317 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode) 2318 # check the file validation 2319 ErrorCode, ErrorInfo = File.Validate() 2320 if ErrorCode != 0: 2321 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) 2322 2323 self._Sources.append(File) 2324 return self._Sources 2325 2326 ## Retrieve library classes employed by this module 2327 def _GetLibraryClassUses(self): 2328 if self._LibraryClasses == None: 2329 self._LibraryClasses = sdict() 2330 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform] 2331 for Record in RecordList: 2332 Lib = Record[0] 2333 Instance = Record[1] 2334 if Instance: 2335 Instance = NormPath(Instance, self._Macros) 2336 self._LibraryClasses[Lib] = Instance 2337 return self._LibraryClasses 2338 2339 ## Retrieve library names (for Edk.x style of modules) 2340 def _GetLibraryNames(self): 2341 if self._Libraries == None: 2342 self._Libraries = [] 2343 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform] 2344 for Record in RecordList: 2345 LibraryName = ReplaceMacro(Record[0], self._Macros, False) 2346 # in case of name with '.lib' extension, which is unusual in Edk.x inf 2347 LibraryName = os.path.splitext(LibraryName)[0] 2348 if LibraryName not in self._Libraries: 2349 self._Libraries.append(LibraryName) 2350 return self._Libraries 2351 2352 def _GetProtocolComments(self): 2353 self._GetProtocols() 2354 return self._ProtocolComments 2355 ## Retrieve protocols consumed/produced by this module 2356 def _GetProtocols(self): 2357 if self._Protocols == None: 2358 self._Protocols = sdict() 2359 self._ProtocolComments = sdict() 2360 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform] 2361 for Record in RecordList: 2362 CName = Record[0] 2363 Value = ProtocolValue(CName, self.Packages, self.MetaFile.Path) 2364 if Value == None: 2365 PackageList = "\n\t".join([str(P) for P in self.Packages]) 2366 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, 2367 "Value of Protocol [%s] is not found under [Protocols] section in" % CName, 2368 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) 2369 self._Protocols[CName] = Value 2370 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]] 2371 Comments = [] 2372 for CmtRec in CommentRecords: 2373 Comments.append(CmtRec[0]) 2374 self._ProtocolComments[CName] = Comments 2375 return self._Protocols 2376 2377 def _GetPpiComments(self): 2378 self._GetPpis() 2379 return self._PpiComments 2380 ## Retrieve PPIs consumed/produced by this module 2381 def _GetPpis(self): 2382 if self._Ppis == None: 2383 self._Ppis = sdict() 2384 self._PpiComments = sdict() 2385 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform] 2386 for Record in RecordList: 2387 CName = Record[0] 2388 Value = PpiValue(CName, self.Packages, self.MetaFile.Path) 2389 if Value == None: 2390 PackageList = "\n\t".join([str(P) for P in self.Packages]) 2391 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, 2392 "Value of PPI [%s] is not found under [Ppis] section in " % CName, 2393 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) 2394 self._Ppis[CName] = Value 2395 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]] 2396 Comments = [] 2397 for CmtRec in CommentRecords: 2398 Comments.append(CmtRec[0]) 2399 self._PpiComments[CName] = Comments 2400 return self._Ppis 2401 2402 def _GetGuidComments(self): 2403 self._GetGuids() 2404 return self._GuidComments 2405 ## Retrieve GUIDs consumed/produced by this module 2406 def _GetGuids(self): 2407 if self._Guids == None: 2408 self._Guids = sdict() 2409 self._GuidComments = sdict() 2410 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform] 2411 for Record in RecordList: 2412 CName = Record[0] 2413 Value = GuidValue(CName, self.Packages, self.MetaFile.Path) 2414 if Value == None: 2415 PackageList = "\n\t".join([str(P) for P in self.Packages]) 2416 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, 2417 "Value of Guid [%s] is not found under [Guids] section in" % CName, 2418 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) 2419 self._Guids[CName] = Value 2420 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]] 2421 Comments = [] 2422 for CmtRec in CommentRecords: 2423 Comments.append(CmtRec[0]) 2424 self._GuidComments[CName] = Comments 2425 return self._Guids 2426 2427 ## Retrieve include paths necessary for this module (for Edk.x style of modules) 2428 def _GetIncludes(self): 2429 if self._Includes == None: 2430 self._Includes = [] 2431 if self._SourceOverridePath: 2432 self._Includes.append(self._SourceOverridePath) 2433 2434 Macros = self._Macros 2435 if 'PROCESSOR' in GlobalData.gEdkGlobal.keys(): 2436 Macros['PROCESSOR'] = GlobalData.gEdkGlobal['PROCESSOR'] 2437 else: 2438 Macros['PROCESSOR'] = self._Arch 2439 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform] 2440 for Record in RecordList: 2441 if Record[0].find('EDK_SOURCE') > -1: 2442 Macros['EDK_SOURCE'] = GlobalData.gEcpSource 2443 File = NormPath(Record[0], self._Macros) 2444 if File[0] == '.': 2445 File = os.path.join(self._ModuleDir, File) 2446 else: 2447 File = os.path.join(GlobalData.gWorkspace, File) 2448 File = RealPath(os.path.normpath(File)) 2449 if File: 2450 self._Includes.append(File) 2451 2452 #TRICK: let compiler to choose correct header file 2453 Macros['EDK_SOURCE'] = GlobalData.gEdkSource 2454 File = NormPath(Record[0], self._Macros) 2455 if File[0] == '.': 2456 File = os.path.join(self._ModuleDir, File) 2457 else: 2458 File = os.path.join(GlobalData.gWorkspace, File) 2459 File = RealPath(os.path.normpath(File)) 2460 if File: 2461 self._Includes.append(File) 2462 else: 2463 File = NormPath(Record[0], Macros) 2464 if File[0] == '.': 2465 File = os.path.join(self._ModuleDir, File) 2466 else: 2467 File = mws.join(GlobalData.gWorkspace, File) 2468 File = RealPath(os.path.normpath(File)) 2469 if File: 2470 self._Includes.append(File) 2471 if not File and Record[0].find('EFI_SOURCE') > -1: 2472 # tricky to regard WorkSpace as EFI_SOURCE 2473 Macros['EFI_SOURCE'] = GlobalData.gWorkspace 2474 File = NormPath(Record[0], Macros) 2475 if File[0] == '.': 2476 File = os.path.join(self._ModuleDir, File) 2477 else: 2478 File = os.path.join(GlobalData.gWorkspace, File) 2479 File = RealPath(os.path.normpath(File)) 2480 if File: 2481 self._Includes.append(File) 2482 return self._Includes 2483 2484 ## Retrieve packages this module depends on 2485 def _GetPackages(self): 2486 if self._Packages == None: 2487 self._Packages = [] 2488 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform] 2489 Macros = self._Macros 2490 Macros['EDK_SOURCE'] = GlobalData.gEcpSource 2491 for Record in RecordList: 2492 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch) 2493 LineNo = Record[-1] 2494 # check the file validation 2495 ErrorCode, ErrorInfo = File.Validate('.dec') 2496 if ErrorCode != 0: 2497 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo) 2498 # parse this package now. we need it to get protocol/ppi/guid value 2499 Package = self._Bdb[File, self._Arch, self._Target, self._Toolchain] 2500 self._Packages.append(Package) 2501 return self._Packages 2502 2503 ## Retrieve PCD comments 2504 def _GetPcdComments(self): 2505 self._GetPcds() 2506 return self._PcdComments 2507 ## Retrieve PCDs used in this module 2508 def _GetPcds(self): 2509 if self._Pcds == None: 2510 self._Pcds = sdict() 2511 self._PcdComments = sdict() 2512 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD)) 2513 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE)) 2514 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG)) 2515 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC)) 2516 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX)) 2517 return self._Pcds 2518 2519 ## Retrieve build options specific to this module 2520 def _GetBuildOptions(self): 2521 if self._BuildOptions == None: 2522 self._BuildOptions = sdict() 2523 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform] 2524 for Record in RecordList: 2525 ToolChainFamily = Record[0] 2526 ToolChain = Record[1] 2527 Option = Record[2] 2528 if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='): 2529 self._BuildOptions[ToolChainFamily, ToolChain] = Option 2530 else: 2531 # concatenate the option string if they're for the same tool 2532 OptionString = self._BuildOptions[ToolChainFamily, ToolChain] 2533 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option 2534 return self._BuildOptions 2535 2536 ## Retrieve dependency expression 2537 def _GetDepex(self): 2538 if self._Depex == None: 2539 self._Depex = tdict(False, 2) 2540 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch] 2541 2542 # If the module has only Binaries and no Sources, then ignore [Depex] 2543 if self.Sources == None or self.Sources == []: 2544 if self.Binaries != None and self.Binaries != []: 2545 return self._Depex 2546 2547 # PEIM and DXE drivers must have a valid [Depex] section 2548 if len(self.LibraryClass) == 0 and len(RecordList) == 0: 2549 if self.ModuleType == 'DXE_DRIVER' or self.ModuleType == 'PEIM' or self.ModuleType == 'DXE_SMM_DRIVER' or \ 2550 self.ModuleType == 'DXE_SAL_DRIVER' or self.ModuleType == 'DXE_RUNTIME_DRIVER': 2551 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \ 2552 % self.ModuleType, File=self.MetaFile) 2553 2554 if len(RecordList) != 0 and self.ModuleType == 'USER_DEFINED': 2555 for Record in RecordList: 2556 if Record[4] not in ['PEIM', 'DXE_DRIVER', 'DXE_SMM_DRIVER']: 2557 EdkLogger.error('build', FORMAT_INVALID, 2558 "'%s' module must specify the type of [Depex] section" % self.ModuleType, 2559 File=self.MetaFile) 2560 2561 Depex = sdict() 2562 for Record in RecordList: 2563 DepexStr = ReplaceMacro(Record[0], self._Macros, False) 2564 Arch = Record[3] 2565 ModuleType = Record[4] 2566 TokenList = DepexStr.split() 2567 if (Arch, ModuleType) not in Depex: 2568 Depex[Arch, ModuleType] = [] 2569 DepexList = Depex[Arch, ModuleType] 2570 for Token in TokenList: 2571 if Token in DEPEX_SUPPORTED_OPCODE: 2572 DepexList.append(Token) 2573 elif Token.endswith(".inf"): # module file name 2574 ModuleFile = os.path.normpath(Token) 2575 Module = self.BuildDatabase[ModuleFile] 2576 if Module == None: 2577 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform", 2578 ExtraData=Token, File=self.MetaFile, Line=Record[-1]) 2579 DepexList.append(Module.Guid) 2580 else: 2581 # get the GUID value now 2582 Value = ProtocolValue(Token, self.Packages, self.MetaFile.Path) 2583 if Value == None: 2584 Value = PpiValue(Token, self.Packages, self.MetaFile.Path) 2585 if Value == None: 2586 Value = GuidValue(Token, self.Packages, self.MetaFile.Path) 2587 if Value == None: 2588 PackageList = "\n\t".join([str(P) for P in self.Packages]) 2589 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, 2590 "Value of [%s] is not found in" % Token, 2591 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1]) 2592 DepexList.append(Value) 2593 for Arch, ModuleType in Depex: 2594 self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType] 2595 return self._Depex 2596 2597 ## Retrieve depedency expression 2598 def _GetDepexExpression(self): 2599 if self._DepexExpression == None: 2600 self._DepexExpression = tdict(False, 2) 2601 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch] 2602 DepexExpression = sdict() 2603 for Record in RecordList: 2604 DepexStr = ReplaceMacro(Record[0], self._Macros, False) 2605 Arch = Record[3] 2606 ModuleType = Record[4] 2607 TokenList = DepexStr.split() 2608 if (Arch, ModuleType) not in DepexExpression: 2609 DepexExpression[Arch, ModuleType] = '' 2610 for Token in TokenList: 2611 DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] + Token.strip() + ' ' 2612 for Arch, ModuleType in DepexExpression: 2613 self._DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] 2614 return self._DepexExpression 2615 2616 def GetGuidsUsedByPcd(self): 2617 return self._GuidsUsedByPcd 2618 ## Retrieve PCD for given type 2619 def _GetPcd(self, Type): 2620 Pcds = sdict() 2621 PcdDict = tdict(True, 4) 2622 PcdList = [] 2623 RecordList = self._RawData[Type, self._Arch, self._Platform] 2624 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Id, LineNo in RecordList: 2625 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo) 2626 PcdList.append((PcdCName, TokenSpaceGuid)) 2627 # get the guid value 2628 if TokenSpaceGuid not in self.Guids: 2629 Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path) 2630 if Value == None: 2631 PackageList = "\n\t".join([str(P) for P in self.Packages]) 2632 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, 2633 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid, 2634 ExtraData=PackageList, File=self.MetaFile, Line=LineNo) 2635 self.Guids[TokenSpaceGuid] = Value 2636 self._GuidsUsedByPcd[TokenSpaceGuid] = Value 2637 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Id] 2638 Comments = [] 2639 for CmtRec in CommentRecords: 2640 Comments.append(CmtRec[0]) 2641 self._PcdComments[TokenSpaceGuid, PcdCName] = Comments 2642 2643 # resolve PCD type, value, datum info, etc. by getting its definition from package 2644 for PcdCName, TokenSpaceGuid in PcdList: 2645 PcdRealName = PcdCName 2646 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid] 2647 if Setting == None: 2648 continue 2649 ValueList = AnalyzePcdData(Setting) 2650 DefaultValue = ValueList[0] 2651 Pcd = PcdClassObject( 2652 PcdCName, 2653 TokenSpaceGuid, 2654 '', 2655 '', 2656 DefaultValue, 2657 '', 2658 '', 2659 {}, 2660 False, 2661 self.Guids[TokenSpaceGuid] 2662 ) 2663 if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]: 2664 # Patch PCD: TokenSpace.PcdCName|Value|Offset 2665 Pcd.Offset = ValueList[1] 2666 2667 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd: 2668 for Package in self.Packages: 2669 for key in Package.Pcds: 2670 if (Package.Pcds[key].TokenCName, Package.Pcds[key].TokenSpaceGuidCName) == (PcdRealName, TokenSpaceGuid): 2671 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]: 2672 Pcd_Type = item[0].split('_')[-1] 2673 if Pcd_Type == Package.Pcds[key].Type: 2674 Value = Package.Pcds[key] 2675 Value.TokenCName = Package.Pcds[key].TokenCName + '_' + Pcd_Type 2676 if len(key) == 2: 2677 newkey = (Value.TokenCName, key[1]) 2678 elif len(key) == 3: 2679 newkey = (Value.TokenCName, key[1], key[2]) 2680 del Package.Pcds[key] 2681 Package.Pcds[newkey] = Value 2682 break 2683 else: 2684 pass 2685 else: 2686 pass 2687 2688 # get necessary info from package declaring this PCD 2689 for Package in self.Packages: 2690 # 2691 # 'dynamic' in INF means its type is determined by platform; 2692 # if platform doesn't give its type, use 'lowest' one in the 2693 # following order, if any 2694 # 2695 # "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx" 2696 # 2697 PcdType = self._PCD_TYPE_STRING_[Type] 2698 if Type == MODEL_PCD_DYNAMIC: 2699 Pcd.Pending = True 2700 for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]: 2701 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd: 2702 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]: 2703 if str(item[0]).endswith(T) and (item[0], item[1], T) in Package.Pcds: 2704 PcdType = T 2705 PcdCName = item[0] 2706 break 2707 else: 2708 pass 2709 break 2710 else: 2711 if (PcdRealName, TokenSpaceGuid, T) in Package.Pcds: 2712 PcdType = T 2713 break 2714 2715 else: 2716 Pcd.Pending = False 2717 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd: 2718 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]: 2719 Pcd_Type = item[0].split('_')[-1] 2720 if Pcd_Type == PcdType: 2721 PcdCName = item[0] 2722 break 2723 else: 2724 pass 2725 else: 2726 pass 2727 2728 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds: 2729 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType] 2730 Pcd.Type = PcdType 2731 Pcd.TokenValue = PcdInPackage.TokenValue 2732 2733 # 2734 # Check whether the token value exist or not. 2735 # 2736 if Pcd.TokenValue == None or Pcd.TokenValue == "": 2737 EdkLogger.error( 2738 'build', 2739 FORMAT_INVALID, 2740 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdRealName, str(Package)), 2741 File=self.MetaFile, Line=LineNo, 2742 ExtraData=None 2743 ) 2744 # 2745 # Check hexadecimal token value length and format. 2746 # 2747 ReIsValidPcdTokenValue = re.compile(r"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re.DOTALL) 2748 if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"): 2749 if ReIsValidPcdTokenValue.match(Pcd.TokenValue) == None: 2750 EdkLogger.error( 2751 'build', 2752 FORMAT_INVALID, 2753 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)), 2754 File=self.MetaFile, Line=LineNo, 2755 ExtraData=None 2756 ) 2757 2758 # 2759 # Check decimal token value length and format. 2760 # 2761 else: 2762 try: 2763 TokenValueInt = int (Pcd.TokenValue, 10) 2764 if (TokenValueInt < 0 or TokenValueInt > 4294967295): 2765 EdkLogger.error( 2766 'build', 2767 FORMAT_INVALID, 2768 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, as a decimal it should between: 0 - 4294967295!" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)), 2769 File=self.MetaFile, Line=LineNo, 2770 ExtraData=None 2771 ) 2772 except: 2773 EdkLogger.error( 2774 'build', 2775 FORMAT_INVALID, 2776 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, it should be hexadecimal or decimal!" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)), 2777 File=self.MetaFile, Line=LineNo, 2778 ExtraData=None 2779 ) 2780 2781 Pcd.DatumType = PcdInPackage.DatumType 2782 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize 2783 Pcd.InfDefaultValue = Pcd.DefaultValue 2784 if Pcd.DefaultValue in [None, '']: 2785 Pcd.DefaultValue = PcdInPackage.DefaultValue 2786 break 2787 else: 2788 EdkLogger.error( 2789 'build', 2790 FORMAT_INVALID, 2791 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdRealName, self.MetaFile), 2792 File=self.MetaFile, Line=LineNo, 2793 ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages]) 2794 ) 2795 Pcds[PcdCName, TokenSpaceGuid] = Pcd 2796 2797 return Pcds 2798 2799 ## check whether current module is binary module 2800 def _IsBinaryModule(self): 2801 if self.Binaries and not self.Sources: 2802 return True 2803 elif GlobalData.gIgnoreSource: 2804 return True 2805 else: 2806 return False 2807 2808 _Macros = property(_GetMacros) 2809 Arch = property(_GetArch, _SetArch) 2810 Platform = property(_GetPlatform, _SetPlatform) 2811 2812 HeaderComments = property(_GetHeaderComments) 2813 TailComments = property(_GetTailComments) 2814 AutoGenVersion = property(_GetInfVersion) 2815 BaseName = property(_GetBaseName) 2816 ModuleType = property(_GetModuleType) 2817 ComponentType = property(_GetComponentType) 2818 BuildType = property(_GetBuildType) 2819 Guid = property(_GetFileGuid) 2820 Version = property(_GetVersion) 2821 PcdIsDriver = property(_GetPcdIsDriver) 2822 Shadow = property(_GetShadow) 2823 CustomMakefile = property(_GetMakefile) 2824 Specification = property(_GetSpec) 2825 LibraryClass = property(_GetLibraryClass) 2826 ModuleEntryPointList = property(_GetEntryPoint) 2827 ModuleUnloadImageList = property(_GetUnloadImage) 2828 ConstructorList = property(_GetConstructor) 2829 DestructorList = property(_GetDestructor) 2830 Defines = property(_GetDefines) 2831 DxsFile = property(_GetDxsFile) 2832 2833 Binaries = property(_GetBinaryFiles) 2834 Sources = property(_GetSourceFiles) 2835 LibraryClasses = property(_GetLibraryClassUses) 2836 Libraries = property(_GetLibraryNames) 2837 Protocols = property(_GetProtocols) 2838 ProtocolComments = property(_GetProtocolComments) 2839 Ppis = property(_GetPpis) 2840 PpiComments = property(_GetPpiComments) 2841 Guids = property(_GetGuids) 2842 GuidComments = property(_GetGuidComments) 2843 Includes = property(_GetIncludes) 2844 Packages = property(_GetPackages) 2845 Pcds = property(_GetPcds) 2846 PcdComments = property(_GetPcdComments) 2847 BuildOptions = property(_GetBuildOptions) 2848 Depex = property(_GetDepex) 2849 DepexExpression = property(_GetDepexExpression) 2850 IsBinaryModule = property(_IsBinaryModule) 2851 IsSupportedArch = property(_IsSupportedArch) 2852 2853 ## Database 2854 # 2855 # This class defined the build database for all modules, packages and platform. 2856 # It will call corresponding parser for the given file if it cannot find it in 2857 # the database. 2858 # 2859 # @param DbPath Path of database file 2860 # @param GlobalMacros Global macros used for replacement during file parsing 2861 # @prarm RenewDb=False Create new database file if it's already there 2862 # 2863 class WorkspaceDatabase(object): 2864 2865 2866 # 2867 # internal class used for call corresponding file parser and caching the result 2868 # to avoid unnecessary re-parsing 2869 # 2870 class BuildObjectFactory(object): 2871 2872 _FILE_TYPE_ = { 2873 ".inf" : MODEL_FILE_INF, 2874 ".dec" : MODEL_FILE_DEC, 2875 ".dsc" : MODEL_FILE_DSC, 2876 } 2877 2878 # file parser 2879 _FILE_PARSER_ = { 2880 MODEL_FILE_INF : InfParser, 2881 MODEL_FILE_DEC : DecParser, 2882 MODEL_FILE_DSC : DscParser, 2883 } 2884 2885 # convert to xxxBuildData object 2886 _GENERATOR_ = { 2887 MODEL_FILE_INF : InfBuildData, 2888 MODEL_FILE_DEC : DecBuildData, 2889 MODEL_FILE_DSC : DscBuildData, 2890 } 2891 2892 _CACHE_ = {} # (FilePath, Arch) : <object> 2893 2894 # constructor 2895 def __init__(self, WorkspaceDb): 2896 self.WorkspaceDb = WorkspaceDb 2897 2898 # key = (FilePath, Arch=None) 2899 def __contains__(self, Key): 2900 FilePath = Key[0] 2901 if len(Key) > 1: 2902 Arch = Key[1] 2903 else: 2904 Arch = None 2905 return (FilePath, Arch) in self._CACHE_ 2906 2907 # key = (FilePath, Arch=None, Target=None, Toochain=None) 2908 def __getitem__(self, Key): 2909 FilePath = Key[0] 2910 KeyLength = len(Key) 2911 if KeyLength > 1: 2912 Arch = Key[1] 2913 else: 2914 Arch = None 2915 if KeyLength > 2: 2916 Target = Key[2] 2917 else: 2918 Target = None 2919 if KeyLength > 3: 2920 Toolchain = Key[3] 2921 else: 2922 Toolchain = None 2923 2924 # if it's generated before, just return the cached one 2925 Key = (FilePath, Arch, Target, Toolchain) 2926 if Key in self._CACHE_: 2927 return self._CACHE_[Key] 2928 2929 # check file type 2930 Ext = FilePath.Type 2931 if Ext not in self._FILE_TYPE_: 2932 return None 2933 FileType = self._FILE_TYPE_[Ext] 2934 if FileType not in self._GENERATOR_: 2935 return None 2936 2937 # get the parser ready for this file 2938 MetaFile = self._FILE_PARSER_[FileType]( 2939 FilePath, 2940 FileType, 2941 Arch, 2942 MetaFileStorage(self.WorkspaceDb.Cur, FilePath, FileType) 2943 ) 2944 # alwasy do post-process, in case of macros change 2945 MetaFile.DoPostProcess() 2946 # object the build is based on 2947 BuildObject = self._GENERATOR_[FileType]( 2948 FilePath, 2949 MetaFile, 2950 self, 2951 Arch, 2952 Target, 2953 Toolchain 2954 ) 2955 self._CACHE_[Key] = BuildObject 2956 return BuildObject 2957 2958 # placeholder for file format conversion 2959 class TransformObjectFactory: 2960 def __init__(self, WorkspaceDb): 2961 self.WorkspaceDb = WorkspaceDb 2962 2963 # key = FilePath, Arch 2964 def __getitem__(self, Key): 2965 pass 2966 2967 ## Constructor of WorkspaceDatabase 2968 # 2969 # @param DbPath Path of database file 2970 # @param GlobalMacros Global macros used for replacement during file parsing 2971 # @prarm RenewDb=False Create new database file if it's already there 2972 # 2973 def __init__(self, DbPath, RenewDb=False): 2974 self._DbClosedFlag = False 2975 if not DbPath: 2976 DbPath = os.path.normpath(mws.join(GlobalData.gWorkspace, 'Conf', GlobalData.gDatabasePath)) 2977 2978 # don't create necessary path for db in memory 2979 if DbPath != ':memory:': 2980 DbDir = os.path.split(DbPath)[0] 2981 if not os.path.exists(DbDir): 2982 os.makedirs(DbDir) 2983 2984 # remove db file in case inconsistency between db and file in file system 2985 if self._CheckWhetherDbNeedRenew(RenewDb, DbPath): 2986 os.remove(DbPath) 2987 2988 # create db with optimized parameters 2989 self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED') 2990 self.Conn.execute("PRAGMA synchronous=OFF") 2991 self.Conn.execute("PRAGMA temp_store=MEMORY") 2992 self.Conn.execute("PRAGMA count_changes=OFF") 2993 self.Conn.execute("PRAGMA cache_size=8192") 2994 #self.Conn.execute("PRAGMA page_size=8192") 2995 2996 # to avoid non-ascii character conversion issue 2997 self.Conn.text_factory = str 2998 self.Cur = self.Conn.cursor() 2999 3000 # create table for internal uses 3001 self.TblDataModel = TableDataModel(self.Cur) 3002 self.TblFile = TableFile(self.Cur) 3003 self.Platform = None 3004 3005 # conversion object for build or file format conversion purpose 3006 self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self) 3007 self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self) 3008 3009 ## Check whether workspace database need to be renew. 3010 # The renew reason maybe: 3011 # 1) If user force to renew; 3012 # 2) If user do not force renew, and 3013 # a) If the time of last modified python source is newer than database file; 3014 # b) If the time of last modified frozen executable file is newer than database file; 3015 # 3016 # @param force User force renew database 3017 # @param DbPath The absolute path of workspace database file 3018 # 3019 # @return Bool value for whether need renew workspace databse 3020 # 3021 def _CheckWhetherDbNeedRenew (self, force, DbPath): 3022 # if database does not exist, we need do nothing 3023 if not os.path.exists(DbPath): return False 3024 3025 # if user force to renew database, then not check whether database is out of date 3026 if force: return True 3027 3028 # 3029 # Check the time of last modified source file or build.exe 3030 # if is newer than time of database, then database need to be re-created. 3031 # 3032 timeOfToolModified = 0 3033 if hasattr(sys, "frozen"): 3034 exePath = os.path.abspath(sys.executable) 3035 timeOfToolModified = os.stat(exePath).st_mtime 3036 else: 3037 curPath = os.path.dirname(__file__) # curPath is the path of WorkspaceDatabase.py 3038 rootPath = os.path.split(curPath)[0] # rootPath is root path of python source, such as /BaseTools/Source/Python 3039 if rootPath == "" or rootPath == None: 3040 EdkLogger.verbose("\nFail to find the root path of build.exe or python sources, so can not \ 3041 determine whether database file is out of date!\n") 3042 3043 # walk the root path of source or build's binary to get the time last modified. 3044 3045 for root, dirs, files in os.walk (rootPath): 3046 for dir in dirs: 3047 # bypass source control folder 3048 if dir.lower() in [".svn", "_svn", "cvs"]: 3049 dirs.remove(dir) 3050 3051 for file in files: 3052 ext = os.path.splitext(file)[1] 3053 if ext.lower() == ".py": # only check .py files 3054 fd = os.stat(os.path.join(root, file)) 3055 if timeOfToolModified < fd.st_mtime: 3056 timeOfToolModified = fd.st_mtime 3057 if timeOfToolModified > os.stat(DbPath).st_mtime: 3058 EdkLogger.verbose("\nWorkspace database is out of data!") 3059 return True 3060 3061 return False 3062 3063 ## Initialize build database 3064 def InitDatabase(self): 3065 EdkLogger.verbose("\nInitialize build database started ...") 3066 3067 # 3068 # Create new tables 3069 # 3070 self.TblDataModel.Create(False) 3071 self.TblFile.Create(False) 3072 3073 # 3074 # Initialize table DataModel 3075 # 3076 self.TblDataModel.InitTable() 3077 EdkLogger.verbose("Initialize build database ... DONE!") 3078 3079 ## Query a table 3080 # 3081 # @param Table: The instance of the table to be queried 3082 # 3083 def QueryTable(self, Table): 3084 Table.Query() 3085 3086 def __del__(self): 3087 self.Close() 3088 3089 ## Close entire database 3090 # 3091 # Commit all first 3092 # Close the connection and cursor 3093 # 3094 def Close(self): 3095 if not self._DbClosedFlag: 3096 self.Conn.commit() 3097 self.Cur.close() 3098 self.Conn.close() 3099 self._DbClosedFlag = True 3100 3101 ## Summarize all packages in the database 3102 def GetPackageList(self, Platform, Arch, TargetName, ToolChainTag): 3103 self.Platform = Platform 3104 PackageList = [] 3105 Pa = self.BuildObject[self.Platform, 'COMMON'] 3106 # 3107 # Get Package related to Modules 3108 # 3109 for Module in Pa.Modules: 3110 ModuleObj = self.BuildObject[Module, Arch, TargetName, ToolChainTag] 3111 for Package in ModuleObj.Packages: 3112 if Package not in PackageList: 3113 PackageList.append(Package) 3114 # 3115 # Get Packages related to Libraries 3116 # 3117 for Lib in Pa.LibraryInstances: 3118 LibObj = self.BuildObject[Lib, Arch, TargetName, ToolChainTag] 3119 for Package in LibObj.Packages: 3120 if Package not in PackageList: 3121 PackageList.append(Package) 3122 3123 return PackageList 3124 3125 ## Summarize all platforms in the database 3126 def _GetPlatformList(self): 3127 PlatformList = [] 3128 for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC): 3129 try: 3130 Platform = self.BuildObject[PathClass(PlatformFile), 'COMMON'] 3131 except: 3132 Platform = None 3133 if Platform != None: 3134 PlatformList.append(Platform) 3135 return PlatformList 3136 3137 def _MapPlatform(self, Dscfile): 3138 Platform = self.BuildObject[PathClass(Dscfile), 'COMMON'] 3139 if Platform == None: 3140 EdkLogger.error('build', PARSER_ERROR, "Failed to parser DSC file: %s" % Dscfile) 3141 return Platform 3142 3143 PlatformList = property(_GetPlatformList) 3144 3145 ## 3146 # 3147 # This acts like the main() function for the script, unless it is 'import'ed into another 3148 # script. 3149 # 3150 if __name__ == '__main__': 3151 pass 3152 3153