1## @file 2# Global variables for GenFds 3# 4# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> 5# 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# 18import Common.LongFilePathOs as os 19import sys 20import subprocess 21import struct 22import array 23 24from Common.BuildToolError import * 25from Common import EdkLogger 26from Common.Misc import SaveFileOnChange 27 28from Common.TargetTxtClassObject import TargetTxtClassObject 29from Common.ToolDefClassObject import ToolDefClassObject 30from AutoGen.BuildEngine import BuildRule 31import Common.DataType as DataType 32from Common.Misc import PathClass 33from Common.LongFilePathSupport import OpenLongFilePath as open 34from Common.MultipleWorkspace import MultipleWorkspace as mws 35 36## Global variables 37# 38# 39class GenFdsGlobalVariable: 40 FvDir = '' 41 OutputDirDict = {} 42 BinDir = '' 43 # will be FvDir + os.sep + 'Ffs' 44 FfsDir = '' 45 FdfParser = None 46 LibDir = '' 47 WorkSpace = None 48 WorkSpaceDir = '' 49 ConfDir = '' 50 EdkSourceDir = '' 51 OutputDirFromDscDict = {} 52 TargetName = '' 53 ToolChainTag = '' 54 RuleDict = {} 55 ArchList = None 56 VtfDict = {} 57 ActivePlatform = None 58 FvAddressFileName = '' 59 VerboseMode = False 60 DebugLevel = -1 61 SharpCounter = 0 62 SharpNumberPerLine = 40 63 FdfFile = '' 64 FdfFileTimeStamp = 0 65 FixedLoadAddress = False 66 PlatformName = '' 67 68 BuildRuleFamily = "MSFT" 69 ToolChainFamily = "MSFT" 70 __BuildRuleDatabase = None 71 GuidToolDefinition = {} 72 73 # 74 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV. 75 # At the beginning of each generation of FV, false flag is appended to the list, 76 # after the call to GenerateSection returns, check the size of the output file, 77 # if it is greater than 0xFFFFFF, the tail flag in list is set to true, 78 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv. 79 # At the end of generation of FV, pop the flag. 80 # List is used as a stack to handle nested FV generation. 81 # 82 LargeFileInFvFlags = [] 83 EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A' 84 LARGE_FILE_SIZE = 0x1000000 85 86 SectionHeader = struct.Struct("3B 1B") 87 88 ## LoadBuildRule 89 # 90 @staticmethod 91 def __LoadBuildRule(): 92 if GenFdsGlobalVariable.__BuildRuleDatabase: 93 return GenFdsGlobalVariable.__BuildRuleDatabase 94 BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.ConfDir, "target.txt")) 95 TargetTxt = TargetTxtClassObject() 96 if os.path.isfile(BuildConfigurationFile) == True: 97 TargetTxt.LoadTargetTxtFile(BuildConfigurationFile) 98 if DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary: 99 BuildRuleFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF] 100 if BuildRuleFile in [None, '']: 101 BuildRuleFile = 'Conf/build_rule.txt' 102 GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule(BuildRuleFile) 103 ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF] 104 if ToolDefinitionFile == '': 105 ToolDefinitionFile = "Conf/tools_def.txt" 106 if os.path.isfile(ToolDefinitionFile): 107 ToolDef = ToolDefClassObject() 108 ToolDef.LoadToolDefFile(ToolDefinitionFile) 109 ToolDefinition = ToolDef.ToolsDefTxtDatabase 110 if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \ 111 and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \ 112 and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]: 113 GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag] 114 115 if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \ 116 and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \ 117 and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]: 118 GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag] 119 return GenFdsGlobalVariable.__BuildRuleDatabase 120 121 ## GetBuildRules 122 # @param Inf: object of InfBuildData 123 # @param Arch: current arch 124 # 125 @staticmethod 126 def GetBuildRules(Inf, Arch): 127 if not Arch: 128 Arch = 'COMMON' 129 130 if not Arch in GenFdsGlobalVariable.OutputDirDict: 131 return {} 132 133 BuildRuleDatabase = GenFdsGlobalVariable.__LoadBuildRule() 134 if not BuildRuleDatabase: 135 return {} 136 137 PathClassObj = PathClass(Inf.MetaFile.File, 138 GenFdsGlobalVariable.WorkSpaceDir) 139 Macro = {} 140 Macro["WORKSPACE" ] = GenFdsGlobalVariable.WorkSpaceDir 141 Macro["MODULE_NAME" ] = Inf.BaseName 142 Macro["MODULE_GUID" ] = Inf.Guid 143 Macro["MODULE_VERSION" ] = Inf.Version 144 Macro["MODULE_TYPE" ] = Inf.ModuleType 145 Macro["MODULE_FILE" ] = str(PathClassObj) 146 Macro["MODULE_FILE_BASE_NAME" ] = PathClassObj.BaseName 147 Macro["MODULE_RELATIVE_DIR" ] = PathClassObj.SubDir 148 Macro["MODULE_DIR" ] = PathClassObj.SubDir 149 150 Macro["BASE_NAME" ] = Inf.BaseName 151 152 Macro["ARCH" ] = Arch 153 Macro["TOOLCHAIN" ] = GenFdsGlobalVariable.ToolChainTag 154 Macro["TOOLCHAIN_TAG" ] = GenFdsGlobalVariable.ToolChainTag 155 Macro["TOOL_CHAIN_TAG" ] = GenFdsGlobalVariable.ToolChainTag 156 Macro["TARGET" ] = GenFdsGlobalVariable.TargetName 157 158 Macro["BUILD_DIR" ] = GenFdsGlobalVariable.OutputDirDict[Arch] 159 Macro["BIN_DIR" ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch) 160 Macro["LIB_DIR" ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch) 161 BuildDir = os.path.join( 162 GenFdsGlobalVariable.OutputDirDict[Arch], 163 Arch, 164 PathClassObj.SubDir, 165 PathClassObj.BaseName 166 ) 167 Macro["MODULE_BUILD_DIR" ] = BuildDir 168 Macro["OUTPUT_DIR" ] = os.path.join(BuildDir, "OUTPUT") 169 Macro["DEBUG_DIR" ] = os.path.join(BuildDir, "DEBUG") 170 171 BuildRules = {} 172 for Type in BuildRuleDatabase.FileTypeList: 173 #first try getting build rule by BuildRuleFamily 174 RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily] 175 if not RuleObject: 176 # build type is always module type, but ... 177 if Inf.ModuleType != Inf.BuildType: 178 RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily] 179 #second try getting build rule by ToolChainFamily 180 if not RuleObject: 181 RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily] 182 if not RuleObject: 183 # build type is always module type, but ... 184 if Inf.ModuleType != Inf.BuildType: 185 RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily] 186 if not RuleObject: 187 continue 188 RuleObject = RuleObject.Instantiate(Macro) 189 BuildRules[Type] = RuleObject 190 for Ext in RuleObject.SourceFileExtList: 191 BuildRules[Ext] = RuleObject 192 return BuildRules 193 194 ## GetModuleCodaTargetList 195 # 196 # @param Inf: object of InfBuildData 197 # @param Arch: current arch 198 # 199 @staticmethod 200 def GetModuleCodaTargetList(Inf, Arch): 201 BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch) 202 if not BuildRules: 203 return [] 204 205 TargetList = set() 206 FileList = [] 207 208 if not Inf.IsBinaryModule: 209 for File in Inf.Sources: 210 if File.TagName in ("", "*", GenFdsGlobalVariable.ToolChainTag) and \ 211 File.ToolChainFamily in ("", "*", GenFdsGlobalVariable.ToolChainFamily): 212 FileList.append((File, DataType.TAB_UNKNOWN_FILE)) 213 214 for File in Inf.Binaries: 215 if File.Target in ['COMMON', '*', GenFdsGlobalVariable.TargetName]: 216 FileList.append((File, File.Type)) 217 218 for File, FileType in FileList: 219 LastTarget = None 220 RuleChain = [] 221 SourceList = [File] 222 Index = 0 223 while Index < len(SourceList): 224 Source = SourceList[Index] 225 Index = Index + 1 226 227 if File.IsBinary and File == Source and Inf.Binaries != None and File in Inf.Binaries: 228 # Skip all files that are not binary libraries 229 if not Inf.LibraryClass: 230 continue 231 RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE] 232 elif FileType in BuildRules: 233 RuleObject = BuildRules[FileType] 234 elif Source.Ext in BuildRules: 235 RuleObject = BuildRules[Source.Ext] 236 else: 237 # stop at no more rules 238 if LastTarget: 239 TargetList.add(str(LastTarget)) 240 break 241 242 FileType = RuleObject.SourceFileType 243 244 # stop at STATIC_LIBRARY for library 245 if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY: 246 if LastTarget: 247 TargetList.add(str(LastTarget)) 248 break 249 250 Target = RuleObject.Apply(Source) 251 if not Target: 252 if LastTarget: 253 TargetList.add(str(LastTarget)) 254 break 255 elif not Target.Outputs: 256 # Only do build for target with outputs 257 TargetList.add(str(Target)) 258 259 # to avoid cyclic rule 260 if FileType in RuleChain: 261 break 262 263 RuleChain.append(FileType) 264 SourceList.extend(Target.Outputs) 265 LastTarget = Target 266 FileType = DataType.TAB_UNKNOWN_FILE 267 268 return list(TargetList) 269 270 ## SetDir() 271 # 272 # @param OutputDir Output directory 273 # @param FdfParser FDF contents parser 274 # @param Workspace The directory of workspace 275 # @param ArchList The Arch list of platform 276 # 277 def SetDir (OutputDir, FdfParser, WorkSpace, ArchList): 278 GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir :%s" % OutputDir) 279# GenFdsGlobalVariable.OutputDirDict = OutputDir 280 GenFdsGlobalVariable.FdfParser = FdfParser 281 GenFdsGlobalVariable.WorkSpace = WorkSpace 282 GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], 'FV') 283 if not os.path.exists(GenFdsGlobalVariable.FvDir) : 284 os.makedirs(GenFdsGlobalVariable.FvDir) 285 GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs') 286 if not os.path.exists(GenFdsGlobalVariable.FfsDir) : 287 os.makedirs(GenFdsGlobalVariable.FfsDir) 288 289 T_CHAR_LF = '\n' 290 # 291 # Create FV Address inf file 292 # 293 GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf') 294 FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w') 295 # 296 # Add [Options] 297 # 298 FvAddressFile.writelines("[options]" + T_CHAR_LF) 299 BsAddress = '0' 300 for Arch in ArchList: 301 if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress: 302 BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress 303 break 304 305 FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \ 306 BsAddress + \ 307 T_CHAR_LF) 308 309 RtAddress = '0' 310 for Arch in ArchList: 311 if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress: 312 RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress 313 314 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ 315 RtAddress + \ 316 T_CHAR_LF) 317 318 FvAddressFile.close() 319 320 ## ReplaceWorkspaceMacro() 321 # 322 # @param String String that may contain macro 323 # 324 def ReplaceWorkspaceMacro(String): 325 String = mws.handleWsMacro(String) 326 Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir) 327 if os.path.exists(Str): 328 if not os.path.isabs(Str): 329 Str = os.path.abspath(Str) 330 else: 331 Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String) 332 return os.path.normpath(Str) 333 334 ## Check if the input files are newer than output files 335 # 336 # @param Output Path of output file 337 # @param Input Path list of input files 338 # 339 # @retval True if Output doesn't exist, or any Input is newer 340 # @retval False if all Input is older than Output 341 # 342 @staticmethod 343 def NeedsUpdate(Output, Input): 344 if not os.path.exists(Output): 345 return True 346 # always update "Output" if no "Input" given 347 if Input == None or len(Input) == 0: 348 return True 349 350 # if fdf file is changed after the 'Output" is generated, update the 'Output' 351 OutputTime = os.path.getmtime(Output) 352 if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime: 353 return True 354 355 for F in Input: 356 # always update "Output" if any "Input" doesn't exist 357 if not os.path.exists(F): 358 return True 359 # always update "Output" if any "Input" is newer than "Output" 360 if os.path.getmtime(F) > OutputTime: 361 return True 362 return False 363 364 @staticmethod 365 def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None, 366 GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=None, BuildNumber=None): 367 Cmd = ["GenSec"] 368 if Type not in [None, '']: 369 Cmd += ["-s", Type] 370 if CompressionType not in [None, '']: 371 Cmd += ["-c", CompressionType] 372 if Guid != None: 373 Cmd += ["-g", Guid] 374 if GuidHdrLen not in [None, '']: 375 Cmd += ["-l", GuidHdrLen] 376 if len(GuidAttr) != 0: 377 #Add each guided attribute 378 for Attr in GuidAttr: 379 Cmd += ["-r", Attr] 380 if InputAlign != None: 381 #Section Align is only for dummy section without section type 382 for SecAlign in InputAlign: 383 Cmd += ["--sectionalign", SecAlign] 384 385 CommandFile = Output + '.txt' 386 if Ui not in [None, '']: 387 #Cmd += ["-n", '"' + Ui + '"'] 388 SectionData = array.array('B', [0, 0, 0, 0]) 389 SectionData.fromstring(Ui.encode("utf_16_le")) 390 SectionData.append(0) 391 SectionData.append(0) 392 Len = len(SectionData) 393 GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15) 394 SaveFileOnChange(Output, SectionData.tostring()) 395 elif Ver not in [None, '']: 396 Cmd += ["-n", Ver] 397 if BuildNumber: 398 Cmd += ["-j", BuildNumber] 399 Cmd += ["-o", Output] 400 401 SaveFileOnChange(CommandFile, ' '.join(Cmd), False) 402 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): 403 return 404 405 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") 406 else: 407 Cmd += ["-o", Output] 408 Cmd += Input 409 410 SaveFileOnChange(CommandFile, ' '.join(Cmd), False) 411 if GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): 412 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 413 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") 414 415 if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and 416 GenFdsGlobalVariable.LargeFileInFvFlags): 417 GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True 418 419 @staticmethod 420 def GetAlignment (AlignString): 421 if AlignString == None: 422 return 0 423 if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K"): 424 return int (AlignString.rstrip('K')) * 1024 425 else: 426 return int (AlignString) 427 428 @staticmethod 429 def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None, 430 SectionAlign=None): 431 Cmd = ["GenFfs", "-t", Type, "-g", Guid] 432 mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K"] 433 if Fixed == True: 434 Cmd += ["-x"] 435 if CheckSum: 436 Cmd += ["-s"] 437 if Align not in [None, '']: 438 if Align not in mFfsValidAlign: 439 Align = GenFdsGlobalVariable.GetAlignment (Align) 440 for index in range(0, len(mFfsValidAlign) - 1): 441 if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))): 442 break 443 Align = mFfsValidAlign[index + 1] 444 Cmd += ["-a", Align] 445 446 Cmd += ["-o", Output] 447 for I in range(0, len(Input)): 448 Cmd += ("-i", Input[I]) 449 if SectionAlign not in [None, '', []] and SectionAlign[I] not in [None, '']: 450 Cmd += ("-n", SectionAlign[I]) 451 452 CommandFile = Output + '.txt' 453 SaveFileOnChange(CommandFile, ' '.join(Cmd), False) 454 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): 455 return 456 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 457 458 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS") 459 460 @staticmethod 461 def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False, 462 AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None): 463 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList): 464 return 465 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 466 467 Cmd = ["GenFv"] 468 if BaseAddress not in [None, '']: 469 Cmd += ["-r", BaseAddress] 470 471 if ForceRebase == False: 472 Cmd += ["-F", "FALSE"] 473 elif ForceRebase == True: 474 Cmd += ["-F", "TRUE"] 475 476 if Capsule: 477 Cmd += ["-c"] 478 if Dump: 479 Cmd += ["-p"] 480 if AddressFile not in [None, '']: 481 Cmd += ["-a", AddressFile] 482 if MapFile not in [None, '']: 483 Cmd += ["-m", MapFile] 484 if FileSystemGuid: 485 Cmd += ["-g", FileSystemGuid] 486 Cmd += ["-o", Output] 487 for I in Input: 488 Cmd += ["-i", I] 489 490 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV") 491 492 @staticmethod 493 def GenerateVtf(Output, Input, BaseAddress=None, FvSize=None): 494 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): 495 return 496 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 497 498 Cmd = ["GenVtf"] 499 if BaseAddress not in [None, ''] and FvSize not in [None, ''] \ 500 and len(BaseAddress) == len(FvSize): 501 for I in range(0, len(BaseAddress)): 502 Cmd += ["-r", BaseAddress[I], "-s", FvSize[I]] 503 Cmd += ["-o", Output] 504 for F in Input: 505 Cmd += ["-f", F] 506 507 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF") 508 509 @staticmethod 510 def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False, 511 Strip=False, Replace=False, TimeStamp=None, Join=False, 512 Align=None, Padding=None, Convert=False): 513 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): 514 return 515 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 516 517 Cmd = ["GenFw"] 518 if Type.lower() == "te": 519 Cmd += ["-t"] 520 if SubType not in [None, '']: 521 Cmd += ["-e", SubType] 522 if TimeStamp not in [None, '']: 523 Cmd += ["-s", TimeStamp] 524 if Align not in [None, '']: 525 Cmd += ["-a", Align] 526 if Padding not in [None, '']: 527 Cmd += ["-p", Padding] 528 if Zero: 529 Cmd += ["-z"] 530 if Strip: 531 Cmd += ["-l"] 532 if Replace: 533 Cmd += ["-r"] 534 if Join: 535 Cmd += ["-j"] 536 if Convert: 537 Cmd += ["-m"] 538 Cmd += ["-o", Output] 539 Cmd += Input 540 541 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image") 542 543 @staticmethod 544 def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None, 545 Revision=None, DeviceId=None, VendorId=None): 546 InputList = [] 547 Cmd = ["EfiRom"] 548 if len(EfiInput) > 0: 549 550 if Compress: 551 Cmd += ["-ec"] 552 else: 553 Cmd += ["-e"] 554 555 for EfiFile in EfiInput: 556 Cmd += [EfiFile] 557 InputList.append (EfiFile) 558 559 if len(BinaryInput) > 0: 560 Cmd += ["-b"] 561 for BinFile in BinaryInput: 562 Cmd += [BinFile] 563 InputList.append (BinFile) 564 565 # Check List 566 if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList): 567 return 568 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList)) 569 570 if ClassCode != None: 571 Cmd += ["-l", ClassCode] 572 if Revision != None: 573 Cmd += ["-r", Revision] 574 if DeviceId != None: 575 Cmd += ["-i", DeviceId] 576 if VendorId != None: 577 Cmd += ["-f", VendorId] 578 579 Cmd += ["-o", Output] 580 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom") 581 582 @staticmethod 583 def GuidTool(Output, Input, ToolPath, Options='', returnValue=[]): 584 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): 585 return 586 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 587 588 Cmd = [ToolPath, ] 589 Cmd += Options.split(' ') 590 Cmd += ["-o", Output] 591 Cmd += Input 592 593 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue) 594 595 def CallExternalTool (cmd, errorMess, returnValue=[]): 596 597 if type(cmd) not in (tuple, list): 598 GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool") 599 600 if GenFdsGlobalVariable.DebugLevel != -1: 601 cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel)) 602 GenFdsGlobalVariable.InfLogger (cmd) 603 604 if GenFdsGlobalVariable.VerboseMode: 605 cmd += ('-v',) 606 GenFdsGlobalVariable.InfLogger (cmd) 607 else: 608 sys.stdout.write ('#') 609 sys.stdout.flush() 610 GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1 611 if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0: 612 sys.stdout.write('\n') 613 614 try: 615 PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 616 except Exception, X: 617 EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0])) 618 (out, error) = PopenObject.communicate() 619 620 while PopenObject.returncode == None : 621 PopenObject.wait() 622 if returnValue != [] and returnValue[0] != 0: 623 #get command return value 624 returnValue[0] = PopenObject.returncode 625 return 626 if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1: 627 GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode) 628 GenFdsGlobalVariable.InfLogger (out) 629 GenFdsGlobalVariable.InfLogger (error) 630 if PopenObject.returncode != 0: 631 print "###", cmd 632 EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess) 633 634 def VerboseLogger (msg): 635 EdkLogger.verbose(msg) 636 637 def InfLogger (msg): 638 EdkLogger.info(msg) 639 640 def ErrorLogger (msg, File=None, Line=None, ExtraData=None): 641 EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData) 642 643 def DebugLogger (Level, msg): 644 EdkLogger.debug(Level, msg) 645 646 ## ReplaceWorkspaceMacro() 647 # 648 # @param Str String that may contain macro 649 # @param MacroDict Dictionary that contains macro value pair 650 # 651 def MacroExtend (Str, MacroDict={}, Arch='COMMON'): 652 if Str == None : 653 return None 654 655 Dict = {'$(WORKSPACE)' : GenFdsGlobalVariable.WorkSpaceDir, 656 '$(EDK_SOURCE)' : GenFdsGlobalVariable.EdkSourceDir, 657# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc, 658 '$(TARGET)' : GenFdsGlobalVariable.TargetName, 659 '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag, 660 '$(SPACE)' : ' ' 661 } 662 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]] 663 if Arch != 'COMMON' and Arch in GenFdsGlobalVariable.ArchList: 664 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch] 665 666 Dict['$(OUTPUT_DIRECTORY)'] = OutputDir 667 668 if MacroDict != None and len (MacroDict) != 0: 669 Dict.update(MacroDict) 670 671 for key in Dict.keys(): 672 if Str.find(key) >= 0 : 673 Str = Str.replace (key, Dict[key]) 674 675 if Str.find('$(ARCH)') >= 0: 676 if len(GenFdsGlobalVariable.ArchList) == 1: 677 Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0]) 678 else: 679 EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str) 680 681 return Str 682 683 ## GetPcdValue() 684 # 685 # @param PcdPattern pattern that labels a PCD. 686 # 687 def GetPcdValue (PcdPattern): 688 if PcdPattern == None : 689 return None 690 PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.') 691 TokenSpace = PcdPair[0] 692 TokenCName = PcdPair[1] 693 694 PcdValue = '' 695 for Arch in GenFdsGlobalVariable.ArchList: 696 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 697 PcdDict = Platform.Pcds 698 for Key in PcdDict: 699 PcdObj = PcdDict[Key] 700 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): 701 if PcdObj.Type != 'FixedAtBuild': 702 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) 703 if PcdObj.DatumType != 'VOID*': 704 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) 705 706 PcdValue = PcdObj.DefaultValue 707 return PcdValue 708 709 for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, 710 Arch, 711 GenFdsGlobalVariable.TargetName, 712 GenFdsGlobalVariable.ToolChainTag): 713 PcdDict = Package.Pcds 714 for Key in PcdDict: 715 PcdObj = PcdDict[Key] 716 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): 717 if PcdObj.Type != 'FixedAtBuild': 718 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) 719 if PcdObj.DatumType != 'VOID*': 720 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) 721 722 PcdValue = PcdObj.DefaultValue 723 return PcdValue 724 725 return PcdValue 726 727 SetDir = staticmethod(SetDir) 728 ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro) 729 CallExternalTool = staticmethod(CallExternalTool) 730 VerboseLogger = staticmethod(VerboseLogger) 731 InfLogger = staticmethod(InfLogger) 732 ErrorLogger = staticmethod(ErrorLogger) 733 DebugLogger = staticmethod(DebugLogger) 734 MacroExtend = staticmethod (MacroExtend) 735 GetPcdValue = staticmethod(GetPcdValue) 736