1## @file 2# generate flash image 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# 18from optparse import OptionParser 19import sys 20import Common.LongFilePathOs as os 21import linecache 22import FdfParser 23import Common.BuildToolError as BuildToolError 24from GenFdsGlobalVariable import GenFdsGlobalVariable 25from Workspace.WorkspaceDatabase import WorkspaceDatabase 26from Workspace.BuildClassObject import PcdClassObject 27from Workspace.BuildClassObject import ModuleBuildClassObject 28import RuleComplexFile 29from EfiSection import EfiSection 30import StringIO 31import Common.TargetTxtClassObject as TargetTxtClassObject 32import Common.ToolDefClassObject as ToolDefClassObject 33import Common.DataType 34import Common.GlobalData as GlobalData 35from Common import EdkLogger 36from Common.String import * 37from Common.Misc import DirCache, PathClass 38from Common.Misc import SaveFileOnChange 39from Common.Misc import ClearDuplicatedInf 40from Common.Misc import GuidStructureStringToGuidString 41from Common.Misc import CheckPcdDatum 42from Common.BuildVersion import gBUILD_VERSION 43from Common.MultipleWorkspace import MultipleWorkspace as mws 44 45## Version and Copyright 46versionNumber = "1.0" + ' ' + gBUILD_VERSION 47__version__ = "%prog Version " + versionNumber 48__copyright__ = "Copyright (c) 2007 - 2016, Intel Corporation All rights reserved." 49 50## Tool entrance method 51# 52# This method mainly dispatch specific methods per the command line options. 53# If no error found, return zero value so the caller of this tool can know 54# if it's executed successfully or not. 55# 56# @retval 0 Tool was successful 57# @retval 1 Tool failed 58# 59def main(): 60 global Options 61 Options = myOptionParser() 62 63 global Workspace 64 Workspace = "" 65 ArchList = None 66 ReturnCode = 0 67 68 EdkLogger.Initialize() 69 try: 70 if Options.verbose != None: 71 EdkLogger.SetLevel(EdkLogger.VERBOSE) 72 GenFdsGlobalVariable.VerboseMode = True 73 74 if Options.FixedAddress != None: 75 GenFdsGlobalVariable.FixedLoadAddress = True 76 77 if Options.quiet != None: 78 EdkLogger.SetLevel(EdkLogger.QUIET) 79 if Options.debug != None: 80 EdkLogger.SetLevel(Options.debug + 1) 81 GenFdsGlobalVariable.DebugLevel = Options.debug 82 else: 83 EdkLogger.SetLevel(EdkLogger.INFO) 84 85 if (Options.Workspace == None): 86 EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined", 87 ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.") 88 elif not os.path.exists(Options.Workspace): 89 EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid", 90 ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.") 91 else: 92 Workspace = os.path.normcase(Options.Workspace) 93 GenFdsGlobalVariable.WorkSpaceDir = Workspace 94 if 'EDK_SOURCE' in os.environ.keys(): 95 GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE']) 96 if (Options.debug): 97 GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace) 98 os.chdir(GenFdsGlobalVariable.WorkSpaceDir) 99 100 # set multiple workspace 101 PackagesPath = os.getenv("PACKAGES_PATH") 102 mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath) 103 104 if (Options.filename): 105 FdfFilename = Options.filename 106 FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename) 107 108 if FdfFilename[0:2] == '..': 109 FdfFilename = os.path.realpath(FdfFilename) 110 if not os.path.isabs(FdfFilename): 111 FdfFilename = mws.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename) 112 if not os.path.exists(FdfFilename): 113 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=FdfFilename) 114 115 GenFdsGlobalVariable.FdfFile = FdfFilename 116 GenFdsGlobalVariable.FdfFileTimeStamp = os.path.getmtime(FdfFilename) 117 else: 118 EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename") 119 120 if (Options.BuildTarget): 121 GenFdsGlobalVariable.TargetName = Options.BuildTarget 122 123 if (Options.ToolChain): 124 GenFdsGlobalVariable.ToolChainTag = Options.ToolChain 125 126 if (Options.activePlatform): 127 ActivePlatform = Options.activePlatform 128 ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform) 129 130 if ActivePlatform[0:2] == '..': 131 ActivePlatform = os.path.realpath(ActivePlatform) 132 133 if not os.path.isabs (ActivePlatform): 134 ActivePlatform = mws.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform) 135 136 if not os.path.exists(ActivePlatform) : 137 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!") 138 else: 139 EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform") 140 141 GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform)) 142 143 if (Options.ConfDirectory): 144 # Get alternate Conf location, if it is absolute, then just use the absolute directory name 145 ConfDirectoryPath = os.path.normpath(Options.ConfDirectory) 146 if ConfDirectoryPath.startswith('"'): 147 ConfDirectoryPath = ConfDirectoryPath[1:] 148 if ConfDirectoryPath.endswith('"'): 149 ConfDirectoryPath = ConfDirectoryPath[:-1] 150 if not os.path.isabs(ConfDirectoryPath): 151 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE 152 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf 153 ConfDirectoryPath = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ConfDirectoryPath) 154 else: 155 if "CONF_PATH" in os.environ.keys(): 156 ConfDirectoryPath = os.path.normcase(os.environ["CONF_PATH"]) 157 else: 158 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf 159 ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf') 160 GenFdsGlobalVariable.ConfDir = ConfDirectoryPath 161 BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt")) 162 if os.path.isfile(BuildConfigurationFile) == True: 163 TargetTxt = TargetTxtClassObject.TargetTxtClassObject() 164 TargetTxt.LoadTargetTxtFile(BuildConfigurationFile) 165 # if no build target given in command line, get it from target.txt 166 if not GenFdsGlobalVariable.TargetName: 167 BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET] 168 if len(BuildTargetList) != 1: 169 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.") 170 GenFdsGlobalVariable.TargetName = BuildTargetList[0] 171 172 # if no tool chain given in command line, get it from target.txt 173 if not GenFdsGlobalVariable.ToolChainTag: 174 ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG] 175 if ToolChainList == None or len(ToolChainList) == 0: 176 EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.") 177 if len(ToolChainList) != 1: 178 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for ToolChain.") 179 GenFdsGlobalVariable.ToolChainTag = ToolChainList[0] 180 else: 181 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile) 182 183 #Set global flag for build mode 184 GlobalData.gIgnoreSource = Options.IgnoreSources 185 186 if Options.Macros: 187 for Pair in Options.Macros: 188 if Pair.startswith('"'): 189 Pair = Pair[1:] 190 if Pair.endswith('"'): 191 Pair = Pair[:-1] 192 List = Pair.split('=') 193 if len(List) == 2: 194 if not List[1].strip(): 195 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="No Value given for Macro %s" %List[0]) 196 if List[0].strip() == "EFI_SOURCE": 197 GlobalData.gEfiSource = List[1].strip() 198 GlobalData.gGlobalDefines["EFI_SOURCE"] = GlobalData.gEfiSource 199 continue 200 elif List[0].strip() == "EDK_SOURCE": 201 GlobalData.gEdkSource = List[1].strip() 202 GlobalData.gGlobalDefines["EDK_SOURCE"] = GlobalData.gEdkSource 203 continue 204 elif List[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]: 205 GlobalData.gGlobalDefines[List[0].strip()] = List[1].strip() 206 else: 207 GlobalData.gCommandLineDefines[List[0].strip()] = List[1].strip() 208 else: 209 GlobalData.gCommandLineDefines[List[0].strip()] = "TRUE" 210 os.environ["WORKSPACE"] = Workspace 211 212 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined 213 if "TARGET" not in GlobalData.gGlobalDefines.keys(): 214 GlobalData.gGlobalDefines["TARGET"] = GenFdsGlobalVariable.TargetName 215 if "TOOLCHAIN" not in GlobalData.gGlobalDefines.keys(): 216 GlobalData.gGlobalDefines["TOOLCHAIN"] = GenFdsGlobalVariable.ToolChainTag 217 if "TOOL_CHAIN_TAG" not in GlobalData.gGlobalDefines.keys(): 218 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable.ToolChainTag 219 220 """call Workspace build create database""" 221 GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath)) 222 BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath) 223 BuildWorkSpace.InitDatabase() 224 225 # 226 # Get files real name in workspace dir 227 # 228 GlobalData.gAllFiles = DirCache(Workspace) 229 GlobalData.gWorkspace = Workspace 230 231 if (Options.archList) : 232 ArchList = Options.archList.split(',') 233 else: 234# EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH") 235 ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON', Options.BuildTarget, Options.ToolChain].SupArchList 236 237 TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON', Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList) 238 if len(TargetArchList) == 0: 239 EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList))) 240 241 for Arch in ArchList: 242 GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory) 243 GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].PlatformName 244 245 if (Options.outputDir): 246 OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir) 247 if not os.path.isabs (OutputDirFromCommandLine): 248 OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine) 249 for Arch in ArchList: 250 GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine 251 else: 252 for Arch in ArchList: 253 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag) 254 255 for Key in GenFdsGlobalVariable.OutputDirDict: 256 OutputDir = GenFdsGlobalVariable.OutputDirDict[Key] 257 if OutputDir[0:2] == '..': 258 OutputDir = os.path.realpath(OutputDir) 259 260 if OutputDir[1] != ':': 261 OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir) 262 263 if not os.path.exists(OutputDir): 264 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=OutputDir) 265 GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir 266 267 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """ 268 FdfParserObj = FdfParser.FdfParser(FdfFilename) 269 FdfParserObj.ParseFile() 270 271 if FdfParserObj.CycleReferenceCheck(): 272 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file") 273 274 if (Options.uiFdName) : 275 if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict.keys(): 276 GenFds.OnlyGenerateThisFd = Options.uiFdName 277 else: 278 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, 279 "No such an FD in FDF file: %s" % Options.uiFdName) 280 281 if (Options.uiFvName) : 282 if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict.keys(): 283 GenFds.OnlyGenerateThisFv = Options.uiFvName 284 else: 285 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, 286 "No such an FV in FDF file: %s" % Options.uiFvName) 287 288 if (Options.uiCapName) : 289 if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict.keys(): 290 GenFds.OnlyGenerateThisCap = Options.uiCapName 291 else: 292 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, 293 "No such a Capsule in FDF file: %s" % Options.uiCapName) 294 295 GenFdsGlobalVariable.WorkSpace = BuildWorkSpace 296 if ArchList != None: 297 GenFdsGlobalVariable.ArchList = ArchList 298 299 if Options.OptionPcd: 300 GlobalData.BuildOptionPcd = Options.OptionPcd 301 CheckBuildOptionPcd() 302 303 """Modify images from build output if the feature of loading driver at fixed address is on.""" 304 if GenFdsGlobalVariable.FixedLoadAddress: 305 GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform) 306 """Call GenFds""" 307 GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList) 308 309 """Generate GUID cross reference file""" 310 GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList) 311 312 """Display FV space info.""" 313 GenFds.DisplayFvSpaceInfo(FdfParserObj) 314 315 except FdfParser.Warning, X: 316 EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False) 317 ReturnCode = FORMAT_INVALID 318 except FatalError, X: 319 if Options.debug != None: 320 import traceback 321 EdkLogger.quiet(traceback.format_exc()) 322 ReturnCode = X.args[0] 323 except: 324 import traceback 325 EdkLogger.error( 326 "\nPython", 327 CODE_ERROR, 328 "Tools code failure", 329 ExtraData="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n", 330 RaiseError=False 331 ) 332 EdkLogger.quiet(traceback.format_exc()) 333 ReturnCode = CODE_ERROR 334 finally: 335 ClearDuplicatedInf() 336 return ReturnCode 337 338gParamCheck = [] 339def SingleCheckCallback(option, opt_str, value, parser): 340 if option not in gParamCheck: 341 setattr(parser.values, option.dest, value) 342 gParamCheck.append(option) 343 else: 344 parser.error("Option %s only allows one instance in command line!" % option) 345 346def CheckBuildOptionPcd(): 347 for Arch in GenFdsGlobalVariable.ArchList: 348 PkgList = GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag) 349 for i, pcd in enumerate(GlobalData.BuildOptionPcd): 350 if type(pcd) is tuple: 351 continue 352 (pcdname, pcdvalue) = pcd.split('=') 353 if not pcdvalue: 354 EdkLogger.error('GenFds', OPTION_MISSING, "No Value specified for the PCD %s." % (pcdname)) 355 if '.' in pcdname: 356 (TokenSpaceGuidCName, TokenCName) = pcdname.split('.') 357 HasTokenSpace = True 358 else: 359 TokenCName = pcdname 360 TokenSpaceGuidCName = '' 361 HasTokenSpace = False 362 TokenSpaceGuidCNameList = [] 363 FoundFlag = False 364 PcdDatumType = '' 365 NewValue = '' 366 for package in PkgList: 367 for key in package.Pcds: 368 PcdItem = package.Pcds[key] 369 if HasTokenSpace: 370 if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName): 371 PcdDatumType = PcdItem.DatumType 372 NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue) 373 FoundFlag = True 374 else: 375 if PcdItem.TokenCName == TokenCName: 376 if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList: 377 if len (TokenSpaceGuidCNameList) < 1: 378 TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName) 379 PcdDatumType = PcdItem.DatumType 380 TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName 381 NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue) 382 FoundFlag = True 383 else: 384 EdkLogger.error( 385 'GenFds', 386 PCD_VALIDATION_INFO_ERROR, 387 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0]) 388 ) 389 390 GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue) 391 392def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Value): 393 if PcdDatumType == 'VOID*': 394 if Value.startswith('L'): 395 if not Value[1]: 396 EdkLogger.error('GenFds', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"') 397 Value = Value[0] + '"' + Value[1:] + '"' 398 elif Value.startswith('B'): 399 if not Value[1]: 400 EdkLogger.error('GenFds', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"') 401 Value = Value[1:] 402 else: 403 if not Value[0]: 404 EdkLogger.error('GenFds', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"') 405 Value = '"' + Value + '"' 406 407 IsValid, Cause = CheckPcdDatum(PcdDatumType, Value) 408 if not IsValid: 409 EdkLogger.error('build', FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName)) 410 if PcdDatumType == 'BOOLEAN': 411 Value = Value.upper() 412 if Value == 'TRUE' or Value == '1': 413 Value = '1' 414 elif Value == 'FALSE' or Value == '0': 415 Value = '0' 416 return Value 417 418## FindExtendTool() 419# 420# Find location of tools to process data 421# 422# @param KeyStringList Filter for inputs of section generation 423# @param CurrentArchList Arch list 424# @param NameGuid The Guid name 425# 426def FindExtendTool(KeyStringList, CurrentArchList, NameGuid): 427 # if user not specify filter, try to deduce it from global data. 428 if KeyStringList == None or KeyStringList == []: 429 Target = GenFdsGlobalVariable.TargetName 430 ToolChain = GenFdsGlobalVariable.ToolChainTag 431 ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase 432 if ToolChain not in ToolDb['TOOL_CHAIN_TAG']: 433 EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain) 434 KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]] 435 for Arch in CurrentArchList: 436 if Target + '_' + ToolChain + '_' + Arch not in KeyStringList: 437 KeyStringList.append(Target + '_' + ToolChain + '_' + Arch) 438 439 if GenFdsGlobalVariable.GuidToolDefinition: 440 if NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys(): 441 return GenFdsGlobalVariable.GuidToolDefinition[NameGuid] 442 443 ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary 444 ToolPathTmp = None 445 ToolOption = None 446 for ToolDef in ToolDefinition.items(): 447 if NameGuid == ToolDef[1]: 448 KeyList = ToolDef[0].split('_') 449 Key = KeyList[0] + \ 450 '_' + \ 451 KeyList[1] + \ 452 '_' + \ 453 KeyList[2] 454 if Key in KeyStringList and KeyList[4] == 'GUID': 455 456 ToolPath = ToolDefinition.get(Key + \ 457 '_' + \ 458 KeyList[3] + \ 459 '_' + \ 460 'PATH') 461 462 ToolOption = ToolDefinition.get(Key + \ 463 '_' + \ 464 KeyList[3] + \ 465 '_' + \ 466 'FLAGS') 467 if ToolPathTmp == None: 468 ToolPathTmp = ToolPath 469 else: 470 if ToolPathTmp != ToolPath: 471 EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath)) 472 473 GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption) 474 return ToolPathTmp, ToolOption 475 476## Parse command line options 477# 478# Using standard Python module optparse to parse command line option of this tool. 479# 480# @retval Opt A optparse.Values object containing the parsed options 481# @retval Args Target of build command 482# 483def myOptionParser(): 484 usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\"" 485 Parser = OptionParser(usage=usage, description=__copyright__, version="%prog " + str(versionNumber)) 486 Parser.add_option("-f", "--file", dest="filename", type="string", help="Name of FDF file to convert", action="callback", callback=SingleCheckCallback) 487 Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM, AARCH64 or EBC which should be built, overrides target.txt?s TARGET_ARCH") 488 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.") 489 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.") 490 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.") 491 Parser.add_option("-p", "--platform", type="string", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.", 492 action="callback", callback=SingleCheckCallback) 493 Parser.add_option("-w", "--workspace", type="string", dest="Workspace", default=os.environ.get('WORKSPACE'), help="Set the WORKSPACE", 494 action="callback", callback=SingleCheckCallback) 495 Parser.add_option("-o", "--outputDir", type="string", dest="outputDir", help="Name of Build Output directory", 496 action="callback", callback=SingleCheckCallback) 497 Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.") 498 Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Build the FV image using the [FV] section named by UiFvName") 499 Parser.add_option("-C", "--CapsuleImage", dest="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName") 500 Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.", 501 action="callback", callback=SingleCheckCallback) 502 Parser.add_option("-t", "--tagname", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.", 503 action="callback", callback=SingleCheckCallback) 504 Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".") 505 Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.") 506 Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.") 507 Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files") 508 Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ") 509 510 (Options, args) = Parser.parse_args() 511 return Options 512 513## The class implementing the EDK2 flash image generation process 514# 515# This process includes: 516# 1. Collect workspace information, includes platform and module information 517# 2. Call methods of Fd class to generate FD 518# 3. Call methods of Fv class to generate FV that not belong to FD 519# 520class GenFds : 521 FdfParsef = None 522 # FvName, FdName, CapName in FDF, Image file name 523 ImageBinDict = {} 524 OnlyGenerateThisFd = None 525 OnlyGenerateThisFv = None 526 OnlyGenerateThisCap = None 527 528 ## GenFd() 529 # 530 # @param OutputDir Output directory 531 # @param FdfParser FDF contents parser 532 # @param Workspace The directory of workspace 533 # @param ArchList The Arch list of platform 534 # 535 def GenFd (OutputDir, FdfParser, WorkSpace, ArchList): 536 GenFdsGlobalVariable.SetDir ('', FdfParser, WorkSpace, ArchList) 537 538 GenFdsGlobalVariable.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!") 539 if GenFds.OnlyGenerateThisCap != None and GenFds.OnlyGenerateThisCap.upper() in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.keys(): 540 CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.get(GenFds.OnlyGenerateThisCap.upper()) 541 if CapsuleObj != None: 542 CapsuleObj.GenCapsule() 543 return 544 545 if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): 546 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(GenFds.OnlyGenerateThisFd.upper()) 547 if FdObj != None: 548 FdObj.GenFd() 549 return 550 elif GenFds.OnlyGenerateThisFd == None and GenFds.OnlyGenerateThisFv == None: 551 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): 552 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName] 553 FdObj.GenFd() 554 555 GenFdsGlobalVariable.VerboseLogger("\n Generate other FV images! ") 556 if GenFds.OnlyGenerateThisFv != None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): 557 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(GenFds.OnlyGenerateThisFv.upper()) 558 if FvObj != None: 559 Buffer = StringIO.StringIO() 560 FvObj.AddToBuffer(Buffer) 561 Buffer.close() 562 return 563 elif GenFds.OnlyGenerateThisFv == None: 564 for FvName in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys(): 565 Buffer = StringIO.StringIO('') 566 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[FvName] 567 FvObj.AddToBuffer(Buffer) 568 Buffer.close() 569 570 if GenFds.OnlyGenerateThisFv == None and GenFds.OnlyGenerateThisFd == None and GenFds.OnlyGenerateThisCap == None: 571 if GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict != {}: 572 GenFdsGlobalVariable.VerboseLogger("\n Generate other Capsule images!") 573 for CapsuleName in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.keys(): 574 CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict[CapsuleName] 575 CapsuleObj.GenCapsule() 576 577 if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}: 578 GenFdsGlobalVariable.VerboseLogger("\n Generate all Option ROM!") 579 for DriverName in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.keys(): 580 OptRomObj = GenFdsGlobalVariable.FdfParser.Profile.OptRomDict[DriverName] 581 OptRomObj.AddToBuffer(None) 582 583 ## GetFvBlockSize() 584 # 585 # @param FvObj Whose block size to get 586 # @retval int Block size value 587 # 588 def GetFvBlockSize(FvObj): 589 DefaultBlockSize = 0x1 590 FdObj = None 591 if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys(): 592 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()] 593 if FdObj == None: 594 for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values(): 595 for ElementRegion in ElementFd.RegionList: 596 if ElementRegion.RegionType == 'FV': 597 for ElementRegionData in ElementRegion.RegionDataList: 598 if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName: 599 if FvObj.BlockSizeList != []: 600 return FvObj.BlockSizeList[0][0] 601 else: 602 return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList) 603 if FvObj.BlockSizeList != []: 604 return FvObj.BlockSizeList[0][0] 605 return DefaultBlockSize 606 else: 607 for ElementRegion in FdObj.RegionList: 608 if ElementRegion.RegionType == 'FV': 609 for ElementRegionData in ElementRegion.RegionDataList: 610 if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName: 611 if FvObj.BlockSizeList != []: 612 return FvObj.BlockSizeList[0][0] 613 else: 614 return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList) 615 return DefaultBlockSize 616 617 ## DisplayFvSpaceInfo() 618 # 619 # @param FvObj Whose block size to get 620 # @retval None 621 # 622 def DisplayFvSpaceInfo(FdfParser): 623 624 FvSpaceInfoList = [] 625 MaxFvNameLength = 0 626 for FvName in FdfParser.Profile.FvDict: 627 if len(FvName) > MaxFvNameLength: 628 MaxFvNameLength = len(FvName) 629 FvSpaceInfoFileName = os.path.join(GenFdsGlobalVariable.FvDir, FvName.upper() + '.Fv.map') 630 if os.path.exists(FvSpaceInfoFileName): 631 FileLinesList = linecache.getlines(FvSpaceInfoFileName) 632 TotalFound = False 633 Total = '' 634 UsedFound = False 635 Used = '' 636 FreeFound = False 637 Free = '' 638 for Line in FileLinesList: 639 NameValue = Line.split('=') 640 if len(NameValue) == 2: 641 if NameValue[0].strip() == 'EFI_FV_TOTAL_SIZE': 642 TotalFound = True 643 Total = NameValue[1].strip() 644 if NameValue[0].strip() == 'EFI_FV_TAKEN_SIZE': 645 UsedFound = True 646 Used = NameValue[1].strip() 647 if NameValue[0].strip() == 'EFI_FV_SPACE_SIZE': 648 FreeFound = True 649 Free = NameValue[1].strip() 650 651 if TotalFound and UsedFound and FreeFound: 652 FvSpaceInfoList.append((FvName, Total, Used, Free)) 653 654 GenFdsGlobalVariable.InfLogger('\nFV Space Information') 655 for FvSpaceInfo in FvSpaceInfoList: 656 Name = FvSpaceInfo[0] 657 TotalSizeValue = long(FvSpaceInfo[1], 0) 658 UsedSizeValue = long(FvSpaceInfo[2], 0) 659 FreeSizeValue = long(FvSpaceInfo[3], 0) 660 if UsedSizeValue == TotalSizeValue: 661 Percentage = '100' 662 else: 663 Percentage = str((UsedSizeValue + 0.0) / TotalSizeValue)[0:4].lstrip('0.') 664 665 GenFdsGlobalVariable.InfLogger(Name + ' ' + '[' + Percentage + '%Full] ' + str(TotalSizeValue) + ' total, ' + str(UsedSizeValue) + ' used, ' + str(FreeSizeValue) + ' free') 666 667 ## PreprocessImage() 668 # 669 # @param BuildDb Database from build meta data files 670 # @param DscFile modules from dsc file will be preprocessed 671 # @retval None 672 # 673 def PreprocessImage(BuildDb, DscFile): 674 PcdDict = BuildDb.BuildObject[DscFile, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Pcds 675 PcdValue = '' 676 for Key in PcdDict: 677 PcdObj = PcdDict[Key] 678 if PcdObj.TokenCName == 'PcdBsBaseAddress': 679 PcdValue = PcdObj.DefaultValue 680 break 681 682 if PcdValue == '': 683 return 684 685 Int64PcdValue = long(PcdValue, 0) 686 if Int64PcdValue == 0 or Int64PcdValue < -1: 687 return 688 689 TopAddress = 0 690 if Int64PcdValue > 0: 691 TopAddress = Int64PcdValue 692 693 ModuleDict = BuildDb.BuildObject[DscFile, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Modules 694 for Key in ModuleDict: 695 ModuleObj = BuildDb.BuildObject[Key, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 696 print ModuleObj.BaseName + ' ' + ModuleObj.ModuleType 697 698 def GenerateGuidXRefFile(BuildDb, ArchList): 699 GuidXRefFileName = os.path.join(GenFdsGlobalVariable.FvDir, "Guid.xref") 700 GuidXRefFile = StringIO.StringIO('') 701 GuidDict = {} 702 for Arch in ArchList: 703 PlatformDataBase = BuildDb.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 704 for ModuleFile in PlatformDataBase.Modules: 705 Module = BuildDb.BuildObject[ModuleFile, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 706 GuidXRefFile.write("%s %s\n" % (Module.Guid, Module.BaseName)) 707 for key, item in Module.Protocols.items(): 708 GuidDict[key] = item 709 for key, item in Module.Guids.items(): 710 GuidDict[key] = item 711 for key, item in Module.Ppis.items(): 712 GuidDict[key] = item 713 # Append GUIDs, Protocols, and PPIs to the Xref file 714 GuidXRefFile.write("\n") 715 for key, item in GuidDict.items(): 716 GuidXRefFile.write("%s %s\n" % (GuidStructureStringToGuidString(item).upper(), key)) 717 718 if GuidXRefFile.getvalue(): 719 SaveFileOnChange(GuidXRefFileName, GuidXRefFile.getvalue(), False) 720 GenFdsGlobalVariable.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName) 721 elif os.path.exists(GuidXRefFileName): 722 os.remove(GuidXRefFileName) 723 GuidXRefFile.close() 724 725 ##Define GenFd as static function 726 GenFd = staticmethod(GenFd) 727 GetFvBlockSize = staticmethod(GetFvBlockSize) 728 DisplayFvSpaceInfo = staticmethod(DisplayFvSpaceInfo) 729 PreprocessImage = staticmethod(PreprocessImage) 730 GenerateGuidXRefFile = staticmethod(GenerateGuidXRefFile) 731 732if __name__ == '__main__': 733 r = main() 734 ## 0-127 is a safe return range, and 1 is a standard default error 735 if r < 0 or r > 127: r = 1 736 sys.exit(r) 737 738