]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FfsInfStatement.py
4b4781755dd41fb0199199a8e73109f5a93b0bde
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
1 ## @file
2 # process FFS generation from INF statement
3 #
4 # Copyright (c) 2007 - 2017, 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 import Rule
20 import Common.LongFilePathOs as os
21 import StringIO
22 from struct import *
23 from GenFdsGlobalVariable import GenFdsGlobalVariable
24 import Ffs
25 import subprocess
26 import sys
27 import Section
28 import RuleSimpleFile
29 import RuleComplexFile
30 from CommonDataClass.FdfClass import FfsInfStatementClassObject
31 from Common.MultipleWorkspace import MultipleWorkspace as mws
32 from Common.String 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
50 ## generate FFS from INF
51 #
52 #
53 class FfsInfStatement(FfsInfStatementClassObject):
54 ## The mapping dictionary from datum type to its maximum number.
55 _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}
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 != "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 != 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 != 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 == None and Inf.Shadow:
204 self.ShadowFromInfFile = Inf.Shadow
205
206 else:
207 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
208 self.BaseName = Inf.BaseName
209 self.ModuleGuid = Inf.Guid
210 self.ModuleType = Inf.ModuleType
211 if Inf.Specification != 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 == '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 == '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 != 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
241 # Workaround here: both build and GenFds tool convert the workspace path to lower case
242 # But INF file path in FDF and DSC file may have real case characters.
243 # Try to convert the path to lower case to see if PCDs value are override by DSC.
244 DscModules = {}
245 for DscModule in Platform.Modules:
246 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]
247 for PcdKey in InfPcds:
248 Pcd = InfPcds[PcdKey]
249 if not hasattr(Pcd, 'Offset'):
250 continue
251 if Pcd.Type != 'PatchableInModule':
252 continue
253 # Override Patchable PCD value by the value from DSC
254 PatchPcd = None
255 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:
256 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]
257 elif PcdKey in Platform.Pcds:
258 PatchPcd = Platform.Pcds[PcdKey]
259 DscOverride = False
260 if PatchPcd and Pcd.Type == PatchPcd.Type:
261 DefaultValue = PatchPcd.DefaultValue
262 DscOverride = True
263
264 # Override Patchable PCD value by the value from FDF
265 FdfOverride = False
266 if PcdKey in FdfPcdDict:
267 DefaultValue = FdfPcdDict[PcdKey]
268 FdfOverride = True
269
270 # Override Patchable PCD value by the value from Build Option
271 BuildOptionOverride = False
272 if GlobalData.BuildOptionPcd:
273 for pcd in GlobalData.BuildOptionPcd:
274 if PcdKey == (pcd[1], pcd[0]):
275 DefaultValue = pcd[2]
276 BuildOptionOverride = True
277 break
278
279 if not DscOverride and not FdfOverride and not BuildOptionOverride:
280 continue
281 # Check value, if value are equal, no need to patch
282 if Pcd.DatumType == "VOID*":
283 if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']:
284 continue
285 # Get the string size from FDF or DSC
286 if DefaultValue[0] == 'L':
287 # Remove L"", but the '\0' must be appended
288 MaxDatumSize = str((len(DefaultValue) - 2) * 2)
289 elif DefaultValue[0] == '{':
290 MaxDatumSize = str(len(DefaultValue.split(',')))
291 else:
292 MaxDatumSize = str(len(DefaultValue) - 1)
293 if DscOverride:
294 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize
295 # If no defined the maximum size in DSC, try to get current size from INF
296 if Pcd.MaxDatumSize in ['', None]:
297 Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(',')))
298 else:
299 Base1 = Base2 = 10
300 if Pcd.DefaultValue.upper().startswith('0X'):
301 Base1 = 16
302 if DefaultValue.upper().startswith('0X'):
303 Base2 = 16
304 try:
305 PcdValueInImg = int(Pcd.DefaultValue, Base1)
306 PcdValueInDscOrFdf = int(DefaultValue, Base2)
307 if PcdValueInImg == PcdValueInDscOrFdf:
308 continue
309 except:
310 continue
311 # Check the Pcd size and data type
312 if Pcd.DatumType == "VOID*":
313 if int(MaxDatumSize) > int(Pcd.MaxDatumSize):
314 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
315 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))
316 else:
317 if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \
318 or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:
319 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \
320 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
321 self.PatchPcds.append((Pcd, DefaultValue))
322
323 self.InfModule = Inf
324 self.PcdIsDriver = Inf.PcdIsDriver
325 self.IsBinaryModule = Inf.IsBinaryModule
326 Inf._GetDepex()
327 Inf._GetDepexExpression()
328 if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:
329 self.Depex = True
330
331 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)
332 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)
333 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)
334 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)
335 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)
336
337 #
338 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
339 #
340
341 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
342 self.ModuleGuid + self.BaseName)
343 if not os.path.exists(self.OutputPath) :
344 os.makedirs(self.OutputPath)
345
346 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()
347 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)
348
349 ## PatchEfiFile
350 #
351 # Patch EFI file with patch PCD
352 #
353 # @param EfiFile: EFI file needs to be patched.
354 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
355 # If passed in file does not end with efi, return as is
356 #
357 def PatchEfiFile(self, EfiFile, FileType):
358 #
359 # If the module does not have any patches, then return path to input file
360 #
361 if not self.PatchPcds:
362 return EfiFile
363
364 #
365 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
366 #
367 if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":
368 return EfiFile
369
370 #
371 # Generate path to patched output file
372 #
373 Basename = os.path.basename(EfiFile)
374 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))
375
376 #
377 # If this file has already been patched, then return the path to the patched file
378 #
379 if self.PatchedBinFile == Output:
380 return Output
381
382 #
383 # If a different file from the same module has already been patched, then generate an error
384 #
385 if self.PatchedBinFile:
386 EdkLogger.error("GenFds", GENFDS_ERROR,
387 'Only one binary file can be patched:\n'
388 ' a binary file has been patched: %s\n'
389 ' current file: %s' % (self.PatchedBinFile, EfiFile),
390 File=self.InfFileName)
391
392 #
393 # Copy unpatched file contents to output file location to perform patching
394 #
395 CopyLongFilePath(EfiFile, Output)
396
397 #
398 # Apply patches to patched output file
399 #
400 for Pcd, Value in self.PatchPcds:
401 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
402 if RetVal:
403 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)
404
405 #
406 # Save the path of the patched output file
407 #
408 self.PatchedBinFile = Output
409
410 #
411 # Return path to patched output file
412 #
413 return Output
414
415 ## GenFfs() method
416 #
417 # Generate FFS
418 #
419 # @param self The object pointer
420 # @param Dict dictionary contains macro and value pair
421 # @param FvChildAddr Array of the inside FvImage base address
422 # @param FvParentAddr Parent Fv base address
423 # @retval string Generated FFS file name
424 #
425 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False):
426 #
427 # Parse Inf file get Module related information
428 #
429
430 self.__InfParse__(Dict)
431 Arch = self.GetCurrentArch()
432 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);
433 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
434
435 SrcFileDir = "."
436 SrcPath = os.path.dirname(SrcFile)
437 SrcFileName = os.path.basename(SrcFile)
438 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)
439 DestPath = os.path.dirname(DestFile)
440 DestFileName = os.path.basename(DestFile)
441 DestFileBase, DestFileExt = os.path.splitext(DestFileName)
442 self.MacroDict = {
443 # source file
444 "${src}" : SrcFile,
445 "${s_path}" : SrcPath,
446 "${s_dir}" : SrcFileDir,
447 "${s_name}" : SrcFileName,
448 "${s_base}" : SrcFileBase,
449 "${s_ext}" : SrcFileExt,
450 # destination file
451 "${dst}" : DestFile,
452 "${d_path}" : DestPath,
453 "${d_name}" : DestFileName,
454 "${d_base}" : DestFileBase,
455 "${d_ext}" : DestFileExt
456 }
457 #
458 # Allow binary type module not specify override rule in FDF file.
459 #
460 if len(self.BinFileList) > 0:
461 if self.Rule == None or self.Rule == "":
462 self.Rule = "BINARY"
463
464 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':
465 IsMakefile = True
466 #
467 # Get the rule of how to generate Ffs file
468 #
469 Rule = self.__GetRule__()
470 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
471 #
472 # Convert Fv File Type for PI1.1 SMM driver.
473 #
474 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
475 if Rule.FvFileType == 'DRIVER':
476 Rule.FvFileType = 'SMM'
477 #
478 # Framework SMM Driver has no SMM FV file type
479 #
480 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
481 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':
482 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
483 #
484 # For the rule only has simpleFile
485 #
486 MakefilePath = None
487 if IsMakefile:
488 MakefilePath = self.InfFileName, Arch
489 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :
490 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)
491 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)
492 return FfsOutput
493 #
494 # For Rule has ComplexFile
495 #
496 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
497 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)
498 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)
499 return FfsOutput
500
501 ## __ExtendMacro__() method
502 #
503 # Replace macro with its value
504 #
505 # @param self The object pointer
506 # @param String The string to be replaced
507 # @retval string Macro replaced string
508 #
509 def __ExtendMacro__ (self, String):
510 MacroDict = {
511 '$(INF_OUTPUT)' : self.EfiOutputPath,
512 '$(MODULE_NAME)' : self.BaseName,
513 '$(BUILD_NUMBER)': self.BuildNum,
514 '$(INF_VERSION)' : self.VersionString,
515 '$(NAMED_GUID)' : self.ModuleGuid
516 }
517 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
518 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)
519 return String
520
521 ## __GetRule__() method
522 #
523 # Get correct rule for generating FFS for this INF
524 #
525 # @param self The object pointer
526 # @retval Rule Rule object
527 #
528 def __GetRule__ (self) :
529 CurrentArchList = []
530 if self.CurrentArch == None:
531 CurrentArchList = ['common']
532 else:
533 CurrentArchList.append(self.CurrentArch)
534
535 for CurrentArch in CurrentArchList:
536 RuleName = 'RULE' + \
537 '.' + \
538 CurrentArch.upper() + \
539 '.' + \
540 self.ModuleType.upper()
541 if self.Rule != None:
542 RuleName = RuleName + \
543 '.' + \
544 self.Rule.upper()
545
546 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
547 if Rule != None:
548 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
549 return Rule
550
551 RuleName = 'RULE' + \
552 '.' + \
553 'COMMON' + \
554 '.' + \
555 self.ModuleType.upper()
556
557 if self.Rule != None:
558 RuleName = RuleName + \
559 '.' + \
560 self.Rule.upper()
561
562 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
563
564 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
565 if Rule != None:
566 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
567 return Rule
568
569 if Rule == None :
570 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
571 % (RuleName, self.InfFileName))
572
573 ## __GetPlatformArchList__() method
574 #
575 # Get Arch list this INF built under
576 #
577 # @param self The object pointer
578 # @retval list Arch list
579 #
580 def __GetPlatformArchList__(self):
581
582 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
583 DscArchList = []
584 for Arch in GenFdsGlobalVariable.ArchList :
585 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
586 if PlatformDataBase != None:
587 if InfFileKey in PlatformDataBase.Modules:
588 DscArchList.append (Arch)
589 else:
590 #
591 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has
592 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,
593 # but the path (self.MetaFile.Path) is the real path
594 #
595 for key in PlatformDataBase.Modules.keys():
596 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):
597 DscArchList.append (Arch)
598 break
599
600 return DscArchList
601
602 ## GetCurrentArch() method
603 #
604 # Get Arch list of the module from this INF is to be placed into flash
605 #
606 # @param self The object pointer
607 # @retval list Arch list
608 #
609 def GetCurrentArch(self) :
610
611 TargetArchList = GenFdsGlobalVariable.ArchList
612
613 PlatformArchList = self.__GetPlatformArchList__()
614
615 CurArchList = TargetArchList
616 if PlatformArchList != []:
617 CurArchList = list(set (TargetArchList) & set (PlatformArchList))
618 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
619
620 ArchList = []
621 if self.KeyStringList != []:
622 for Key in self.KeyStringList:
623 Key = GenFdsGlobalVariable.MacroExtend(Key)
624 Target, Tag, Arch = Key.split('_')
625 if Arch in CurArchList:
626 ArchList.append(Arch)
627 if Target not in self.TargetOverrideList:
628 self.TargetOverrideList.append(Target)
629 else:
630 ArchList = CurArchList
631
632 UseArchList = TargetArchList
633 if self.UseArch != None:
634 UseArchList = []
635 UseArchList.append(self.UseArch)
636 ArchList = list(set (UseArchList) & set (ArchList))
637
638 self.InfFileName = NormPath(self.InfFileName)
639 if len(PlatformArchList) == 0:
640 self.InDsc = False
641 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
642 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
643 if ErrorCode != 0:
644 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
645 if len(ArchList) == 1:
646 Arch = ArchList[0]
647 return Arch
648 elif len(ArchList) > 1:
649 if len(PlatformArchList) == 0:
650 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))
651 else:
652 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))
653 else:
654 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." \
655 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
656
657 ## __GetEFIOutPutPath__() method
658 #
659 # Get the output path for generated files
660 #
661 # @param self The object pointer
662 # @retval string Path that output files from this INF go to
663 #
664 def __GetEFIOutPutPath__(self):
665 Arch = ''
666 OutputPath = ''
667 DebugPath = ''
668 (ModulePath, FileName) = os.path.split(self.InfFileName)
669 Index = FileName.rfind('.')
670 FileName = FileName[0:Index]
671 if self.OverrideGuid:
672 FileName = self.OverrideGuid
673 Arch = "NoneArch"
674 if self.CurrentArch != None:
675 Arch = self.CurrentArch
676
677 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
678 Arch ,
679 ModulePath,
680 FileName,
681 'OUTPUT'
682 )
683 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
684 Arch ,
685 ModulePath,
686 FileName,
687 'DEBUG'
688 )
689 OutputPath = os.path.realpath(OutputPath)
690 DebugPath = os.path.realpath(DebugPath)
691 return OutputPath, DebugPath
692
693 ## __GenSimpleFileSection__() method
694 #
695 # Generate section by specified file name or a list of files with file extension
696 #
697 # @param self The object pointer
698 # @param Rule The rule object used to generate section
699 # @retval string File name of the generated section file
700 #
701 def __GenSimpleFileSection__(self, Rule, IsMakefile = False):
702 #
703 # Prepare the parameter of GenSection
704 #
705 FileList = []
706 OutputFileList = []
707 GenSecInputFile = None
708 if Rule.FileName != None:
709 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
710 if os.path.isabs(GenSecInputFile):
711 GenSecInputFile = os.path.normpath(GenSecInputFile)
712 else:
713 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
714 else:
715 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
716
717 Index = 1
718 SectionType = Rule.SectionType
719 #
720 # Convert Fv Section Type for PI1.1 SMM driver.
721 #
722 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
723 if SectionType == 'DXE_DEPEX':
724 SectionType = 'SMM_DEPEX'
725 #
726 # Framework SMM Driver has no SMM_DEPEX section type
727 #
728 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
729 if SectionType == 'SMM_DEPEX':
730 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
731 NoStrip = True
732 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
733 if self.KeepReloc != None:
734 NoStrip = self.KeepReloc
735 elif Rule.KeepReloc != None:
736 NoStrip = Rule.KeepReloc
737 elif self.ShadowFromInfFile != None:
738 NoStrip = self.ShadowFromInfFile
739
740 if FileList != [] :
741 for File in FileList:
742
743 SecNum = '%d' %Index
744 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
745 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
746 Index = Index + 1
747 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
748 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
749
750 #Get PE Section alignment when align is set to AUTO
751 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
752 ImageObj = PeImageClass (File)
753 if ImageObj.SectionAlignment < 0x400:
754 self.Alignment = str (ImageObj.SectionAlignment)
755 elif ImageObj.SectionAlignment < 0x100000:
756 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
757 else:
758 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'
759
760 if not NoStrip:
761 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
762 if not os.path.exists(FileBeforeStrip) or \
763 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
764 CopyLongFilePath(File, FileBeforeStrip)
765 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
766 GenFdsGlobalVariable.GenerateFirmwareImage(
767 StrippedFile,
768 [File],
769 Strip=True,
770 IsMakefile=IsMakefile
771 )
772 File = StrippedFile
773
774 if SectionType == 'TE':
775 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
776 GenFdsGlobalVariable.GenerateFirmwareImage(
777 TeFile,
778 [File],
779 Type='te',
780 IsMakefile=IsMakefile
781 )
782 File = TeFile
783 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
784 OutputFileList.append(OutputFile)
785 else:
786 SecNum = '%d' %Index
787 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
788 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum
789 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
790 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
791
792 #Get PE Section alignment when align is set to AUTO
793 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):
794 ImageObj = PeImageClass (GenSecInputFile)
795 if ImageObj.SectionAlignment < 0x400:
796 self.Alignment = str (ImageObj.SectionAlignment)
797 elif ImageObj.SectionAlignment < 0x100000:
798 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'
799 else:
800 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'
801
802 if not NoStrip:
803 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
804 if not os.path.exists(FileBeforeStrip) or \
805 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
806 CopyLongFilePath(GenSecInputFile, FileBeforeStrip)
807
808 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
809 GenFdsGlobalVariable.GenerateFirmwareImage(
810 StrippedFile,
811 [GenSecInputFile],
812 Strip=True,
813 IsMakefile=IsMakefile
814 )
815 GenSecInputFile = StrippedFile
816
817 if SectionType == 'TE':
818 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
819 GenFdsGlobalVariable.GenerateFirmwareImage(
820 TeFile,
821 [GenSecInputFile],
822 Type='te',
823 IsMakefile=IsMakefile
824 )
825 GenSecInputFile = TeFile
826 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
827 OutputFileList.append(OutputFile)
828
829 return OutputFileList
830
831 ## __GenSimpleFileFfs__() method
832 #
833 # Generate FFS
834 #
835 # @param self The object pointer
836 # @param Rule The rule object used to generate section
837 # @param InputFileList The output file list from GenSection
838 # @retval string Generated FFS file name
839 #
840 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):
841 FfsOutput = self.OutputPath + \
842 os.sep + \
843 self.__ExtendMacro__(Rule.NameGuid) + \
844 '.ffs'
845
846 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
847 InputSection = []
848 SectionAlignments = []
849 for InputFile in InputFileList:
850 InputSection.append(InputFile)
851 SectionAlignments.append(Rule.SectAlignment)
852
853 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
854 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
855 if len(PcdValue) == 0:
856 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
857 % (Rule.NameGuid))
858 if PcdValue.startswith('{'):
859 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
860 RegistryGuidStr = PcdValue
861 if len(RegistryGuidStr) == 0:
862 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
863 % (Rule.NameGuid))
864 self.ModuleGuid = RegistryGuidStr
865
866 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
867 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
868 self.ModuleGuid, Fixed=Rule.Fixed,
869 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
870 SectionAlign=SectionAlignments,
871 MakefilePath=MakefilePath
872 )
873 return FfsOutput
874
875 ## __GenComplexFileSection__() method
876 #
877 # Generate section by sections in Rule
878 #
879 # @param self The object pointer
880 # @param Rule The rule object used to generate section
881 # @param FvChildAddr Array of the inside FvImage base address
882 # @param FvParentAddr Parent Fv base address
883 # @retval string File name of the generated section file
884 #
885 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):
886 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):
887 if Rule.KeepReloc != None:
888 self.KeepRelocFromRule = Rule.KeepReloc
889 SectFiles = []
890 SectAlignments = []
891 Index = 1
892 HasGeneratedFlag = False
893 if self.PcdIsDriver == 'PEI_PCD_DRIVER':
894 if self.IsBinaryModule:
895 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")
896 else:
897 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")
898 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")
899 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
900 [PcdExDbFileName],
901 "EFI_SECTION_RAW",
902 IsMakefile = IsMakefile
903 )
904 SectFiles.append(PcdExDbSecName)
905 SectAlignments.append(None)
906 elif self.PcdIsDriver == 'DXE_PCD_DRIVER':
907 if self.IsBinaryModule:
908 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")
909 else:
910 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")
911 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")
912 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
913 [PcdExDbFileName],
914 "EFI_SECTION_RAW",
915 IsMakefile = IsMakefile
916 )
917 SectFiles.append(PcdExDbSecName)
918 SectAlignments.append(None)
919 for Sect in Rule.SectionList:
920 SecIndex = '%d' %Index
921 SectList = []
922 #
923 # Convert Fv Section Type for PI1.1 SMM driver.
924 #
925 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:
926 if Sect.SectionType == 'DXE_DEPEX':
927 Sect.SectionType = 'SMM_DEPEX'
928 #
929 # Framework SMM Driver has no SMM_DEPEX section type
930 #
931 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:
932 if Sect.SectionType == 'SMM_DEPEX':
933 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
934 #
935 # process the inside FvImage from FvSection or GuidSection
936 #
937 if FvChildAddr != []:
938 if isinstance(Sect, FvImageSection):
939 Sect.FvAddr = FvChildAddr.pop(0)
940 elif isinstance(Sect, GuidSection):
941 Sect.FvAddr = FvChildAddr
942 if FvParentAddr != None and isinstance(Sect, GuidSection):
943 Sect.FvParentAddr = FvParentAddr
944
945 if Rule.KeyStringList != []:
946 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)
947 else :
948 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)
949
950 if not HasGeneratedFlag:
951 UniVfrOffsetFileSection = ""
952 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
953 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
954 #
955 # Search the source list in InfData to find if there are .vfr file exist.
956 #
957 VfrUniBaseName = {}
958 VfrUniOffsetList = []
959 for SourceFile in InfData.Sources:
960 if SourceFile.Type.upper() == ".VFR" :
961 #
962 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
963 #
964 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
965 if SourceFile.Type.upper() == ".UNI" :
966 #
967 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
968 #
969 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
970
971
972 if len(VfrUniBaseName) > 0:
973 if IsMakefile:
974 if InfData.BuildType != 'UEFI_HII':
975 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
976 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
977 UniVfrOffsetFileNameList = []
978 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
979 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)
980 GenFdsGlobalVariable.SecCmdList.append(TrimCmd)
981 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
982 [UniVfrOffsetFileName],
983 "EFI_SECTION_RAW",
984 IsMakefile = True
985 )
986 else:
987 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
988 #
989 # Generate the Raw data of raw section
990 #
991 if VfrUniOffsetList:
992 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
993 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
994 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
995 UniVfrOffsetFileNameList = []
996 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
997 """Call GenSection"""
998
999 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
1000 UniVfrOffsetFileNameList,
1001 "EFI_SECTION_RAW"
1002 )
1003 #os.remove(UniVfrOffsetFileName)
1004 if UniVfrOffsetFileSection:
1005 SectList.append(UniVfrOffsetFileSection)
1006 HasGeneratedFlag = True
1007
1008 for SecName in SectList :
1009 SectFiles.append(SecName)
1010 SectAlignments.append(Align)
1011 Index = Index + 1
1012 return SectFiles, SectAlignments
1013
1014 ## __GenComplexFileFfs__() method
1015 #
1016 # Generate FFS
1017 #
1018 # @param self The object pointer
1019 # @param Rule The rule object used to generate section
1020 # @param InputFileList The output file list from GenSection
1021 # @retval string Generated FFS file name
1022 #
1023 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):
1024
1025 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):
1026 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
1027 if len(PcdValue) == 0:
1028 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
1029 % (Rule.NameGuid))
1030 if PcdValue.startswith('{'):
1031 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
1032 RegistryGuidStr = PcdValue
1033 if len(RegistryGuidStr) == 0:
1034 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
1035 % (Rule.NameGuid))
1036 self.ModuleGuid = RegistryGuidStr
1037
1038 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
1039 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
1040 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],
1041 self.ModuleGuid, Fixed=Rule.Fixed,
1042 CheckSum=Rule.CheckSum, Align=Rule.Alignment,
1043 SectionAlign=Alignments,
1044 MakefilePath=MakefilePath
1045 )
1046 return FfsOutput
1047
1048 ## __GetGenFfsCmdParameter__() method
1049 #
1050 # Create parameter string for GenFfs
1051 #
1052 # @param self The object pointer
1053 # @param Rule The rule object used to generate section
1054 # @retval tuple (FileType, Fixed, CheckSum, Alignment)
1055 #
1056 def __GetGenFfsCmdParameter__(self, Rule):
1057 result = tuple()
1058 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])
1059 if Rule.Fixed != False:
1060 result += ('-x',)
1061 if Rule.CheckSum != False:
1062 result += ('-s',)
1063
1064 if Rule.Alignment != None and Rule.Alignment != '':
1065 result += ('-a', Rule.Alignment)
1066
1067 return result
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, VfrUniBaseName.values())
1081
1082 ## __GenUniVfrOffsetFile() method
1083 #
1084 # Generate the offset file for the module which contain VFR or UNI file.
1085 #
1086 # @param self The object pointer
1087 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
1088 # @param UniVfrOffsetFileName The output offset file name.
1089 #
1090 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):
1091
1092 # Use a instance of StringIO to cache data
1093 fStringIO = StringIO.StringIO('')
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 = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
1103 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
1104 fStringIO.write(''.join(UniGuid))
1105 UniValue = pack ('Q', int (Item[1], 16))
1106 fStringIO.write (UniValue)
1107 else:
1108 #
1109 # VFR binary offset in image.
1110 # GUID + Offset
1111 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
1112 #
1113 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
1114 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
1115 fStringIO.write(''.join(VfrGuid))
1116 type (Item[1])
1117 VfrValue = pack ('Q', int (Item[1], 16))
1118 fStringIO.write (VfrValue)
1119
1120 #
1121 # write data into file.
1122 #
1123 try :
1124 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())
1125 except:
1126 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)
1127
1128 fStringIO.close ()
1129
1130