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