1## @file 2# process FFS generation from INF statement 3# 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> 5# Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR> 6# 7# SPDX-License-Identifier: BSD-2-Clause-Patent 8# 9 10## 11# Import Modules 12# 13from __future__ import absolute_import 14from . import Rule 15import Common.LongFilePathOs as os 16from io import BytesIO 17from struct import * 18from .GenFdsGlobalVariable import GenFdsGlobalVariable 19from .Ffs import SectionSuffix,FdfFvFileTypeToFileType 20import subprocess 21import sys 22from . import Section 23from . import RuleSimpleFile 24from . import RuleComplexFile 25from CommonDataClass.FdfClass import FfsInfStatementClassObject 26from Common.MultipleWorkspace import MultipleWorkspace as mws 27from Common.DataType import SUP_MODULE_USER_DEFINED 28from Common.DataType import SUP_MODULE_HOST_APPLICATION 29from Common.StringUtils import * 30from Common.Misc import PathClass 31from Common.Misc import GuidStructureByteArrayToGuidString 32from Common.Misc import ProcessDuplicatedInf 33from Common.Misc import GetVariableOffset 34from Common import EdkLogger 35from Common.BuildToolError import * 36from .GuidSection import GuidSection 37from .FvImageSection import FvImageSection 38from Common.Misc import PeImageClass 39from AutoGen.GenDepex import DependencyExpression 40from PatchPcdValue.PatchPcdValue import PatchBinaryFile 41from Common.LongFilePathSupport import CopyLongFilePath 42from Common.LongFilePathSupport import OpenLongFilePath as open 43import Common.GlobalData as GlobalData 44from .DepexSection import DepexSection 45from Common.Misc import SaveFileOnChange 46from Common.Expression import * 47from Common.DataType import * 48 49## generate FFS from INF 50# 51# 52class FfsInfStatement(FfsInfStatementClassObject): 53 ## The constructor 54 # 55 # @param self The object pointer 56 # 57 def __init__(self): 58 FfsInfStatementClassObject.__init__(self) 59 self.TargetOverrideList = [] 60 self.ShadowFromInfFile = None 61 self.KeepRelocFromRule = None 62 self.InDsc = True 63 self.OptRomDefs = {} 64 self.PiSpecVersion = '0x00000000' 65 self.InfModule = None 66 self.FinalTargetSuffixMap = {} 67 self.CurrentLineNum = None 68 self.CurrentLineContent = None 69 self.FileName = None 70 self.InfFileName = None 71 self.OverrideGuid = None 72 self.PatchedBinFile = '' 73 self.MacroDict = {} 74 self.Depex = False 75 76 ## GetFinalTargetSuffixMap() method 77 # 78 # Get final build target list 79 def GetFinalTargetSuffixMap(self): 80 if not self.InfModule or not self.CurrentArch: 81 return [] 82 if not self.FinalTargetSuffixMap: 83 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch) 84 for File in FinalBuildTargetList: 85 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File) 86 87 # Check if current INF module has DEPEX 88 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != SUP_MODULE_USER_DEFINED and self.InfModule.ModuleType != SUP_MODULE_HOST_APPLICATION \ 89 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass: 90 ModuleType = self.InfModule.ModuleType 91 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 92 93 if ModuleType != SUP_MODULE_USER_DEFINED and ModuleType != SUP_MODULE_HOST_APPLICATION: 94 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys(): 95 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]: 96 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType] 97 98 StrModule = str(self.InfModule) 99 PlatformModule = None 100 if StrModule in PlatformDataBase.Modules: 101 PlatformModule = PlatformDataBase.Modules[StrModule] 102 for LibraryClass in PlatformModule.LibraryClasses: 103 if LibraryClass.startswith("NULL"): 104 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass] 105 106 DependencyList = [self.InfModule] 107 LibraryInstance = {} 108 DepexList = [] 109 while len(DependencyList) > 0: 110 Module = DependencyList.pop(0) 111 if not Module: 112 continue 113 for Dep in Module.Depex[self.CurrentArch, ModuleType]: 114 if DepexList != []: 115 DepexList.append('AND') 116 DepexList.append('(') 117 DepexList.extend(Dep) 118 if DepexList[-1] == 'END': # no need of a END at this time 119 DepexList.pop() 120 DepexList.append(')') 121 if 'BEFORE' in DepexList or 'AFTER' in DepexList: 122 break 123 for LibName in Module.LibraryClasses: 124 if LibName in LibraryInstance: 125 continue 126 if PlatformModule and LibName in PlatformModule.LibraryClasses: 127 LibraryPath = PlatformModule.LibraryClasses[LibName] 128 else: 129 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType] 130 if not LibraryPath: 131 LibraryPath = Module.LibraryClasses[LibName] 132 if not LibraryPath: 133 continue 134 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 135 LibraryInstance[LibName] = LibraryModule 136 DependencyList.append(LibraryModule) 137 if DepexList: 138 Dpx = DependencyExpression(DepexList, ModuleType, True) 139 if len(Dpx.PostfixNotation) != 0: 140 # It means this module has DEPEX 141 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex'] 142 return self.FinalTargetSuffixMap 143 144 ## __InfParse() method 145 # 146 # Parse inf file to get module information 147 # 148 # @param self The object pointer 149 # @param Dict dictionary contains macro and value pair 150 # 151 def __InfParse__(self, Dict = None, IsGenFfs=False): 152 153 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName) 154 155 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '') 156 if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\': 157 pass 158 elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' : 159 self.InfFileName = self.InfFileName[1:] 160 161 if self.InfFileName.find('$') == -1: 162 InfPath = NormPath(self.InfFileName) 163 if not os.path.exists(InfPath): 164 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath) 165 if not os.path.exists(InfPath): 166 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName)) 167 168 self.CurrentArch = self.GetCurrentArch() 169 # 170 # Get the InfClass object 171 # 172 173 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) 174 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf") 175 if ErrorCode != 0: 176 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo) 177 178 # 179 # Cache lower case version of INF path before processing FILE_GUID override 180 # 181 InfLowerPath = str(PathClassObj).lower() 182 if self.OverrideGuid: 183 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir) 184 if self.CurrentArch is not None: 185 186 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 187 # 188 # Set Ffs BaseName, ModuleGuid, ModuleType, Version, OutputPath 189 # 190 self.BaseName = Inf.BaseName 191 self.ModuleGuid = Inf.Guid 192 self.ModuleType = Inf.ModuleType 193 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification: 194 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION'] 195 if Inf.AutoGenVersion < 0x00010005: 196 self.ModuleType = Inf.ComponentType 197 self.VersionString = Inf.Version 198 self.BinFileList = Inf.Binaries 199 self.SourceFileList = Inf.Sources 200 if self.KeepReloc is None and Inf.Shadow: 201 self.ShadowFromInfFile = Inf.Shadow 202 203 else: 204 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 205 self.BaseName = Inf.BaseName 206 self.ModuleGuid = Inf.Guid 207 self.ModuleType = Inf.ModuleType 208 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification: 209 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION'] 210 self.VersionString = Inf.Version 211 self.BinFileList = Inf.Binaries 212 self.SourceFileList = Inf.Sources 213 if self.BinFileList == []: 214 EdkLogger.error("GenFds", GENFDS_ERROR, 215 "INF %s specified in FDF could not be found in build ARCH %s!" \ 216 % (self.InfFileName, GenFdsGlobalVariable.ArchList)) 217 218 if self.OverrideGuid: 219 self.ModuleGuid = self.OverrideGuid 220 221 if len(self.SourceFileList) != 0 and not self.InDsc: 222 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName)) 223 224 if self.ModuleType == SUP_MODULE_SMM_CORE and int(self.PiSpecVersion, 16) < 0x0001000A: 225 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName) 226 227 if self.ModuleType == SUP_MODULE_MM_CORE_STANDALONE and int(self.PiSpecVersion, 16) < 0x00010032: 228 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.InfFileName) 229 230 if Inf._Defs is not None and len(Inf._Defs) > 0: 231 self.OptRomDefs.update(Inf._Defs) 232 233 self.PatchPcds = [] 234 InfPcds = Inf.Pcds 235 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 236 FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict 237 PlatformPcds = Platform.Pcds 238 239 # Workaround here: both build and GenFds tool convert the workspace path to lower case 240 # But INF file path in FDF and DSC file may have real case characters. 241 # Try to convert the path to lower case to see if PCDs value are override by DSC. 242 DscModules = {} 243 for DscModule in Platform.Modules: 244 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule] 245 for PcdKey in InfPcds: 246 Pcd = InfPcds[PcdKey] 247 if not hasattr(Pcd, 'Offset'): 248 continue 249 if Pcd.Type != TAB_PCDS_PATCHABLE_IN_MODULE: 250 continue 251 # Override Patchable PCD value by the value from DSC 252 PatchPcd = None 253 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds: 254 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey] 255 elif PcdKey in Platform.Pcds: 256 PatchPcd = Platform.Pcds[PcdKey] 257 DscOverride = False 258 if PatchPcd and Pcd.Type == PatchPcd.Type: 259 DefaultValue = PatchPcd.DefaultValue 260 DscOverride = True 261 262 # Override Patchable PCD value by the value from FDF 263 FdfOverride = False 264 if PcdKey in FdfPcdDict: 265 DefaultValue = FdfPcdDict[PcdKey] 266 FdfOverride = True 267 268 # Override Patchable PCD value by the value from Build Option 269 BuildOptionOverride = False 270 if GlobalData.BuildOptionPcd: 271 for pcd in GlobalData.BuildOptionPcd: 272 if PcdKey == (pcd[1], pcd[0]): 273 if pcd[2]: 274 continue 275 DefaultValue = pcd[3] 276 BuildOptionOverride = True 277 break 278 279 if not DscOverride and not FdfOverride and not BuildOptionOverride: 280 continue 281 282 # Support Flexible PCD format 283 if DefaultValue: 284 try: 285 DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True) 286 except BadExpression: 287 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName) 288 289 if Pcd.InfDefaultValue: 290 try: 291 Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True) 292 except BadExpression: 293 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue), File=self.InfFileName) 294 295 # Check value, if value are equal, no need to patch 296 if Pcd.DatumType == TAB_VOID: 297 if Pcd.InfDefaultValue == DefaultValue or not DefaultValue: 298 continue 299 # Get the string size from FDF or DSC 300 if DefaultValue[0] == 'L': 301 # Remove L"", but the '\0' must be appended 302 MaxDatumSize = str((len(DefaultValue) - 2) * 2) 303 elif DefaultValue[0] == '{': 304 MaxDatumSize = str(len(DefaultValue.split(','))) 305 else: 306 MaxDatumSize = str(len(DefaultValue) - 1) 307 if DscOverride: 308 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize 309 # If no defined the maximum size in DSC, try to get current size from INF 310 if not Pcd.MaxDatumSize: 311 Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(','))) 312 else: 313 Base1 = Base2 = 10 314 if Pcd.InfDefaultValue.upper().startswith('0X'): 315 Base1 = 16 316 if DefaultValue.upper().startswith('0X'): 317 Base2 = 16 318 try: 319 PcdValueInImg = int(Pcd.InfDefaultValue, Base1) 320 PcdValueInDscOrFdf = int(DefaultValue, Base2) 321 if PcdValueInImg == PcdValueInDscOrFdf: 322 continue 323 except: 324 continue 325 # Check the Pcd size and data type 326 if Pcd.DatumType == TAB_VOID: 327 if int(MaxDatumSize) > int(Pcd.MaxDatumSize): 328 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \ 329 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize))) 330 else: 331 if PcdValueInDscOrFdf > MAX_VAL_TYPE[Pcd.DatumType] \ 332 or PcdValueInImg > MAX_VAL_TYPE[Pcd.DatumType]: 333 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \ 334 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) 335 self.PatchPcds.append((Pcd, DefaultValue)) 336 337 self.InfModule = Inf 338 self.PcdIsDriver = Inf.PcdIsDriver 339 self.IsBinaryModule = Inf.IsBinaryModule 340 if len(Inf.Depex.data) > 0 and len(Inf.DepexExpression.data) > 0: 341 self.Depex = True 342 343 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName) 344 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid) 345 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType) 346 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString) 347 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName) 348 349 # 350 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${ModuleName}\ 351 # 352 if IsGenFfs: 353 Rule = self.__GetRule__() 354 if GlobalData.gGuidPatternEnd.match(Rule.NameGuid): 355 self.ModuleGuid = Rule.NameGuid 356 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \ 357 self.ModuleGuid + self.BaseName) 358 if not os.path.exists(self.OutputPath) : 359 os.makedirs(self.OutputPath) 360 361 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__() 362 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath) 363 364 ## PatchEfiFile 365 # 366 # Patch EFI file with patch PCD 367 # 368 # @param EfiFile: EFI file needs to be patched. 369 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name 370 # If passed in file does not end with efi, return as is 371 # 372 def PatchEfiFile(self, EfiFile, FileType): 373 # 374 # If the module does not have any patches, then return path to input file 375 # 376 if not self.PatchPcds: 377 return EfiFile 378 379 # 380 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED 381 # 382 if FileType != BINARY_FILE_TYPE_PE32 and self.ModuleType != SUP_MODULE_USER_DEFINED and self.ModuleType != SUP_MODULE_HOST_APPLICATION: 383 return EfiFile 384 385 # 386 # Generate path to patched output file 387 # 388 Basename = os.path.basename(EfiFile) 389 Output = os.path.normpath (os.path.join(self.OutputPath, Basename)) 390 391 # 392 # If this file has already been patched, then return the path to the patched file 393 # 394 if self.PatchedBinFile == Output: 395 return Output 396 397 # 398 # If a different file from the same module has already been patched, then generate an error 399 # 400 if self.PatchedBinFile: 401 EdkLogger.error("GenFds", GENFDS_ERROR, 402 'Only one binary file can be patched:\n' 403 ' a binary file has been patched: %s\n' 404 ' current file: %s' % (self.PatchedBinFile, EfiFile), 405 File=self.InfFileName) 406 407 # 408 # Copy unpatched file contents to output file location to perform patching 409 # 410 CopyLongFilePath(EfiFile, Output) 411 412 # 413 # Apply patches to patched output file 414 # 415 for Pcd, Value in self.PatchPcds: 416 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize) 417 if RetVal: 418 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName) 419 420 # 421 # Save the path of the patched output file 422 # 423 self.PatchedBinFile = Output 424 425 # 426 # Return path to patched output file 427 # 428 return Output 429 430 ## GenFfs() method 431 # 432 # Generate FFS 433 # 434 # @param self The object pointer 435 # @param Dict dictionary contains macro and value pair 436 # @param FvChildAddr Array of the inside FvImage base address 437 # @param FvParentAddr Parent Fv base address 438 # @retval string Generated FFS file name 439 # 440 def GenFfs(self, Dict = None, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None): 441 # 442 # Parse Inf file get Module related information 443 # 444 if Dict is None: 445 Dict = {} 446 self.__InfParse__(Dict, IsGenFfs=True) 447 Arch = self.GetCurrentArch() 448 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName); 449 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs') 450 451 SrcFileDir = "." 452 SrcPath = os.path.dirname(SrcFile) 453 SrcFileName = os.path.basename(SrcFile) 454 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName) 455 DestPath = os.path.dirname(DestFile) 456 DestFileName = os.path.basename(DestFile) 457 DestFileBase, DestFileExt = os.path.splitext(DestFileName) 458 self.MacroDict = { 459 # source file 460 "${src}" : SrcFile, 461 "${s_path}" : SrcPath, 462 "${s_dir}" : SrcFileDir, 463 "${s_name}" : SrcFileName, 464 "${s_base}" : SrcFileBase, 465 "${s_ext}" : SrcFileExt, 466 # destination file 467 "${dst}" : DestFile, 468 "${d_path}" : DestPath, 469 "${d_name}" : DestFileName, 470 "${d_base}" : DestFileBase, 471 "${d_ext}" : DestFileExt 472 } 473 # 474 # Allow binary type module not specify override rule in FDF file. 475 # 476 if len(self.BinFileList) > 0: 477 if self.Rule is None or self.Rule == "": 478 self.Rule = "BINARY" 479 480 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY': 481 IsMakefile = True 482 # 483 # Get the rule of how to generate Ffs file 484 # 485 Rule = self.__GetRule__() 486 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName) 487 # 488 # Convert Fv File Type for PI1.1 SMM driver. 489 # 490 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A: 491 if Rule.FvFileType == 'DRIVER': 492 Rule.FvFileType = 'SMM' 493 # 494 # Framework SMM Driver has no SMM FV file type 495 # 496 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A: 497 if Rule.FvFileType == 'SMM' or Rule.FvFileType == SUP_MODULE_SMM_CORE: 498 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName) 499 # 500 # For the rule only has simpleFile 501 # 502 MakefilePath = None 503 if self.IsBinaryModule: 504 IsMakefile = False 505 if IsMakefile: 506 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) 507 if self.OverrideGuid: 508 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir) 509 MakefilePath = PathClassObj.Path, Arch 510 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile): 511 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile) 512 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath) 513 return FfsOutput 514 # 515 # For Rule has ComplexFile 516 # 517 elif isinstance(Rule, RuleComplexFile.RuleComplexFile): 518 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile) 519 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath) 520 return FfsOutput 521 522 ## __ExtendMacro__() method 523 # 524 # Replace macro with its value 525 # 526 # @param self The object pointer 527 # @param String The string to be replaced 528 # @retval string Macro replaced string 529 # 530 def __ExtendMacro__ (self, String): 531 MacroDict = { 532 '$(INF_OUTPUT)' : self.EfiOutputPath, 533 '$(MODULE_NAME)' : self.BaseName, 534 '$(BUILD_NUMBER)': self.BuildNum, 535 '$(INF_VERSION)' : self.VersionString, 536 '$(NAMED_GUID)' : self.ModuleGuid 537 } 538 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict) 539 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict) 540 return String 541 542 ## __GetRule__() method 543 # 544 # Get correct rule for generating FFS for this INF 545 # 546 # @param self The object pointer 547 # @retval Rule Rule object 548 # 549 def __GetRule__ (self) : 550 CurrentArchList = [] 551 if self.CurrentArch is None: 552 CurrentArchList = ['common'] 553 else: 554 CurrentArchList.append(self.CurrentArch) 555 556 for CurrentArch in CurrentArchList: 557 RuleName = 'RULE' + \ 558 '.' + \ 559 CurrentArch.upper() + \ 560 '.' + \ 561 self.ModuleType.upper() 562 if self.Rule is not None: 563 RuleName = RuleName + \ 564 '.' + \ 565 self.Rule.upper() 566 567 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName) 568 if Rule is not None: 569 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName) 570 return Rule 571 572 RuleName = 'RULE' + \ 573 '.' + \ 574 TAB_COMMON + \ 575 '.' + \ 576 self.ModuleType.upper() 577 578 if self.Rule is not None: 579 RuleName = RuleName + \ 580 '.' + \ 581 self.Rule.upper() 582 583 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName)) 584 585 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName) 586 if Rule is not None: 587 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName) 588 return Rule 589 590 if Rule is None : 591 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \ 592 % (RuleName, self.InfFileName)) 593 594 ## __GetPlatformArchList__() method 595 # 596 # Get Arch list this INF built under 597 # 598 # @param self The object pointer 599 # @retval list Arch list 600 # 601 def __GetPlatformArchList__(self): 602 603 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)) 604 DscArchList = [] 605 for Arch in GenFdsGlobalVariable.ArchList : 606 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] 607 if PlatformDataBase is not None: 608 if InfFileKey in PlatformDataBase.Modules: 609 DscArchList.append (Arch) 610 else: 611 # 612 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has 613 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key, 614 # but the path (self.MetaFile.Path) is the real path 615 # 616 for key in PlatformDataBase.Modules: 617 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path): 618 DscArchList.append (Arch) 619 break 620 621 return DscArchList 622 623 ## GetCurrentArch() method 624 # 625 # Get Arch list of the module from this INF is to be placed into flash 626 # 627 # @param self The object pointer 628 # @retval list Arch list 629 # 630 def GetCurrentArch(self) : 631 632 TargetArchList = GenFdsGlobalVariable.ArchList 633 634 PlatformArchList = self.__GetPlatformArchList__() 635 636 CurArchList = TargetArchList 637 if PlatformArchList != []: 638 CurArchList = list(set (TargetArchList) & set (PlatformArchList)) 639 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList)) 640 641 ArchList = [] 642 if self.KeyStringList != []: 643 for Key in self.KeyStringList: 644 Key = GenFdsGlobalVariable.MacroExtend(Key) 645 Target, Tag, Arch = Key.split('_') 646 if Arch in CurArchList: 647 ArchList.append(Arch) 648 if Target not in self.TargetOverrideList: 649 self.TargetOverrideList.append(Target) 650 else: 651 ArchList = CurArchList 652 653 UseArchList = TargetArchList 654 if self.UseArch is not None: 655 UseArchList = [] 656 UseArchList.append(self.UseArch) 657 ArchList = list(set (UseArchList) & set (ArchList)) 658 659 self.InfFileName = NormPath(self.InfFileName) 660 if len(PlatformArchList) == 0: 661 self.InDsc = False 662 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) 663 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf") 664 if ErrorCode != 0: 665 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo) 666 if len(ArchList) == 1: 667 Arch = ArchList[0] 668 return Arch 669 elif len(ArchList) > 1: 670 if len(PlatformArchList) == 0: 671 EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName)) 672 else: 673 EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName)) 674 else: 675 EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \ 676 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList)))) 677 678 ## __GetEFIOutPutPath__() method 679 # 680 # Get the output path for generated files 681 # 682 # @param self The object pointer 683 # @retval string Path that output files from this INF go to 684 # 685 def __GetEFIOutPutPath__(self): 686 Arch = '' 687 OutputPath = '' 688 DebugPath = '' 689 (ModulePath, FileName) = os.path.split(self.InfFileName) 690 Index = FileName.rfind('.') 691 FileName = FileName[0:Index] 692 if self.OverrideGuid: 693 FileName = self.OverrideGuid 694 Arch = "NoneArch" 695 if self.CurrentArch is not None: 696 Arch = self.CurrentArch 697 698 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], 699 Arch, 700 ModulePath, 701 FileName, 702 'OUTPUT' 703 ) 704 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], 705 Arch, 706 ModulePath, 707 FileName, 708 'DEBUG' 709 ) 710 OutputPath = os.path.realpath(OutputPath) 711 DebugPath = os.path.realpath(DebugPath) 712 return OutputPath, DebugPath 713 714 ## __GenSimpleFileSection__() method 715 # 716 # Generate section by specified file name or a list of files with file extension 717 # 718 # @param self The object pointer 719 # @param Rule The rule object used to generate section 720 # @retval string File name of the generated section file 721 # 722 def __GenSimpleFileSection__(self, Rule, IsMakefile = False): 723 # 724 # Prepare the parameter of GenSection 725 # 726 FileList = [] 727 OutputFileList = [] 728 GenSecInputFile = None 729 if Rule.FileName is not None: 730 GenSecInputFile = self.__ExtendMacro__(Rule.FileName) 731 if os.path.isabs(GenSecInputFile): 732 GenSecInputFile = os.path.normpath(GenSecInputFile) 733 else: 734 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile)) 735 else: 736 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension) 737 738 Index = 1 739 SectionType = Rule.SectionType 740 # 741 # Convert Fv Section Type for PI1.1 SMM driver. 742 # 743 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A: 744 if SectionType == BINARY_FILE_TYPE_DXE_DEPEX: 745 SectionType = BINARY_FILE_TYPE_SMM_DEPEX 746 # 747 # Framework SMM Driver has no SMM_DEPEX section type 748 # 749 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A: 750 if SectionType == BINARY_FILE_TYPE_SMM_DEPEX: 751 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName) 752 NoStrip = True 753 if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM): 754 if self.KeepReloc is not None: 755 NoStrip = self.KeepReloc 756 elif Rule.KeepReloc is not None: 757 NoStrip = Rule.KeepReloc 758 elif self.ShadowFromInfFile is not None: 759 NoStrip = self.ShadowFromInfFile 760 761 if FileList != [] : 762 for File in FileList: 763 764 SecNum = '%d' %Index 765 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \ 766 SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum 767 Index = Index + 1 768 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile) 769 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch) 770 771 #Get PE Section alignment when align is set to AUTO 772 if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE): 773 ImageObj = PeImageClass (File) 774 if ImageObj.SectionAlignment < 0x400: 775 self.Alignment = str (ImageObj.SectionAlignment) 776 elif ImageObj.SectionAlignment < 0x100000: 777 self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K' 778 else: 779 self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M' 780 781 if not NoStrip: 782 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc') 783 if not os.path.exists(FileBeforeStrip) or \ 784 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)): 785 CopyLongFilePath(File, FileBeforeStrip) 786 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped') 787 GenFdsGlobalVariable.GenerateFirmwareImage( 788 StrippedFile, 789 [File], 790 Strip=True, 791 IsMakefile=IsMakefile 792 ) 793 File = StrippedFile 794 795 if SectionType == BINARY_FILE_TYPE_TE: 796 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw') 797 GenFdsGlobalVariable.GenerateFirmwareImage( 798 TeFile, 799 [File], 800 Type='te', 801 IsMakefile=IsMakefile 802 ) 803 File = TeFile 804 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile) 805 OutputFileList.append(OutputFile) 806 else: 807 SecNum = '%d' %Index 808 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \ 809 SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum 810 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile) 811 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch) 812 813 #Get PE Section alignment when align is set to AUTO 814 if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE): 815 ImageObj = PeImageClass (GenSecInputFile) 816 if ImageObj.SectionAlignment < 0x400: 817 self.Alignment = str (ImageObj.SectionAlignment) 818 elif ImageObj.SectionAlignment < 0x100000: 819 self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K' 820 else: 821 self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M' 822 823 if not NoStrip: 824 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc') 825 if not os.path.exists(FileBeforeStrip) or \ 826 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)): 827 CopyLongFilePath(GenSecInputFile, FileBeforeStrip) 828 829 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped') 830 GenFdsGlobalVariable.GenerateFirmwareImage( 831 StrippedFile, 832 [GenSecInputFile], 833 Strip=True, 834 IsMakefile=IsMakefile 835 ) 836 GenSecInputFile = StrippedFile 837 838 if SectionType == BINARY_FILE_TYPE_TE: 839 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw') 840 GenFdsGlobalVariable.GenerateFirmwareImage( 841 TeFile, 842 [GenSecInputFile], 843 Type='te', 844 IsMakefile=IsMakefile 845 ) 846 GenSecInputFile = TeFile 847 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile) 848 OutputFileList.append(OutputFile) 849 850 return OutputFileList 851 852 ## __GenSimpleFileFfs__() method 853 # 854 # Generate FFS 855 # 856 # @param self The object pointer 857 # @param Rule The rule object used to generate section 858 # @param InputFileList The output file list from GenSection 859 # @retval string Generated FFS file name 860 # 861 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None): 862 FfsOutput = self.OutputPath + \ 863 os.sep + \ 864 self.__ExtendMacro__(Rule.NameGuid) + \ 865 '.ffs' 866 867 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid)) 868 InputSection = [] 869 SectionAlignments = [] 870 for InputFile in InputFileList: 871 InputSection.append(InputFile) 872 SectionAlignments.append(Rule.SectAlignment) 873 874 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('): 875 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid) 876 if len(PcdValue) == 0: 877 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \ 878 % (Rule.NameGuid)) 879 if PcdValue.startswith('{'): 880 PcdValue = GuidStructureByteArrayToGuidString(PcdValue) 881 RegistryGuidStr = PcdValue 882 if len(RegistryGuidStr) == 0: 883 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \ 884 % (Rule.NameGuid)) 885 self.ModuleGuid = RegistryGuidStr 886 887 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection, 888 FdfFvFileTypeToFileType[Rule.FvFileType], 889 self.ModuleGuid, Fixed=Rule.Fixed, 890 CheckSum=Rule.CheckSum, Align=Rule.Alignment, 891 SectionAlign=SectionAlignments, 892 MakefilePath=MakefilePath 893 ) 894 return FfsOutput 895 896 ## __GenComplexFileSection__() method 897 # 898 # Generate section by sections in Rule 899 # 900 # @param self The object pointer 901 # @param Rule The rule object used to generate section 902 # @param FvChildAddr Array of the inside FvImage base address 903 # @param FvParentAddr Parent Fv base address 904 # @retval string File name of the generated section file 905 # 906 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False): 907 if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE): 908 if Rule.KeepReloc is not None: 909 self.KeepRelocFromRule = Rule.KeepReloc 910 SectFiles = [] 911 SectAlignments = [] 912 Index = 1 913 HasGeneratedFlag = False 914 if self.PcdIsDriver == 'PEI_PCD_DRIVER': 915 if self.IsBinaryModule: 916 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw") 917 else: 918 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw") 919 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw") 920 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName, 921 [PcdExDbFileName], 922 "EFI_SECTION_RAW", 923 IsMakefile = IsMakefile 924 ) 925 SectFiles.append(PcdExDbSecName) 926 SectAlignments.append(None) 927 elif self.PcdIsDriver == 'DXE_PCD_DRIVER': 928 if self.IsBinaryModule: 929 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw") 930 else: 931 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw") 932 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw") 933 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName, 934 [PcdExDbFileName], 935 "EFI_SECTION_RAW", 936 IsMakefile = IsMakefile 937 ) 938 SectFiles.append(PcdExDbSecName) 939 SectAlignments.append(None) 940 for Sect in Rule.SectionList: 941 SecIndex = '%d' %Index 942 SectList = [] 943 # 944 # Convert Fv Section Type for PI1.1 SMM driver. 945 # 946 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A: 947 if Sect.SectionType == BINARY_FILE_TYPE_DXE_DEPEX: 948 Sect.SectionType = BINARY_FILE_TYPE_SMM_DEPEX 949 # 950 # Framework SMM Driver has no SMM_DEPEX section type 951 # 952 if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A: 953 if Sect.SectionType == BINARY_FILE_TYPE_SMM_DEPEX: 954 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName) 955 # 956 # process the inside FvImage from FvSection or GuidSection 957 # 958 if FvChildAddr != []: 959 if isinstance(Sect, FvImageSection): 960 Sect.FvAddr = FvChildAddr.pop(0) 961 elif isinstance(Sect, GuidSection): 962 Sect.FvAddr = FvChildAddr 963 if FvParentAddr is not None and isinstance(Sect, GuidSection): 964 Sect.FvParentAddr = FvParentAddr 965 966 if Rule.KeyStringList != []: 967 SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile) 968 else : 969 SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile) 970 971 if not HasGeneratedFlag: 972 UniVfrOffsetFileSection = "" 973 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName) 974 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch] 975 # 976 # Search the source list in InfData to find if there are .vfr file exist. 977 # 978 VfrUniBaseName = {} 979 VfrUniOffsetList = [] 980 for SourceFile in InfData.Sources: 981 if SourceFile.Type.upper() == ".VFR" : 982 # 983 # search the .map file to find the offset of vfr binary in the PE32+/TE file. 984 # 985 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin") 986 if SourceFile.Type.upper() == ".UNI" : 987 # 988 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. 989 # 990 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings") 991 992 993 if len(VfrUniBaseName) > 0: 994 if IsMakefile: 995 if InfData.BuildType != 'UEFI_HII': 996 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset') 997 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw') 998 UniVfrOffsetFileNameList = [] 999 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName) 1000 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath) 1001 GenFdsGlobalVariable.SecCmdList.append(TrimCmd) 1002 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection, 1003 [UniVfrOffsetFileName], 1004 "EFI_SECTION_RAW", 1005 IsMakefile = True 1006 ) 1007 else: 1008 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName) 1009 # 1010 # Generate the Raw data of raw section 1011 # 1012 if VfrUniOffsetList: 1013 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset') 1014 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw') 1015 FfsInfStatement.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName) 1016 UniVfrOffsetFileNameList = [] 1017 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName) 1018 """Call GenSection""" 1019 1020 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection, 1021 UniVfrOffsetFileNameList, 1022 "EFI_SECTION_RAW" 1023 ) 1024 #os.remove(UniVfrOffsetFileName) 1025 if UniVfrOffsetFileSection: 1026 SectList.append(UniVfrOffsetFileSection) 1027 HasGeneratedFlag = True 1028 1029 for SecName in SectList : 1030 SectFiles.append(SecName) 1031 SectAlignments.append(Align) 1032 Index = Index + 1 1033 return SectFiles, SectAlignments 1034 1035 ## __GenComplexFileFfs__() method 1036 # 1037 # Generate FFS 1038 # 1039 # @param self The object pointer 1040 # @param Rule The rule object used to generate section 1041 # @param InputFileList The output file list from GenSection 1042 # @retval string Generated FFS file name 1043 # 1044 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None): 1045 1046 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('): 1047 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid) 1048 if len(PcdValue) == 0: 1049 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \ 1050 % (Rule.NameGuid)) 1051 if PcdValue.startswith('{'): 1052 PcdValue = GuidStructureByteArrayToGuidString(PcdValue) 1053 RegistryGuidStr = PcdValue 1054 if len(RegistryGuidStr) == 0: 1055 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \ 1056 % (Rule.NameGuid)) 1057 self.ModuleGuid = RegistryGuidStr 1058 1059 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs') 1060 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile, 1061 FdfFvFileTypeToFileType[Rule.FvFileType], 1062 self.ModuleGuid, Fixed=Rule.Fixed, 1063 CheckSum=Rule.CheckSum, Align=Rule.Alignment, 1064 SectionAlign=Alignments, 1065 MakefilePath=MakefilePath 1066 ) 1067 return FfsOutput 1068 1069 ## __GetBuildOutputMapFileVfrUniInfo() method 1070 # 1071 # Find the offset of UNI/INF object offset in the EFI image file. 1072 # 1073 # @param self The object pointer 1074 # @param VfrUniBaseName A name list contain the UNI/INF object name. 1075 # @retval RetValue A list contain offset of UNI/INF object. 1076 # 1077 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName): 1078 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map") 1079 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi") 1080 return GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values())) 1081 1082 ## __GenUniVfrOffsetFile() method 1083 # 1084 # Generate the offset file for the module which contain VFR or UNI file. 1085 # 1086 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file. 1087 # @param UniVfrOffsetFileName The output offset file name. 1088 # 1089 @staticmethod 1090 def __GenUniVfrOffsetFile(VfrUniOffsetList, UniVfrOffsetFileName): 1091 1092 # Use a instance of StringIO to cache data 1093 fStringIO = BytesIO() 1094 1095 for Item in VfrUniOffsetList: 1096 if (Item[0].find("Strings") != -1): 1097 # 1098 # UNI offset in image. 1099 # GUID + Offset 1100 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } } 1101 # 1102 UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f' 1103 fStringIO.write(UniGuid) 1104 UniValue = pack ('Q', int (Item[1], 16)) 1105 fStringIO.write (UniValue) 1106 else: 1107 # 1108 # VFR binary offset in image. 1109 # GUID + Offset 1110 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }; 1111 # 1112 VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2' 1113 fStringIO.write(VfrGuid) 1114 type (Item[1]) 1115 VfrValue = pack ('Q', int (Item[1], 16)) 1116 fStringIO.write (VfrValue) 1117 1118 # 1119 # write data into file. 1120 # 1121 try : 1122 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue()) 1123 except: 1124 EdkLogger.error("GenFds", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %UniVfrOffsetFileName, None) 1125 1126 fStringIO.close () 1127 1128 1129