1## @file 2# Global variables for GenFds 3# 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8 9## 10# Import Modules 11# 12from __future__ import print_function 13from __future__ import absolute_import 14 15import Common.LongFilePathOs as os 16import sys 17from sys import stdout 18from subprocess import PIPE,Popen 19from struct import Struct 20from array import array 21 22from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR 23from Common import EdkLogger 24from Common.Misc import SaveFileOnChange 25 26from Common.TargetTxtClassObject import TargetTxtDict 27from Common.ToolDefClassObject import ToolDefDict 28from AutoGen.BuildEngine import ToolBuildRule 29import Common.DataType as DataType 30from Common.Misc import PathClass 31from Common.LongFilePathSupport import OpenLongFilePath as open 32from Common.MultipleWorkspace import MultipleWorkspace as mws 33import Common.GlobalData as GlobalData 34 35## Global variables 36# 37# 38class GenFdsGlobalVariable: 39 FvDir = '' 40 OutputDirDict = {} 41 BinDir = '' 42 # will be FvDir + os.sep + 'Ffs' 43 FfsDir = '' 44 FdfParser = None 45 LibDir = '' 46 WorkSpace = None 47 WorkSpaceDir = '' 48 ConfDir = '' 49 OutputDirFromDscDict = {} 50 TargetName = '' 51 ToolChainTag = '' 52 RuleDict = {} 53 ArchList = None 54 ActivePlatform = None 55 FvAddressFileName = '' 56 VerboseMode = False 57 DebugLevel = -1 58 SharpCounter = 0 59 SharpNumberPerLine = 40 60 FdfFile = '' 61 FdfFileTimeStamp = 0 62 FixedLoadAddress = False 63 PlatformName = '' 64 65 BuildRuleFamily = DataType.TAB_COMPILER_MSFT 66 ToolChainFamily = DataType.TAB_COMPILER_MSFT 67 __BuildRuleDatabase = None 68 GuidToolDefinition = {} 69 FfsCmdDict = {} 70 SecCmdList = [] 71 CopyList = [] 72 ModuleFile = '' 73 EnableGenfdsMultiThread = True 74 75 # 76 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV. 77 # At the beginning of each generation of FV, false flag is appended to the list, 78 # after the call to GenerateSection returns, check the size of the output file, 79 # if it is greater than 0xFFFFFF, the tail flag in list is set to true, 80 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv. 81 # At the end of generation of FV, pop the flag. 82 # List is used as a stack to handle nested FV generation. 83 # 84 LargeFileInFvFlags = [] 85 EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A' 86 LARGE_FILE_SIZE = 0x1000000 87 88 SectionHeader = Struct("3B 1B") 89 90 # FvName, FdName, CapName in FDF, Image file name 91 ImageBinDict = {} 92 93 ## LoadBuildRule 94 # 95 @staticmethod 96 def _LoadBuildRule(): 97 if GenFdsGlobalVariable.__BuildRuleDatabase: 98 return GenFdsGlobalVariable.__BuildRuleDatabase 99 BuildRule = ToolBuildRule() 100 GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule.ToolBuildRule 101 TargetObj = TargetTxtDict() 102 ToolDefinitionFile = TargetObj.Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF] 103 if ToolDefinitionFile == '': 104 ToolDefinitionFile = "Conf/tools_def.txt" 105 if os.path.isfile(ToolDefinitionFile): 106 ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf"))) 107 ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase 108 if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \ 109 and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \ 110 and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]: 111 GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag] 112 113 if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \ 114 and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \ 115 and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]: 116 GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag] 117 return GenFdsGlobalVariable.__BuildRuleDatabase 118 119 ## GetBuildRules 120 # @param Inf: object of InfBuildData 121 # @param Arch: current arch 122 # 123 @staticmethod 124 def GetBuildRules(Inf, Arch): 125 if not Arch: 126 Arch = DataType.TAB_COMMON 127 128 if not Arch in GenFdsGlobalVariable.OutputDirDict: 129 return {} 130 131 BuildRuleDatabase = GenFdsGlobalVariable._LoadBuildRule() 132 if not BuildRuleDatabase: 133 return {} 134 135 PathClassObj = PathClass(Inf.MetaFile.File, 136 GenFdsGlobalVariable.WorkSpaceDir) 137 BuildDir = os.path.join( 138 GenFdsGlobalVariable.OutputDirDict[Arch], 139 Arch, 140 PathClassObj.SubDir, 141 PathClassObj.BaseName 142 ) 143 BinDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch) 144 Macro = { 145 "WORKSPACE":GenFdsGlobalVariable.WorkSpaceDir, 146 "MODULE_NAME":Inf.BaseName, 147 "MODULE_GUID":Inf.Guid, 148 "MODULE_VERSION":Inf.Version, 149 "MODULE_TYPE":Inf.ModuleType, 150 "MODULE_FILE":str(PathClassObj), 151 "MODULE_FILE_BASE_NAME":PathClassObj.BaseName, 152 "MODULE_RELATIVE_DIR":PathClassObj.SubDir, 153 "MODULE_DIR":PathClassObj.SubDir, 154 "BASE_NAME":Inf.BaseName, 155 "ARCH":Arch, 156 "TOOLCHAIN":GenFdsGlobalVariable.ToolChainTag, 157 "TOOLCHAIN_TAG":GenFdsGlobalVariable.ToolChainTag, 158 "TOOL_CHAIN_TAG":GenFdsGlobalVariable.ToolChainTag, 159 "TARGET":GenFdsGlobalVariable.TargetName, 160 "BUILD_DIR":GenFdsGlobalVariable.OutputDirDict[Arch], 161 "BIN_DIR":BinDir, 162 "LIB_DIR":BinDir, 163 "MODULE_BUILD_DIR":BuildDir, 164 "OUTPUT_DIR":os.path.join(BuildDir, "OUTPUT"), 165 "DEBUG_DIR":os.path.join(BuildDir, "DEBUG") 166 } 167 168 BuildRules = {} 169 for Type in BuildRuleDatabase.FileTypeList: 170 #first try getting build rule by BuildRuleFamily 171 RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily] 172 if not RuleObject: 173 # build type is always module type, but ... 174 if Inf.ModuleType != Inf.BuildType: 175 RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily] 176 #second try getting build rule by ToolChainFamily 177 if not RuleObject: 178 RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily] 179 if not RuleObject: 180 # build type is always module type, but ... 181 if Inf.ModuleType != Inf.BuildType: 182 RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily] 183 if not RuleObject: 184 continue 185 RuleObject = RuleObject.Instantiate(Macro) 186 BuildRules[Type] = RuleObject 187 for Ext in RuleObject.SourceFileExtList: 188 BuildRules[Ext] = RuleObject 189 return BuildRules 190 191 ## GetModuleCodaTargetList 192 # 193 # @param Inf: object of InfBuildData 194 # @param Arch: current arch 195 # 196 @staticmethod 197 def GetModuleCodaTargetList(Inf, Arch): 198 BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch) 199 if not BuildRules: 200 return [] 201 202 TargetList = set() 203 FileList = [] 204 205 if not Inf.IsBinaryModule: 206 for File in Inf.Sources: 207 if File.TagName in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainTag} and \ 208 File.ToolChainFamily in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainFamily}: 209 FileList.append((File, DataType.TAB_UNKNOWN_FILE)) 210 211 for File in Inf.Binaries: 212 if File.Target in {DataType.TAB_COMMON, DataType.TAB_STAR, GenFdsGlobalVariable.TargetName}: 213 FileList.append((File, File.Type)) 214 215 for File, FileType in FileList: 216 LastTarget = None 217 RuleChain = [] 218 SourceList = [File] 219 Index = 0 220 while Index < len(SourceList): 221 Source = SourceList[Index] 222 Index = Index + 1 223 224 if File.IsBinary and File == Source and Inf.Binaries and File in Inf.Binaries: 225 # Skip all files that are not binary libraries 226 if not Inf.LibraryClass: 227 continue 228 RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE] 229 elif FileType in BuildRules: 230 RuleObject = BuildRules[FileType] 231 elif Source.Ext in BuildRules: 232 RuleObject = BuildRules[Source.Ext] 233 else: 234 # stop at no more rules 235 if LastTarget: 236 TargetList.add(str(LastTarget)) 237 break 238 239 FileType = RuleObject.SourceFileType 240 241 # stop at STATIC_LIBRARY for library 242 if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY: 243 if LastTarget: 244 TargetList.add(str(LastTarget)) 245 break 246 247 Target = RuleObject.Apply(Source) 248 if not Target: 249 if LastTarget: 250 TargetList.add(str(LastTarget)) 251 break 252 elif not Target.Outputs: 253 # Only do build for target with outputs 254 TargetList.add(str(Target)) 255 256 # to avoid cyclic rule 257 if FileType in RuleChain: 258 break 259 260 RuleChain.append(FileType) 261 SourceList.extend(Target.Outputs) 262 LastTarget = Target 263 FileType = DataType.TAB_UNKNOWN_FILE 264 for Cmd in Target.Commands: 265 if "$(CP)" == Cmd.split()[0]: 266 CpTarget = Cmd.split()[2] 267 TargetList.add(CpTarget) 268 269 return list(TargetList) 270 271 ## SetDir() 272 # 273 # @param OutputDir Output directory 274 # @param FdfParser FDF contents parser 275 # @param Workspace The directory of workspace 276 # @param ArchList The Arch list of platform 277 # 278 @staticmethod 279 def SetDir (OutputDir, FdfParser, WorkSpace, ArchList): 280 GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir) 281 GenFdsGlobalVariable.FdfParser = FdfParser 282 GenFdsGlobalVariable.WorkSpace = WorkSpace 283 GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY) 284 if not os.path.exists(GenFdsGlobalVariable.FvDir): 285 os.makedirs(GenFdsGlobalVariable.FvDir) 286 GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs') 287 if not os.path.exists(GenFdsGlobalVariable.FfsDir): 288 os.makedirs(GenFdsGlobalVariable.FfsDir) 289 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]" + DataType.TAB_LINE_BREAK) 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 DataType.TAB_LINE_BREAK) 308 309 RtAddress = '0' 310 for Arch in reversed(ArchList): 311 temp = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress 312 if temp: 313 RtAddress = temp 314 break 315 316 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ 317 RtAddress + \ 318 DataType.TAB_LINE_BREAK) 319 320 FvAddressFile.close() 321 322 @staticmethod 323 def SetEnv(FdfParser, WorkSpace, ArchList, GlobalData): 324 GenFdsGlobalVariable.ModuleFile = WorkSpace.ModuleFile 325 GenFdsGlobalVariable.FdfParser = FdfParser 326 GenFdsGlobalVariable.WorkSpace = WorkSpace.Db 327 GenFdsGlobalVariable.ArchList = ArchList 328 GenFdsGlobalVariable.ToolChainTag = GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"] 329 GenFdsGlobalVariable.TargetName = GlobalData.gGlobalDefines["TARGET"] 330 GenFdsGlobalVariable.ActivePlatform = GlobalData.gActivePlatform 331 GenFdsGlobalVariable.ConfDir = GlobalData.gConfDirectory 332 GenFdsGlobalVariable.EnableGenfdsMultiThread = GlobalData.gEnableGenfdsMultiThread 333 for Arch in ArchList: 334 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.normpath( 335 os.path.join(GlobalData.gWorkspace, 336 WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'], 337 GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory, 338 GlobalData.gGlobalDefines['TARGET'] +'_' + GlobalData.gGlobalDefines['TOOLCHAIN'])) 339 GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = os.path.normpath( 340 WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, 341 GlobalData.gGlobalDefines['TARGET'], GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory) 342 GenFdsGlobalVariable.PlatformName = WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, 343 GlobalData.gGlobalDefines['TARGET'], 344 GlobalData.gGlobalDefines['TOOLCHAIN']].PlatformName 345 GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY) 346 if not os.path.exists(GenFdsGlobalVariable.FvDir): 347 os.makedirs(GenFdsGlobalVariable.FvDir) 348 GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs') 349 if not os.path.exists(GenFdsGlobalVariable.FfsDir): 350 os.makedirs(GenFdsGlobalVariable.FfsDir) 351 352 # 353 # Create FV Address inf file 354 # 355 GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf') 356 FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w') 357 # 358 # Add [Options] 359 # 360 FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK) 361 BsAddress = '0' 362 for Arch in ArchList: 363 BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, 364 GlobalData.gGlobalDefines['TARGET'], 365 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].BsBaseAddress 366 if BsAddress: 367 break 368 369 FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \ 370 BsAddress + \ 371 DataType.TAB_LINE_BREAK) 372 373 RtAddress = '0' 374 for Arch in reversed(ArchList): 375 temp = GenFdsGlobalVariable.WorkSpace.BuildObject[ 376 GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'], 377 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress 378 if temp: 379 RtAddress = temp 380 break 381 382 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ 383 RtAddress + \ 384 DataType.TAB_LINE_BREAK) 385 386 FvAddressFile.close() 387 388 ## ReplaceWorkspaceMacro() 389 # 390 # @param String String that may contain macro 391 # 392 @staticmethod 393 def ReplaceWorkspaceMacro(String): 394 String = mws.handleWsMacro(String) 395 Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir) 396 if os.path.exists(Str): 397 if not os.path.isabs(Str): 398 Str = os.path.abspath(Str) 399 else: 400 Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String) 401 return os.path.normpath(Str) 402 403 ## Check if the input files are newer than output files 404 # 405 # @param Output Path of output file 406 # @param Input Path list of input files 407 # 408 # @retval True if Output doesn't exist, or any Input is newer 409 # @retval False if all Input is older than Output 410 # 411 @staticmethod 412 def NeedsUpdate(Output, Input): 413 if not os.path.exists(Output): 414 return True 415 # always update "Output" if no "Input" given 416 if not Input: 417 return True 418 419 # if fdf file is changed after the 'Output" is generated, update the 'Output' 420 OutputTime = os.path.getmtime(Output) 421 if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime: 422 return True 423 424 for F in Input: 425 # always update "Output" if any "Input" doesn't exist 426 if not os.path.exists(F): 427 return True 428 # always update "Output" if any "Input" is newer than "Output" 429 if os.path.getmtime(F) > OutputTime: 430 return True 431 return False 432 433 @staticmethod 434 def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None, 435 GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=[], BuildNumber=None, DummyFile=None, IsMakefile=False): 436 Cmd = ["GenSec"] 437 if Type: 438 Cmd += ("-s", Type) 439 if CompressionType: 440 Cmd += ("-c", CompressionType) 441 if Guid: 442 Cmd += ("-g", Guid) 443 if DummyFile: 444 Cmd += ("--dummy", DummyFile) 445 if GuidHdrLen: 446 Cmd += ("-l", GuidHdrLen) 447 #Add each guided attribute 448 for Attr in GuidAttr: 449 Cmd += ("-r", Attr) 450 #Section Align is only for dummy section without section type 451 for SecAlign in InputAlign: 452 Cmd += ("--sectionalign", SecAlign) 453 454 CommandFile = Output + '.txt' 455 if Ui: 456 if IsMakefile: 457 if Ui == "$(MODULE_NAME)": 458 Cmd += ('-n', Ui) 459 else: 460 Cmd += ("-n", '"' + Ui + '"') 461 Cmd += ("-o", Output) 462 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: 463 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip()) 464 else: 465 SectionData = array('B', [0, 0, 0, 0]) 466 SectionData.fromstring(Ui.encode("utf_16_le")) 467 SectionData.append(0) 468 SectionData.append(0) 469 Len = len(SectionData) 470 GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15) 471 SaveFileOnChange(Output, SectionData.tostring()) 472 473 elif Ver: 474 Cmd += ("-n", Ver) 475 if BuildNumber: 476 Cmd += ("-j", BuildNumber) 477 Cmd += ("-o", Output) 478 479 SaveFileOnChange(CommandFile, ' '.join(Cmd), False) 480 if IsMakefile: 481 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: 482 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip()) 483 else: 484 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): 485 return 486 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") 487 else: 488 Cmd += ("-o", Output) 489 Cmd += Input 490 491 SaveFileOnChange(CommandFile, ' '.join(Cmd), False) 492 if IsMakefile: 493 if sys.platform == "win32": 494 Cmd = ['if', 'exist', Input[0]] + Cmd 495 else: 496 Cmd = ['-test', '-e', Input[0], "&&"] + Cmd 497 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: 498 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip()) 499 elif GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): 500 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 501 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") 502 if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and 503 GenFdsGlobalVariable.LargeFileInFvFlags): 504 GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True 505 506 @staticmethod 507 def GetAlignment (AlignString): 508 if not AlignString: 509 return 0 510 if AlignString.endswith('K'): 511 return int (AlignString.rstrip('K')) * 1024 512 if AlignString.endswith('M'): 513 return int (AlignString.rstrip('M')) * 1024 * 1024 514 if AlignString.endswith('G'): 515 return int (AlignString.rstrip('G')) * 1024 * 1024 * 1024 516 return int (AlignString) 517 518 @staticmethod 519 def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None, 520 SectionAlign=None, MakefilePath=None): 521 Cmd = ["GenFfs", "-t", Type, "-g", Guid] 522 mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"] 523 if Fixed == True: 524 Cmd.append("-x") 525 if CheckSum: 526 Cmd.append("-s") 527 if Align: 528 if Align not in mFfsValidAlign: 529 Align = GenFdsGlobalVariable.GetAlignment (Align) 530 for index in range(0, len(mFfsValidAlign) - 1): 531 if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))): 532 break 533 Align = mFfsValidAlign[index + 1] 534 Cmd += ("-a", Align) 535 536 Cmd += ("-o", Output) 537 for I in range(0, len(Input)): 538 if MakefilePath: 539 Cmd += ("-oi", Input[I]) 540 else: 541 Cmd += ("-i", Input[I]) 542 if SectionAlign and SectionAlign[I]: 543 Cmd += ("-n", SectionAlign[I]) 544 545 CommandFile = Output + '.txt' 546 SaveFileOnChange(CommandFile, ' '.join(Cmd), False) 547 548 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 549 if MakefilePath: 550 if (tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict: 551 GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath 552 GenFdsGlobalVariable.SecCmdList = [] 553 GenFdsGlobalVariable.CopyList = [] 554 else: 555 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): 556 return 557 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS") 558 559 @staticmethod 560 def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False, 561 AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None): 562 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList): 563 return 564 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 565 566 Cmd = ["GenFv"] 567 if BaseAddress: 568 Cmd += ("-r", BaseAddress) 569 570 if ForceRebase == False: 571 Cmd += ("-F", "FALSE") 572 elif ForceRebase == True: 573 Cmd += ("-F", "TRUE") 574 575 if Capsule: 576 Cmd.append("-c") 577 if Dump: 578 Cmd.append("-p") 579 if AddressFile: 580 Cmd += ("-a", AddressFile) 581 if MapFile: 582 Cmd += ("-m", MapFile) 583 if FileSystemGuid: 584 Cmd += ("-g", FileSystemGuid) 585 Cmd += ("-o", Output) 586 for I in Input: 587 Cmd += ("-i", I) 588 589 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV") 590 591 @staticmethod 592 def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False, 593 Strip=False, Replace=False, TimeStamp=None, Join=False, 594 Align=None, Padding=None, Convert=False, IsMakefile=False): 595 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile: 596 return 597 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 598 599 Cmd = ["GenFw"] 600 if Type.lower() == "te": 601 Cmd.append("-t") 602 if SubType: 603 Cmd += ("-e", SubType) 604 if TimeStamp: 605 Cmd += ("-s", TimeStamp) 606 if Align: 607 Cmd += ("-a", Align) 608 if Padding: 609 Cmd += ("-p", Padding) 610 if Zero: 611 Cmd.append("-z") 612 if Strip: 613 Cmd.append("-l") 614 if Replace: 615 Cmd.append("-r") 616 if Join: 617 Cmd.append("-j") 618 if Convert: 619 Cmd.append("-m") 620 Cmd += ("-o", Output) 621 Cmd += Input 622 if IsMakefile: 623 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: 624 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip()) 625 else: 626 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image") 627 628 @staticmethod 629 def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None, 630 Revision=None, DeviceId=None, VendorId=None, IsMakefile=False): 631 InputList = [] 632 Cmd = ["EfiRom"] 633 if EfiInput: 634 635 if Compress: 636 Cmd.append("-ec") 637 else: 638 Cmd.append("-e") 639 640 for EfiFile in EfiInput: 641 Cmd.append(EfiFile) 642 InputList.append (EfiFile) 643 644 if BinaryInput: 645 Cmd.append("-b") 646 for BinFile in BinaryInput: 647 Cmd.append(BinFile) 648 InputList.append (BinFile) 649 650 # Check List 651 if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile: 652 return 653 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList)) 654 655 if ClassCode: 656 Cmd += ("-l", ClassCode) 657 if Revision: 658 Cmd += ("-r", Revision) 659 if DeviceId: 660 Cmd += ("-i", DeviceId) 661 if VendorId: 662 Cmd += ("-f", VendorId) 663 664 Cmd += ("-o", Output) 665 if IsMakefile: 666 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: 667 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip()) 668 else: 669 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom") 670 671 @staticmethod 672 def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False): 673 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile: 674 return 675 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) 676 677 Cmd = [ToolPath, ] 678 Cmd += Options.split(' ') 679 Cmd += ("-o", Output) 680 Cmd += Input 681 if IsMakefile: 682 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: 683 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip()) 684 else: 685 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue) 686 687 @staticmethod 688 def CallExternalTool (cmd, errorMess, returnValue=[]): 689 690 if type(cmd) not in (tuple, list): 691 GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool") 692 693 if GenFdsGlobalVariable.DebugLevel != -1: 694 cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel)) 695 GenFdsGlobalVariable.InfLogger (cmd) 696 697 if GenFdsGlobalVariable.VerboseMode: 698 cmd += ('-v',) 699 GenFdsGlobalVariable.InfLogger (cmd) 700 else: 701 stdout.write ('#') 702 stdout.flush() 703 GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1 704 if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0: 705 stdout.write('\n') 706 707 try: 708 PopenObject = Popen(' '.join(cmd), stdout=PIPE, stderr=PIPE, shell=True) 709 except Exception as X: 710 EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0])) 711 (out, error) = PopenObject.communicate() 712 713 while PopenObject.returncode is None: 714 PopenObject.wait() 715 if returnValue != [] and returnValue[0] != 0: 716 #get command return value 717 returnValue[0] = PopenObject.returncode 718 return 719 if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1: 720 GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode) 721 GenFdsGlobalVariable.InfLogger(out.decode(encoding='utf-8', errors='ignore')) 722 GenFdsGlobalVariable.InfLogger(error.decode(encoding='utf-8', errors='ignore')) 723 if PopenObject.returncode != 0: 724 print("###", cmd) 725 EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess) 726 727 @staticmethod 728 def VerboseLogger (msg): 729 EdkLogger.verbose(msg) 730 731 @staticmethod 732 def InfLogger (msg): 733 EdkLogger.info(msg) 734 735 @staticmethod 736 def ErrorLogger (msg, File=None, Line=None, ExtraData=None): 737 EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData) 738 739 @staticmethod 740 def DebugLogger (Level, msg): 741 EdkLogger.debug(Level, msg) 742 743 ## MacroExtend() 744 # 745 # @param Str String that may contain macro 746 # @param MacroDict Dictionary that contains macro value pair 747 # 748 @staticmethod 749 def MacroExtend (Str, MacroDict=None, Arch=DataType.TAB_COMMON): 750 if Str is None: 751 return None 752 753 Dict = {'$(WORKSPACE)': GenFdsGlobalVariable.WorkSpaceDir, 754# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc, 755 '$(TARGET)': GenFdsGlobalVariable.TargetName, 756 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable.ToolChainTag, 757 '$(SPACE)': ' ' 758 } 759 760 if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList: 761 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch] 762 else: 763 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]] 764 765 Dict['$(OUTPUT_DIRECTORY)'] = OutputDir 766 767 if MacroDict: 768 Dict.update(MacroDict) 769 770 for key in Dict: 771 if Str.find(key) >= 0: 772 Str = Str.replace (key, Dict[key]) 773 774 if Str.find('$(ARCH)') >= 0: 775 if len(GenFdsGlobalVariable.ArchList) == 1: 776 Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0]) 777 else: 778 EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str) 779 780 return Str 781 782 ## GetPcdValue() 783 # 784 # @param PcdPattern pattern that labels a PCD. 785 # 786 @staticmethod 787 def GetPcdValue (PcdPattern): 788 if PcdPattern is None: 789 return None 790 if PcdPattern.startswith('PCD('): 791 PcdPair = PcdPattern[4:].rstrip(')').strip().split('.') 792 else: 793 PcdPair = PcdPattern.strip().split('.') 794 TokenSpace = PcdPair[0] 795 TokenCName = PcdPair[1] 796 797 for Arch in GenFdsGlobalVariable.ArchList: 798 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 799 PcdDict = Platform.Pcds 800 for Key in PcdDict: 801 PcdObj = PcdDict[Key] 802 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): 803 if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD: 804 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) 805 if PcdObj.DatumType != DataType.TAB_VOID: 806 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) 807 808 return PcdObj.DefaultValue 809 810 for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, 811 Arch, 812 GenFdsGlobalVariable.TargetName, 813 GenFdsGlobalVariable.ToolChainTag): 814 PcdDict = Package.Pcds 815 for Key in PcdDict: 816 PcdObj = PcdDict[Key] 817 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): 818 if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD: 819 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) 820 if PcdObj.DatumType != DataType.TAB_VOID: 821 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) 822 823 return PcdObj.DefaultValue 824 825 return '' 826 827## FindExtendTool() 828# 829# Find location of tools to process data 830# 831# @param KeyStringList Filter for inputs of section generation 832# @param CurrentArchList Arch list 833# @param NameGuid The Guid name 834# 835def FindExtendTool(KeyStringList, CurrentArchList, NameGuid): 836 ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf"))) 837 ToolDef = ToolDefObj.ToolDef 838 ToolDb = ToolDef.ToolsDefTxtDatabase 839 # if user not specify filter, try to deduce it from global data. 840 if KeyStringList is None or KeyStringList == []: 841 Target = GenFdsGlobalVariable.TargetName 842 ToolChain = GenFdsGlobalVariable.ToolChainTag 843 if ToolChain not in ToolDb['TOOL_CHAIN_TAG']: 844 EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain) 845 KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]] 846 for Arch in CurrentArchList: 847 if Target + '_' + ToolChain + '_' + Arch not in KeyStringList: 848 KeyStringList.append(Target + '_' + ToolChain + '_' + Arch) 849 850 if GenFdsGlobalVariable.GuidToolDefinition: 851 if NameGuid in GenFdsGlobalVariable.GuidToolDefinition: 852 return GenFdsGlobalVariable.GuidToolDefinition[NameGuid] 853 854 ToolDefinition = ToolDef.ToolsDefTxtDictionary 855 ToolPathTmp = None 856 ToolOption = None 857 ToolPathKey = None 858 ToolOptionKey = None 859 KeyList = None 860 for tool_def in ToolDefinition.items(): 861 if NameGuid.lower() == tool_def[1].lower(): 862 KeyList = tool_def[0].split('_') 863 Key = KeyList[0] + \ 864 '_' + \ 865 KeyList[1] + \ 866 '_' + \ 867 KeyList[2] 868 if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID: 869 ToolPathKey = Key + '_' + KeyList[3] + '_PATH' 870 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS' 871 ToolPath = ToolDefinition.get(ToolPathKey) 872 ToolOption = ToolDefinition.get(ToolOptionKey) 873 if ToolPathTmp is None: 874 ToolPathTmp = ToolPath 875 else: 876 if ToolPathTmp != ToolPath: 877 EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath)) 878 879 BuildOption = {} 880 for Arch in CurrentArchList: 881 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 882 # key is (ToolChainFamily, ToolChain, CodeBase) 883 for item in Platform.BuildOptions: 884 if '_PATH' in item[1] or '_FLAGS' in item[1] or '_GUID' in item[1]: 885 if not item[0] or (item[0] and GenFdsGlobalVariable.ToolChainFamily== item[0]): 886 if item[1] not in BuildOption: 887 BuildOption[item[1]] = Platform.BuildOptions[item] 888 if BuildOption: 889 ToolList = [DataType.TAB_TOD_DEFINES_TARGET, DataType.TAB_TOD_DEFINES_TOOL_CHAIN_TAG, DataType.TAB_TOD_DEFINES_TARGET_ARCH] 890 for Index in range(2, -1, -1): 891 for Key in list(BuildOption.keys()): 892 List = Key.split('_') 893 if List[Index] == DataType.TAB_STAR: 894 for String in ToolDb[ToolList[Index]]: 895 if String in [Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]: 896 List[Index] = String 897 NewKey = '%s_%s_%s_%s_%s' % tuple(List) 898 if NewKey not in BuildOption: 899 BuildOption[NewKey] = BuildOption[Key] 900 continue 901 del BuildOption[Key] 902 elif List[Index] not in ToolDb[ToolList[Index]]: 903 del BuildOption[Key] 904 if BuildOption: 905 if not KeyList: 906 for Op in BuildOption: 907 if NameGuid == BuildOption[Op]: 908 KeyList = Op.split('_') 909 Key = KeyList[0] + '_' + KeyList[1] +'_' + KeyList[2] 910 if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID: 911 ToolPathKey = Key + '_' + KeyList[3] + '_PATH' 912 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS' 913 if ToolPathKey in BuildOption: 914 ToolPathTmp = BuildOption[ToolPathKey] 915 if ToolOptionKey in BuildOption: 916 ToolOption = BuildOption[ToolOptionKey] 917 918 GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption) 919 return ToolPathTmp, ToolOption 920